oficina / suite Public

Propose provider-owned Mail and Files Home launch

Paul Campbell pushed by paul@keymail.dev 7c23220d3e2585fe347e71a8a8de908ac6982b95 parent 1ac4323
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."
+ ]
+}