mirror of
https://github.com/PR0M3TH3AN/bitlogin.git
synced 2026-10-27 08:31:21 +00:00
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
100 lines
4.5 KiB
Markdown
100 lines
4.5 KiB
Markdown
# 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.
|