eleven / ocho Public

Define passkey-only signup and short encrypted invitations

Paul Campbell pushed by codex agent, operated by paul@keymail.dev ac95203b84cf28ff73e1964bc041332bbc9372a9 parent cec6fd1
1 file changed, +15 −0
  • docs/infinity/simple-onboarding.md +15 −0
diff --git a/docs/infinity/simple-onboarding.md b/docs/infinity/simple-onboarding.md
new file mode 100644
index 0000000..a432a8a
--- /dev/null
+++ b/docs/infinity/simple-onboarding.md
@@ -0,0 +1,15 @@
+# 🤖 Passkey-only Ocho — 2026-09-07
+
+Paul requests a reset of onboarding, not deletion of accounts/messages. The public root shows Sign up and Sign in. Sign up opens a name step; Create invokes passkey creation before personal provisioning, then opens chat at the same public origin. RP display name is ocho.chat. Remove recovery-file UI; retain low-level legacy readers only for compatibility, with no new user-facing recovery-file path. Existing signed-in accounts may add a passkey without discarding their history. No password fallback or server-readable escrow when PRF is unavailable.
+
+Registration begins with an anonymous bounded WebAuthn challenge bound to the existing random provisioning nonce. The device creates its PRF-capable passkey first; cancellation allocates no personal instance. It retains the ceremony and wrapping key locally while the existing Carlos proof-of-work/idempotent allocation creates the personal instance. Finalization verifies the attestation through Rastrillo, the provisioning nonce-to-host binding and owner authorization, and atomically stores the sealed identity. Finalization is idempotent for exactly the same completed request so a lost reply cannot strand signup. Signup challenges allow a bounded 15-minute provisioning window. No passkey PRF output, wrapping key or private identity is sent to the server.
+
+The authenticated same-origin relay continues to serve personal APIs beneath ocho.chat while each account retains its process/database. CARLOS's available path routing maps fixed first segments and leaves the root on its host route; it does not select the currently signed-in account. Routing is implementation detail and must not appear in the product UI or cause tenant-host navigation.
+
+A short invitation uses 16 random bytes (128 bits, 22 base64url characters) in the URL fragment. Domain-separated derivations produce a lookup identifier, encryption key and separate redemption proof. The server stores an encrypted descriptor, lookup ID and proof hash, never the fragment/key. A read-only preview decrypts locally to show “Paul is inviting you to chat on Ocho”. Owner-authenticated redemption is atomic, bound to a recipient and retryable only by that recipient. Expiry is seven days. Link preview bots cannot consume it. Opening an invite shows Accept and Sign up to accept, or Accept for an existing session; creation shows Name then Connect with Paul then passkey. Successful acceptance opens the conversation directly.
+
+The inviter's signed encrypted invitation grants advance consent to the first valid redeemer. The invitation contains a dedicated one-use inbound capability and a signed descriptor. Recipient and inviter clients verify that consent, avoiding a second manual approval even if the inviter's app is closed. Delivery retries must reuse the same encrypted handshake, and the first valid recipient is pinned; forged/duplicate competitors cannot replace the chosen peer. Existing legacy/manual invitations retain their original consent semantics.
+
+Profile editing persists display name/avatar in the encrypted vault and sends signed encrypted profile updates to established contacts. Avatars are bounded raster data, never remote tracking URLs or executable SVG. Both the Go engine and browser preserve and validate the new fields so native saves cannot erase web profile changes. Profile editing never changes identity keys.
+
+Acceptance: passkey signup and sign-in, cancellation before allocation, lost replies/retry, no tenant navigation, short-link entropy and encryption, preview without consumption, simultaneous redemption isolation, direct chat with inviter offline, existing chat/group integrity, avatar/name synchronization, and native compilation. Preserve pending push work and deploy both features after their checks. No test messaging real contacts or resetting user instances.