199 lines
9.2 KiB
Markdown
199 lines
9.2 KiB
Markdown
|
|
# Identity + wallet roadmap
|
||
|
|
|
||
|
|
Two independent strands, both rooted in the same BCH-style seed-with-hardened-
|
||
|
|
derivation model. Order them however makes sense to the session picking this
|
||
|
|
up; strands don't block each other.
|
||
|
|
|
||
|
|
**Strand A — Password manager.** Local-first vault, deterministic derivation
|
||
|
|
per site+username, optional Sia backup for cross-device.
|
||
|
|
**Strand B — Browser-integrated BCH wallet.** MetaMask-style provider so
|
||
|
|
Silent Mode pages (and any BCH-native dApp) can request signatures,
|
||
|
|
payments, and BCNR name operations from the user's wallet.
|
||
|
|
|
||
|
|
Both use the SAME seed via distinct hardened purpose subtrees so one
|
||
|
|
compromise can't leak the other:
|
||
|
|
|
||
|
|
```
|
||
|
|
m / 44' / 145' BCH wallet (SLIP-44) ← wallet already ships
|
||
|
|
m / 1381' / 0' passwords ← phase 1 shipped
|
||
|
|
m / 1414' / 0' messenger (Nostr etc.) ← future
|
||
|
|
```
|
||
|
|
|
||
|
|
Same seed, three purposes, no cross-derivation. See
|
||
|
|
[DESIGN-password-manager.md](DESIGN-password-manager.md) for the discipline.
|
||
|
|
|
||
|
|
## Strand A — Password manager
|
||
|
|
|
||
|
|
### A.1 — SHIPPED (0.0.3, 9c09955e)
|
||
|
|
- Local encrypted vault at `<userData>/passwords.vault`
|
||
|
|
- AES-256-GCM under PBKDF2 (200k iters, SHA-256) master-password key
|
||
|
|
- BIP39 mnemonic → seed → HKDF purpose root
|
||
|
|
- Deterministic derivation per (domain, username, version, rules)
|
||
|
|
- Settings UI: setup / locked / unlocked panels, add/edit/reveal/copy/delete
|
||
|
|
- IPC surface: pwStatus/Setup/Unlock/Lock/List/Get/Add/Update/Remove/Generate
|
||
|
|
- 12 crypto unit tests, all passing
|
||
|
|
|
||
|
|
### A.2 — Autofill (~ 1 week)
|
||
|
|
The user-visible next step. Right now users must copy from Settings.
|
||
|
|
|
||
|
|
- **ContentScript** injected on every page (Electron
|
||
|
|
`session.defaultSession.setPreloads` OR per-webContents preload extension)
|
||
|
|
- Watch `input[type=password]` + adjacent username field on load AND on
|
||
|
|
DOM mutation (SPAs). Debounce.
|
||
|
|
- **Origin binding via eTLD+1** using the public suffix list. Ship a
|
||
|
|
bundled snapshot of https://publicsuffix.org/list/public_suffix_list.dat
|
||
|
|
under `Argus/data/` so `evil-google.com` can't fill `google.com`.
|
||
|
|
- **Toolbar affordance**: a key icon in the address bar OR the shield's
|
||
|
|
overlay grows a "Passwords" chip when entries exist for the current
|
||
|
|
origin. Click → pick which credential to fill.
|
||
|
|
- **Keyboard shortcut**: Ctrl+Shift+L to fill the current form.
|
||
|
|
- **Save prompt**: when a form submit yields a password field the vault
|
||
|
|
hasn't seen, prompt "Save this password? (Generate strong one instead?)"
|
||
|
|
- **Per-origin permission** cached: sites that were already refused don't
|
||
|
|
re-prompt.
|
||
|
|
- Tests: origin-binding table (eTLD+1 for suffix corner cases —
|
||
|
|
`*.co.uk`, `*.compute.amazonaws.com`, IDN), autofill DOM injection
|
||
|
|
vector coverage.
|
||
|
|
|
||
|
|
### A.3 — Sia backup / cross-device restore (~ 3-5 days)
|
||
|
|
Opt-in cloud sync of the encrypted vault blob.
|
||
|
|
|
||
|
|
- New setting: "Sync vault to Sia". Off by default.
|
||
|
|
- User provides their own Sia S3 endpoint + credentials (like the operator's
|
||
|
|
`sia-s3.json`), OR opts to use the operator's public relay at
|
||
|
|
`sia://silentmode.st/vault/<vaultId>` (metadata leaks: only "this
|
||
|
|
vaultId exists", nothing else — vault is encrypted end-to-end).
|
||
|
|
- On save: upload the encrypted-blob bytes to `bucket/vault-<id>.bin`.
|
||
|
|
Include an integrity hash in the local vault header.
|
||
|
|
- On new-device setup: user picks "Restore from Sia" → enters vaultId +
|
||
|
|
master password → download blob → decrypt.
|
||
|
|
- **Explicit non-goal**: no operational sync (last-write-wins across
|
||
|
|
devices, no merge). Phase A.3 is "clone the vault to another laptop",
|
||
|
|
not "keep two laptops perfectly in step". Multi-device concurrent-edit
|
||
|
|
is A.4 if we ever want it.
|
||
|
|
|
||
|
|
### A.4 — Nice-to-haves
|
||
|
|
Order these however makes sense; each is small and independent.
|
||
|
|
- Import from Bitwarden JSON / KeePass CSV / Firefox CSV
|
||
|
|
- Export to same
|
||
|
|
- Password strength meter on the paste-a-password entry
|
||
|
|
- Auto-lock after N minutes of Theseus idle
|
||
|
|
- Password-history per entry (previous versions kept, so a rotation
|
||
|
|
doesn't lose the old password until the user confirms it's no longer
|
||
|
|
needed anywhere)
|
||
|
|
- Compromised-password check via HIBP k-anonymity API (opt-in, sends
|
||
|
|
a 5-char SHA-1 prefix only)
|
||
|
|
- Password-strength / composition rules from the site's `passwordrules`
|
||
|
|
attribute (WICG spec) so generated passwords satisfy site policy
|
||
|
|
|
||
|
|
## Strand B — Browser-integrated BCH wallet
|
||
|
|
|
||
|
|
MetaMask-style `window.bcnr` (or `window.bch`) provider that lets a page
|
||
|
|
request signatures, payments, and name operations from the user's wallet.
|
||
|
|
The wallet already exists in `site/js/` for the registrar flow; this
|
||
|
|
strand generalises it to a per-origin API for any page.
|
||
|
|
|
||
|
|
### B.1 — Design (start here) (~ 2-3 days)
|
||
|
|
|
||
|
|
Ship the doc before writing code. Two hard problems to nail:
|
||
|
|
|
||
|
|
1. **Permission model**. Chrome dapp providers have taught us how easily
|
||
|
|
this becomes malware infrastructure. The doc must lock down:
|
||
|
|
- Permission granularity: per-origin, per-method, per-amount
|
||
|
|
- First-use always shows a modal (never auto-approves)
|
||
|
|
- Persistent permissions revocable in Settings > Wallet > Sites
|
||
|
|
- "You're on a BCNR name backed by an on-chain contract" vs "You're
|
||
|
|
on random-site.com" — trust badges the user can see before signing
|
||
|
|
- Anti-phishing: display the recipient's cash address in the
|
||
|
|
confirmation dialog with a big warning if the address changes
|
||
|
|
mid-session
|
||
|
|
|
||
|
|
2. **API surface**. Match existing convention where possible so BCH dApp
|
||
|
|
developers don't learn a Silent Mode-only dialect:
|
||
|
|
- `bcnr.getAccounts()` — returns cash addresses the user has approved
|
||
|
|
for this origin
|
||
|
|
- `bcnr.requestAccount()` — first-use modal
|
||
|
|
- `bcnr.signMessage({message, address})` — BIP-137 style, used for
|
||
|
|
BCNR name registration and auth flows
|
||
|
|
- `bcnr.sendPayment({to, amount, memo})` — modal-confirmed BCH send
|
||
|
|
- `bcnr.resolveName(name)` — no permission needed; BCNR lookup
|
||
|
|
- `bcnr.registerName({name, records})`, `bcnr.updateName(name, records)`
|
||
|
|
— modal-confirmed; ties into the site/register.html flow
|
||
|
|
|
||
|
|
Deliverable: `TheseusNavigator/DESIGN-integrated-wallet.md` in the same
|
||
|
|
shape as `DESIGN-password-manager.md`.
|
||
|
|
|
||
|
|
### B.2 — Injection scaffold + read-only APIs (~ 1 week)
|
||
|
|
|
||
|
|
- ContentScript that injects `window.bcnr` on every page load. Isolated
|
||
|
|
world (Electron's `contextIsolation: true` already enforces this) so
|
||
|
|
page JS can't tamper with the provider.
|
||
|
|
- Provider is an event-emitting object that speaks JSON-RPC over
|
||
|
|
postMessage to the preload, which forwards to main via IPC.
|
||
|
|
- Read-only methods (no permission needed): `resolveName`, `getBcnrTlds`,
|
||
|
|
`isRegistered`, `getRecordVersion`.
|
||
|
|
- Tests: page-script → provider → main round trip; provider surface
|
||
|
|
matches the spec.
|
||
|
|
|
||
|
|
### B.3 — Signature + payment APIs (~ 2-3 weeks)
|
||
|
|
|
||
|
|
- Permission-gated: `requestAccount`, `signMessage`, `sendPayment`.
|
||
|
|
- Reuse the existing wallet in `site/js/` (libauth-based) as the signing
|
||
|
|
core; wrap it in a main-process handler that reads the wallet's
|
||
|
|
`wallets.json` (already encrypted with the wallet passphrase).
|
||
|
|
- Modal confirmations rendered as a new WebContentsView overlay (same
|
||
|
|
pattern as popover/engine-picker/downloads).
|
||
|
|
- Site permissions persisted in `userData/wallet-permissions.json`.
|
||
|
|
- Settings → Wallet section: list connected sites, revoke per-site or
|
||
|
|
per-method.
|
||
|
|
|
||
|
|
### B.4 — BCNR name operations (~ 1 week)
|
||
|
|
|
||
|
|
- `registerName`, `updateName` — thin wrappers over the existing
|
||
|
|
`Argus/src/register.js` / `update.js` flows.
|
||
|
|
- Sanity: same modal-first pattern; show the exact record payload before
|
||
|
|
signing (users need to see what's going on-chain permanently).
|
||
|
|
|
||
|
|
### B.5 — Nostr messenger integration (~ 2-3 weeks)
|
||
|
|
|
||
|
|
Bring the messenger strand in as a parallel purpose. Same seed under
|
||
|
|
`m/1414'/0'`, so users who set up passwords in strand A already have
|
||
|
|
messenger keys.
|
||
|
|
|
||
|
|
- Derive Nostr keys (secp256k1, npub/nsec encoding) from the messenger
|
||
|
|
purpose root
|
||
|
|
- `window.nostr` NIP-07 provider (widely-supported protocol, dozens of
|
||
|
|
compatible clients)
|
||
|
|
- Chrome integration: address bar chip when a Nostr-native site connects
|
||
|
|
- Threat model: Nostr keys don't hold funds, but do bind identity —
|
||
|
|
compromise = impersonation. Same modal-first permission model.
|
||
|
|
|
||
|
|
### B.6 — Advanced: connect-wallet UX
|
||
|
|
|
||
|
|
- QR-pairing so a mobile Ariadne can act as a hardware-wallet-like
|
||
|
|
signer for a desktop Theseus
|
||
|
|
- Multisig confirmations (2-of-3 with a hardware wallet + Theseus +
|
||
|
|
Nostr-relayed remote signer)
|
||
|
|
|
||
|
|
## Cross-strand dependencies
|
||
|
|
|
||
|
|
- Both strands rely on the crypto module at
|
||
|
|
`Argus/src/lib/password-vault.js`. Extract `bip39ToSeed` +
|
||
|
|
`seedToPurposeRoot` into a `seed-derive.js` module the wallet strand
|
||
|
|
can also import cleanly.
|
||
|
|
- Both strands should share the master-password unlock. If a user has
|
||
|
|
the vault unlocked and the wallet locked (or vice versa), the second
|
||
|
|
unlock should not re-prompt.
|
||
|
|
|
||
|
|
## Non-goals
|
||
|
|
|
||
|
|
- No third-party cloud sync. Sia is the only sync target we bless.
|
||
|
|
- No Chromium password-manager UI reuse. Ergonomics don't fit our threat
|
||
|
|
model (Google Sync-shaped).
|
||
|
|
- No Ethereum / Solana / other-chain support in Strand B. This is BCH-
|
||
|
|
specific; multi-chain is a separate future decision.
|
||
|
|
- No hardware-wallet abstraction layer in phase 1. Ledger/Trezor
|
||
|
|
integration is a phase 4 conversation.
|
||
|
|
- No autofill for credit cards, addresses, or contact forms. Each has
|
||
|
|
security nuances that deserve their own design pass. Password-only.
|