openvibers/openvibe.locker Commits
Document the blind fill flow (#10)
Changes
@@@ -1,43 +1,45 @@--# Blind fill (phase 2 design only)++# Blind fill--Blind fill lets a person approve a sign-in in a trusted Locker UI while a Computer session operates a browser. It waits--for Run's control lease and is not implemented by Locker's password manager.++Blind fill lets an agent request a sign-in for the browser in its OpenVibe.Run session. The person approves in the++Companion extension, which reads one saved Locker login, seals the selected fields to the target machine's Link Send++public key, and sends only that envelope to Run. The agent receives only `{ ok, reason }`.## Flow--1. A Computer asks for a saved login by exact origin. It receives only a request id, origin, and the site title; it-- never receives a login, password, TOTP seed, or decrypted Locker item.--2. Run pauses the Computer browser under its control lease and sends a B2 approval request to the person's trusted-- device. The trusted device displays the Computer, exact origin, requested account label, and the requested fields.--3. The person approves or denies. Approval unlocks the selected login in the trusted device's extension and creates a-- short-lived, single-use fill grant scoped to that exact origin and those fields.--4. Link/Run delivers the grant to the Companion extension through its authenticated channel. The extension checks the-- active tab origin and frame origin again, fills only the approved fields in the top-level page, and submits only if-- the person approved submission. It never fills a cross-origin iframe.--5. The extension discards plaintext and grant state after use or timeout, and locks after 15 minutes idle. The agent-- tool `locker_fill_login` returns only a success/failure result; it never returns field values or secrets.++1. The session controller calls `POST /api/v1/sessions/:id/fill-requests` with an origin. Run reads the active tab's++ top-level origin from the machine and requires an exact scheme, host, and port match. Run accepts only a machine the++ person owns or OpenVibe's own pool, pauses the agent's control lease, and expires the request after two minutes.++2. Run notifies the person with an **Approve a sign-in** action. Companion lists the person's pending requests with++ the agent, computer, exact origin, and fields that will be typed. Companion uses the `run.fill.approve` Dock scope.++3. The person unlocks Locker in Companion, selects a login for that exact origin, and approves username, password, an++ optional TOTP code computed locally, and whether to submit. Companion shows the machine's Link Send key thumbprint.++ It seals `{ request_id, origin, username, password, code?, submit, exp }` for that machine; the grant expires in++ sixty seconds. Only the envelope is posted to Run, and each request can be granted once.++4. Run sends the envelope over its existing machine control channel. Node opens it with its Link Send private key and++ checks request id, expiry, and exact origin. Origins must be HTTPS and match exactly, including host and port; HTTP++ pages are refused at request and fill time. Node checks the active CDP top-level frame origin again, creates a CDP++ isolated world for that frame with universal access disabled, and evaluates the fill script there. The script checks++ `location.origin` again, fills visible inputs in the top-level document only, and submits only when approved. Iframe++ inputs are never searched. Node retains used request ids for two minutes and returns `reused` on replay. Node reports++ `ok` or `failed`; Run resumes the agent after navigation or five seconds.++5. Run refuses screenshots and page text while approval or fill is active and until the next navigation. Fill audit++ records contain request id, origin, decision, outcome, and times only.--## Required controls++## Security requirements--- The password manager extension unlocks Locker locally with the same passphrase, passkey, or recovery-kit flow.--- A saved login is eligible only when its stored origin exactly matches the requested origin or the person explicitly-- added that second origin. No wildcard domains, redirects, subdomains, or cross-origin frames inherit access.--- Approval names the target Computer, origin, account label, and fields. Each fill needs a fresh approval; approval-- cannot be replayed, transferred to another tab, or used after its short expiry.--- The browser integration must bind its grant to the active tab and top-level frame, verify the origin immediately-- before input, and abort if navigation or focus changes.--- The Locker server, Run, Link, MCP response, and agent context receive no plaintext. The extension is the only-- component that decrypts and types the selected fields.--- Audit records contain request id, origin, decision, and time only. Do not record field contents, credential ids,-- TOTP codes, page HTML, or screenshots containing secrets.--- TOTP remains locally computed. If a site needs an OTP, show that as a separately approved field in the trusted-- prompt; never expose it to the agent.++- The agent never receives a login, password, TOTP seed or code, decrypted item, envelope, page HTML, or screenshot++ captured during the protected interval.++- Requests require the agent to hold the session control lease. Partner, community, and external machines cannot fill.++- The requested origin and the machine's current top-level origin must match exactly at request and fill time. A++ cross-origin iframe is never eligible.++- Grants are encrypted to the chosen machine, expire after sixty seconds, and are single-use. Mutable plaintext buffers++ are cleared after the machine hands the fields to its local browser plugin. Python strings are immutable and cannot++ be overwritten; the plugin drops its plaintext local references as soon as the call returns.++- Audit data contains no field contents, credential ids, codes, page HTML, or screenshots.++- `locker_fill_login(origin)` returns only `{ ok, reason }`.--## Open decisions before implementation++## Verification--- Run's control lease must provide a race-free pause/resume and identify the exact browser tab and navigation epoch.--- Link needs an authenticated, single-use channel between the trusted extension and the Companion running in the-- Computer browser.--- The B2 request contract must support origin and field scopes without allowing an agent to impersonate the trusted-- prompt.--- Product review must confirm the approval copy, timeout, recovery behavior, and extension permission model.++The implementation tests origin mismatch at request and fill, expiry and replay, owner/pool eligibility, refusal of++community machines, response secrecy, screenshot withholding, iframe refusal, and cross-language Locker envelope++vectors generated by the JavaScript SDK.
@@ -1,43 +1,45 @@
@@ -1,43 +1,45 @@
-# Blind fill (phase 2 design only)
+# Blind fill
-Blind fill lets a person approve a sign-in in a trusted Locker UI while a Computer session operates a browser. It waits
-for Run's control lease and is not implemented by Locker's password manager.
+Blind fill lets an agent request a sign-in for the browser in its OpenVibe.Run session. The person approves in the
+Companion extension, which reads one saved Locker login, seals the selected fields to the target machine's Link Send
+public key, and sends only that envelope to Run. The agent receives only `{ ok, reason }`.
## Flow
## Flow
-1. A Computer asks for a saved login by exact origin. It receives only a request id, origin, and the site title; it
- never receives a login, password, TOTP seed, or decrypted Locker item.
-2. Run pauses the Computer browser under its control lease and sends a B2 approval request to the person's trusted
- device. The trusted device displays the Computer, exact origin, requested account label, and the requested fields.
-3. The person approves or denies. Approval unlocks the selected login in the trusted device's extension and creates a
- short-lived, single-use fill grant scoped to that exact origin and those fields.
-4. Link/Run delivers the grant to the Companion extension through its authenticated channel. The extension checks the
- active tab origin and frame origin again, fills only the approved fields in the top-level page, and submits only if
- the person approved submission. It never fills a cross-origin iframe.
-5. The extension discards plaintext and grant state after use or timeout, and locks after 15 minutes idle. The agent
- tool `locker_fill_login` returns only a success/failure result; it never returns field values or secrets.
+1. The session controller calls `POST /api/v1/sessions/:id/fill-requests` with an origin. Run reads the active tab's
+ top-level origin from the machine and requires an exact scheme, host, and port match. Run accepts only a machine the
+ person owns or OpenVibe's own pool, pauses the agent's control lease, and expires the request after two minutes.
+2. Run notifies the person with an **Approve a sign-in** action. Companion lists the person's pending requests with
+ the agent, computer, exact origin, and fields that will be typed. Companion uses the `run.fill.approve` Dock scope.
+3. The person unlocks Locker in Companion, selects a login for that exact origin, and approves username, password, an
+ optional TOTP code computed locally, and whether to submit. Companion shows the machine's Link Send key thumbprint.
+ It seals `{ request_id, origin, username, password, code?, submit, exp }` for that machine; the grant expires in
+ sixty seconds. Only the envelope is posted to Run, and each request can be granted once.
+4. Run sends the envelope over its existing machine control channel. Node opens it with its Link Send private key and
+ checks request id, expiry, and exact origin. Origins must be HTTPS and match exactly, including host and port; HTTP
+ pages are refused at request and fill time. Node checks the active CDP top-level frame origin again, creates a CDP
+ isolated world for that frame with universal access disabled, and evaluates the fill script there. The script checks
+ `location.origin` again, fills visible inputs in the top-level document only, and submits only when approved. Iframe
+ inputs are never searched. Node retains used request ids for two minutes and returns `reused` on replay. Node reports
+ `ok` or `failed`; Run resumes the agent after navigation or five seconds.
+5. Run refuses screenshots and page text while approval or fill is active and until the next navigation. Fill audit
+ records contain request id, origin, decision, outcome, and times only.
-## Required controls
+## Security requirements
-- The password manager extension unlocks Locker locally with the same passphrase, passkey, or recovery-kit flow.
-- A saved login is eligible only when its stored origin exactly matches the requested origin or the person explicitly
- added that second origin. No wildcard domains, redirects, subdomains, or cross-origin frames inherit access.
-- Approval names the target Computer, origin, account label, and fields. Each fill needs a fresh approval; approval
- cannot be replayed, transferred to another tab, or used after its short expiry.
-- The browser integration must bind its grant to the active tab and top-level frame, verify the origin immediately
- before input, and abort if navigation or focus changes.
-- The Locker server, Run, Link, MCP response, and agent context receive no plaintext. The extension is the only
- component that decrypts and types the selected fields.
-- Audit records contain request id, origin, decision, and time only. Do not record field contents, credential ids,
- TOTP codes, page HTML, or screenshots containing secrets.
-- TOTP remains locally computed. If a site needs an OTP, show that as a separately approved field in the trusted
- prompt; never expose it to the agent.
+- The agent never receives a login, password, TOTP seed or code, decrypted item, envelope, page HTML, or screenshot
+ captured during the protected interval.
+- Requests require the agent to hold the session control lease. Partner, community, and external machines cannot fill.
+- The requested origin and the machine's current top-level origin must match exactly at request and fill time. A
+ cross-origin iframe is never eligible.
+- Grants are encrypted to the chosen machine, expire after sixty seconds, and are single-use. Mutable plaintext buffers
+ are cleared after the machine hands the fields to its local browser plugin. Python strings are immutable and cannot
+ be overwritten; the plugin drops its plaintext local references as soon as the call returns.
+- Audit data contains no field contents, credential ids, codes, page HTML, or screenshots.
+- `locker_fill_login(origin)` returns only `{ ok, reason }`.
-## Open decisions before implementation
+## Verification
-- Run's control lease must provide a race-free pause/resume and identify the exact browser tab and navigation epoch.
-- Link needs an authenticated, single-use channel between the trusted extension and the Companion running in the
- Computer browser.
-- The B2 request contract must support origin and field scopes without allowing an agent to impersonate the trusted
- prompt.
-- Product review must confirm the approval copy, timeout, recovery behavior, and extension permission model.
+The implementation tests origin mismatch at request and fill, expiry and replay, owner/pool eligibility, refusal of
+community machines, response secrecy, screenshot withholding, iframe refusal, and cross-language Locker envelope
+vectors generated by the JavaScript SDK.