Propose provider-owned Mail and Files Home launch
1 file changed,
+139
−0
implementation/external-home-launch.json+139 −0
diff --git a/implementation/external-home-launch.json b/implementation/external-home-launch.json| new file mode 100644 |
| index 0000000..ad245b2 |
| --- /dev/null |
| +++ b/implementation/external-home-launch.json |
| @@ -0,0 +1,139 @@ |
| +{ |
| + "proposal": "External Mail and Files launch with existing device proof and client unlock", |
| + "status": { |
| + "state": "proposed", |
| + "author": "this session, Codex suite coordinator subagent", |
| + "date": "2026-09-10", |
| + "reviewer": null, |
| + "runtime_activation": false |
| + }, |
| + "citations": [ |
| + { |
| + "repo": "oficina/suite", |
| + "commit": "1ac4323a7317a2bf4def3829896d9895a6ddc464", |
| + "path": "docs/superpowers/specs/2026-09-05-suite-sharing-doctrine.md", |
| + "sections": [ |
| + "ruling 10", |
| + "mail and files wrapper trigger" |
| + ] |
| + }, |
| + { |
| + "repo": "keymail/keymail", |
| + "commit": "d660c4dd78630a4590cc7226935dd5e547f31bd6", |
| + "paths": [ |
| + "identity.go", |
| + "oauth.go", |
| + "appapi.go", |
| + "docs/apps.md", |
| + "CLAUDE.md" |
| + ] |
| + }, |
| + { |
| + "repo": "slopboxcloud/slopbox", |
| + "commit": "c88ad26f9a61771ca4ff66ec27306d17f284fd97", |
| + "paths": [ |
| + "internal/home/home.go", |
| + "internal/home/auth.go", |
| + "internal/home/store.go", |
| + "internal/instance/webauthn.go", |
| + "CLAUDE.md" |
| + ] |
| + } |
| + ], |
| + "decision": { |
| + "proposed_boundary": "Oficina Home can identify the person requesting a launch. The provider must independently prove the existing local account/device and retain its current client unlock ceremony. The provider remains the data and decryption authority.", |
| + "shipping_order": [ |
| + "Complete native Oficina SSO rollout first.", |
| + "Expose explicit launch navigation to existing provider front doors, with existing sign-in/unlock requirements visible.", |
| + "Implement separately reviewed provider-owned linking and return navigation.", |
| + "Evaluate reducing repeated gestures only with proof that existing browser-held vault key/device authority remains intact." |
| + ], |
| + "placement": "Provider-owned endpoints and browser code at the existing Keymail/Slopbox origin. Avoid moving vault storage or app keys to a new Oficina wrapper origin.", |
| + "not_authorized_by_this_design": [ |
| + "minting owner inbox/file sessions from Home assertions", |
| + "replacing passkey PRF with server-delivered keys", |
| + "email-based account matching", |
| + "copying provider bearer credentials into Home", |
| + "claiming an unopened vault is ready", |
| + "reusing generic connect session hooks without a provider-specific proof adapter" |
| + ] |
| + }, |
| + "provider_seams": { |
| + "mail": { |
| + "local_authority": "Existing verified Keymail owner/device proof, not OAuth app grants. Existing consent scopes identify/send/newsletter do not authorize inbox reading.", |
| + "unlock": "Existing same-origin WebAuthn PRF or established local device key state opens the mailbox vault client-side.", |
| + "integration_owner": "keymail/keymail", |
| + "new_entry": "Proposed provider-owned /oficina/launch and /oficina/connect endpoints; route names require provider review before implementation." |
| + }, |
| + "files": { |
| + "local_authority": "Existing Slopbox Home credential/device proof chooses the encrypted directory; existing instance membership proof authorizes files. These are distinct authorities.", |
| + "unlock": "Existing browser passkey PRF opens the encrypted Home directory and instance file keys; the browser chooses the already-authorized instance.", |
| + "integration_owner": "slopboxcloud/slopbox", |
| + "new_entry": "Proposed provider-owned /oficina/launch and /oficina/connect endpoints at Slopbox Home; instance APIs remain unchanged." |
| + } |
| + }, |
| + "link_flow": [ |
| + { |
| + "step": 1, |
| + "actor": "provider browser", |
| + "action": "Start an explicit account-connection screen at the existing provider origin. No link begins from a background request." |
| + }, |
| + { |
| + "step": 2, |
| + "actor": "provider", |
| + "action": "Require a fresh existing local owner/device proof using the provider ceremony. Bind the pending link to the exact local principal ID, current credential/device identifier and a rotating session/device proof. An OAuth identify grant cannot substitute." |
| + }, |
| + { |
| + "step": 3, |
| + "actor": "browser and Oficina Home", |
| + "action": "Use a separately registered Home assertion consumer with fresh authentication required. Reuse the reviewed Home handoff transport and replay protections only; do not reuse connect storage/session assumptions." |
| + }, |
| + { |
| + "step": 4, |
| + "actor": "provider", |
| + "action": "Verify exact registered issuer, audience, callback origin, browser nonce, expiry and fresh Home proof. Keep the local device binding unchanged throughout the round trip." |
| + }, |
| + { |
| + "step": 5, |
| + "actor": "person", |
| + "action": "Explicitly confirm the connection after both independent proofs. Show provider account context only inside its already-unlocked client UI; never send inbox names, file paths or vault plaintext to Home." |
| + }, |
| + { |
| + "step": 6, |
| + "actor": "provider", |
| + "action": "Commit a one-to-one relation between the verified existing provider principal and the Home subject using provider-owned opaque identifiers. No account is created; duplicate or conflicting relations refuse. Bind stored links to non-reusable local principal identity and a revocation generation." |
| + } |
| + ], |
| + "launch_flow": [ |
| + "Home navigation selects the registered provider consumer and same fixed provider launch endpoint; caller-supplied external return destinations are refused.", |
| + "Home handoff identifies a linked launch request only. The provider resolves the existing relation and rechecks local admission/revocation.", |
| + "If the correct local browser/device remains authenticated and its client vault is already unlocked, continue to the existing inbox or files screen.", |
| + "If the vault is locked or browser proof is missing, run the provider unlock ceremony. Do not create a server-side decryption path.", |
| + "If a different provider account is active, show explicit account-switch confirmation and require its correct existing proof; do not silently replace it.", |
| + "After success, discard launch state and remain at the existing provider origin. No key material or provider token goes back to Home." |
| + ], |
| + "storage_and_revocation": { |
| + "home": "No provider bearer token, device secret, private key, vault plaintext, inbox name or file path.", |
| + "provider": "Provider-specific reviewed relation schema; HMAC or sealed opaque Home subject binding under a dedicated provider key, bound to issuer/consumer/local immutable principal/revocation generation. Exact schema and key lifecycle are implementation-review prerequisites.", |
| + "deletion": "Remove relation in the same transaction as local principal deletion; never reuse principal IDs. Revoked provider devices cannot satisfy pending or future local proof.", |
| + "unlink": "Own confirm screen behind fresh provider proof. Delete relation and pending flows atomically, preserving mailbox/files and existing independent credentials.", |
| + "logout": "Provider sign-out retains its existing vault-lock/device semantics and must not instantly restart Home sign-in. Home sign-out grants no authority to erase provider keys or data.", |
| + "rollback": "Disable launch feature while preserving old local sign-in, existing credentials and encrypted content. Never remove keys, vaults or historical data as rollback." |
| + }, |
| + "implementation_acceptance": [ |
| + "Provider owners approve exact local proof API, credential/device revocation model and privacy effect before code or schema ships.", |
| + "Synthetic two-account tests prove no email match, wrong-device link, changed session, replay, stale proof or cross-origin callback can connect accounts.", |
| + "Client tests prove Home authentication alone cannot decrypt or read mailbox/files and cannot bypass existing local unlock.", |
| + "Chromium and WebKit tests cover locked, unlocked, lost local state, second account, sign-out and no-JavaScript explanation flows; existing cryptographic ceremonies may retain their current JavaScript requirement.", |
| + "CSP tests compare provider baseline and permit only the fixed validated Home issuer when needed; unrelated destinations and form chains remain blocked.", |
| + "Existing raw-database/blob ciphertext invariants and recovery/device-link suites remain green.", |
| + "No tests send human mail, authorize real OAuth accounts, expose keys or mutate customer files.", |
| + "Deploy isolated provider canaries after independent whole-delta review, then verify live versions and local unlock behavior; no shared production instance overwrite." |
| + ], |
| + "unresolved_before_implementation": [ |
| + "Exact provider owner/device freshness APIs and whether they rotate/revoke proof on account switch.", |
| + "Private relation schema, account deletion hooks, and provider key rotation/recovery mechanics.", |
| + "Which provider origins and customer mappings Home may list without disclosing information the current provider Home deliberately keeps encrypted.", |
| + "Whether an already unlocked browser can complete the intended launch without an extra passkey gesture; no guarantee until browser/device proof is tested." |
| + ] |
| +} |