Files
thePR0M3TH3ANandClaude Fable 5 a465e1d8fa Implement the Connection Vault protocol layer (phases A-C)
connection-vault.md 5-13 as code, with the implementation-time decisions
recorded in a new section 18 and vault-ux.md holding the agreed UX
walkthroughs as the authorization layer's acceptance criteria.

Capsules gain paired optional fields connection_vault_root and
vault_sudo_key (both or neither, validated); registration mints them,
login/change-password/recovery carry them forward, and
enableConnectionVault is the phrase-gated migration for existing
accounts -- recovery capsule written first, fail closed, idempotent by
reusing roots found in either capsule so a partial failure can never
mint twice and strand records.

src/vault/ holds the finalized key hierarchy (HKDF/ScalarExpand
constants pinned by test vectors that must only ever be reverted, never
updated), per-connection encrypted records signed by a derived vault
identity with the capsule JCS+padding+AES-GCM pipeline and shared
buckets so record types are indistinguishable by size, the NWC profile
with lossless URI parse/export, relay sync reusing the publish-and-
verify quorum bar, and per-record high-water marks so a stale replica
is withheld and reported rather than silently resurrecting a revoked
credential.

The two-tier model makes sudo mode cryptographically real: personal-
tier record keys require vault_sudo_key as HKDF input, VaultSession
holds it only inside an enableSudo/endSudo window (wiping on the way in
and out), and outside a window personal records are invisible -- the
same trial-decrypt returns null, not an error. The app-facing API is
structurally blind to the tier by construction.

118 tests passing, including four end-to-end scenarios against mock
relays: clean-device restore, password-change carry, legacy-account
migration (wrong phrase refused), and rollback detection.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CMr9Yt8SYmZcfgrg3CV2G1
2026-07-30 12:29:46 -04:00

100 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Connection Vault — UX walkthroughs
**Status:** Agreed product direction (2026-07-30)
**Role:** These scenarios are the acceptance criteria for the Phase D
authorization layer (`connection-vault.md` §12, §18). The design principle
running through all of them: **friction appears exactly where danger is, and
nowhere else.** Count the friction across the whole set: one phrase entry
ever, one budget-facing tap per app, one tap per new device, sudo or phone
approval only at genuinely dangerous reveals. Everything else is silence.
## 1. Turning the vault on — existing account
Account manager card: *"Connection Vault — store wallet and storage
connections once, use them on every device."* Enabling asks for the recovery
phrase with the reason stated plainly (*"the vault must survive both your
password and your phrase"*), rewrites both capsules with quorum readback, and
fails closed with a retry that reuses the same roots
(`enableConnectionVault`). New accounts skip this scenario entirely — the
roots are minted at registration.
*Deliberate friction:* the phrase entry, once per account ever.
## 2. Connecting a wallet the first time — inside an app
The app calls the request API with a reason string. The sheet walks the user
through pasting/scanning an NWC URI, parses it, and shows what it learned —
provider, relay, and **the budget in large type**. No budget draws an amber
warning recommending a budgeted connection, never a hard block. Label
pre-filled from the app name. The final line before reveal is honest:
*"[App] will receive this connection and can spend within its budget until
you revoke it."* Save binds the record to the requesting origin.
*Deliberate friction:* one explicit share tap, budget staring at the user.
*Removed friction:* naming, binding, storage.
## 3. The payoff — new phone
Sign into the app's BitLogin, and at the first payment moment:
> **Use "Satisfied spending wallet"?**
> *You connected this wallet to Satisfied on another device. Budget: 500 sats/day.*
One tap. Zero pasting. This screen is the entire reason the vault exists.
A new device seeing a credential for the first time must never happen
silently, even with a durable grant.
## 4. Every ordinary day after
Nothing. No prompt, no branding. The grant is durable per origin per device;
the vault's best UX is absence.
## 5. Connected apps — management
Account manager page listing origin → connection → grant date → devices, with
**Revoke access** per row and one **"Revoke all app access"** panic button.
Each connection's detail page separates two red actions honestly:
- **Remove from BitLogin** — deletes the stored copy; the credential itself
keeps working for anyone who already holds it.
- **Revoke at wallet/provider** — an instruction with a guide, not a button
pretending BitLogin can reach into the wallet (§11).
## 6. S3 connections
Same sheet pattern; the import screen teaches while it collects: scoped IAM
key vs root key question, a recommended object-prefix field, amber warning on
unscoped credentials. Reveal to an app requires sudo mode — S3 secrets guard
buckets, not a 500-sat budget.
## 7. Personal tier — passwords and secure notes
Exists ONLY in the first-party account manager. No app can request, list, or
learn these records exist (the tier is invisible to the app-facing API by
construction — see §18.2). Viewing requires sudo mode: re-enter the account
password, ~5-minute window. Copy button, auto-clearing field. The copy is
honest: a safe place for a few important secrets, not a password manager —
autofill and site-matching wait for the extension generation. Seed phrases
stay banned.
## 8. Phone approval (after §SF5–7 ships)
High-tier reveals push to the enrolled phone; the record key is 2-of-2
derived so a laptop cryptographically cannot proceed on its own. Budgeted NWC
connections deliberately do NOT phone-prompt — the budget is already the
lock, and prompting every payment trains reflexive approval.
## 9. Disaster — phrase-only recovery
Twelve words on a clean device restore identity, then the vault roots ride
the recovery capsule (§13.2), so connections reappear: wallets, buckets,
passwords. The phrase remains the ungated master path (§SF9). The flow nudges
re-enrolling a phone and rotating anything sensitive.
## Build order for Phase D
The screens, in dependency order: request/consent sheet (2, 3) → guided NWC
import (2) → Connected apps + connection detail (5) → S3 import (6) → sudo
mode (7). The personal tier and phone approval layer on later without
reshaping anything before them.