docs(theseus): draft wallet multi-account amendment
Amends DESIGN-integrated-wallet.md §0 ("one account per profile in v1") with
a formal path to supporting external key imports (BIP39 seeds and raw WIFs)
alongside the primary HD purpose-subtree. Motivated by the user's 15-wallet
Deviant chipnet keystore now encrypted under the same master-password model
that Theseus is designed around.
Key discipline:
- SEPARATE storage file (wallet-imports.enc), same PBKDF2/AES-256-GCM crypto,
same master password, distinct KDF salt. Imports cannot compromise the
primary seed and vice versa; corruption of one file does not damage the
other.
- The imports schema mirrors Deviant's chipnet-keystore/1 shape (cashaddr /
label / category / source / path / seed / wif) so import is a 1:1 field
copy, not a translation.
- Every import stores the raw seed + BIP44 path (or the raw WIF) and derives
addresses DIRECTLY via HDKey.fromMasterSeed, bypassing the vault's
purposes/wallet HKDF subtree. This is essential: without the bypass,
pasting a mnemonic re-hashes the seed through HKDF and produces DIFFERENT
addresses than the source wallet (see memory
bchwallet-vault-root-derivation).
- No bcnr.importWallet() ever; imports are settings-page only.
- Sign modal grows an account picker with category chips; per-origin
"recently used" pre-selection with red-flag on category change.
Also introduces:
- bcnr.requestAccount({ account?, category? }) — backwards compatible
- bcnr.getAccounts({ category? })
- Stale-import detection (source-file cashaddr comparison on unlock)
- Sequencing: M.1 (generic import) → M.2 (import from Deviant keystore) →
M.3 (API extensions) → M.4 (stale detection). M.1 is load-bearing;
everything else composes.
Companion to Option A which shipped separately as the cross-repo fall-through
in Argus/src/lib/wallet.js.
This commit is contained in:
parent
30734847e9
commit
8649bb97ea
1 changed files with 436 additions and 0 deletions
436
DESIGN-wallet-multi-account-amendment.md
Normal file
436
DESIGN-wallet-multi-account-amendment.md
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
# Theseus wallet — multi-account amendment
|
||||
|
||||
Amendment to [`DESIGN-integrated-wallet.md`](DESIGN-integrated-wallet.md) §0
|
||||
("Multi-account UX. One account per Theseus profile in v1."). Proposes lifting
|
||||
that restriction under a specific discipline that keeps the single-seed HKDF
|
||||
purpose-subtree model intact.
|
||||
|
||||
Status: **draft** — not accepted, not scheduled. Written 2026-09-09 as the
|
||||
formal path to "Theseus recognises the master password and shows all of my
|
||||
existing wallets, including externally-generated ones", raised while migrating
|
||||
the Deviant `Keys/chipnet-keystore.json` to master-password encryption.
|
||||
|
||||
Companion documents:
|
||||
- [`DESIGN-integrated-wallet.md`](DESIGN-integrated-wallet.md) — the v1 design this amends
|
||||
- [`DESIGN-password-manager.md`](DESIGN-password-manager.md) — the crypto discipline (PBKDF2, HKDF, purpose subtrees)
|
||||
- [`../Argus/src/lib/password-vault.js`](../Argus/src/lib/password-vault.js) — the implemented vault primitives
|
||||
- [`../Argus/src/lib/wallet.js`](../Argus/src/lib/wallet.js) — the just-landed cross-repo loader (Option A) that resolves `loadWallet('sirius.x')` from either SilentMode's own `wallets.json` or Deviant's encrypted `Keys/chipnet-keystore.json`
|
||||
|
||||
---
|
||||
|
||||
## 0. Why amend now
|
||||
|
||||
Three facts changed since §0 was written:
|
||||
|
||||
1. **The user has 15 chipnet wallets already** — 5 HD seeds plus 10 single-key
|
||||
WIFs — spread across Deviant (`Keys/chipnet-keystore.json`, encrypted with
|
||||
PBKDF2/AES-256-GCM and the master password) and SilentMode
|
||||
(`Argus/wallets.json`, plaintext). Consolidating them under Theseus is the
|
||||
natural next step now that both projects use the same master password.
|
||||
2. **`password-vault.js` already ships** the primitives that make this cheap:
|
||||
`unlockVault(path, pw)` returns a state object; `seedToPurposeRoot(seed,
|
||||
purpose)` derives an HKDF subtree deterministically; `bytesToHex/hexToBytes`
|
||||
are the wire format. There is no new crypto to design — only new state to
|
||||
serialise.
|
||||
3. **The Deviant wallet dApp (`shells/app/`) already has multi-account UX**,
|
||||
including `MultiKeyStore.WalletSummary { id, label, network, cashaddr, kind:
|
||||
'independent' | 'hd-account' }`. The alternative to amending Theseus is to
|
||||
host that dApp inside Theseus. This document argues the amendment is
|
||||
*additionally* worth doing, not a replacement for that path.
|
||||
|
||||
The core question §0 punted on was not "is multi-account complicated?" — it was
|
||||
"does supporting external key material contaminate the single-seed model?"
|
||||
This document answers: **no, if we keep external material in a distinct storage
|
||||
lane with a separate origin tier in every UI surface.**
|
||||
|
||||
---
|
||||
|
||||
## 1. What "multi-account" means here — three distinct notions
|
||||
|
||||
We need to keep these apart because they have different threat models:
|
||||
|
||||
| Kind | Storage | Origin | Recovery | Example |
|
||||
|---|---|---|---|---|
|
||||
| **Primary account (unchanged)** | HKDF subtree under `silentmode/wallet/0/<index>` | Derived from the profile's single seed | Recover the seed → recover every primary account | The wallet a fresh Theseus profile creates for you |
|
||||
| **Primary sub-accounts (new)** | HKDF subtree at index N under the same purpose root | Same seed | Same seed | "Trading", "Savings", "GMX game bets" — different indexes off the same profile seed |
|
||||
| **External accounts (new)** | Separately encrypted blob keyed by the same master password | Independent (imported seed OR raw WIF) | Recover the *external material* — the profile seed does NOT recover them | Deviant's `sirius.x`, `bns-beacon`, the a-g throughput test WIFs |
|
||||
|
||||
The confusion §0 avoided was mixing categories 1 and 3 in one bag. The
|
||||
amendment keeps them **in separate files** on disk. The user sees one unified
|
||||
UI, the crypto keeps them completely isolated.
|
||||
|
||||
---
|
||||
|
||||
## 2. Threat-model deltas from §1 of the base doc
|
||||
|
||||
### 2.1 New surface: importing external key material
|
||||
|
||||
Every import path is a potential exfiltration event. Three attack shapes:
|
||||
|
||||
- **Shoulder-surf on paste** — someone reads the seed / WIF as it's typed or
|
||||
pasted. Mitigation: never render the imported string; the modal shows only a
|
||||
masked derived cashaddr after the import completes ("Import a wallet ending
|
||||
in …abc123?"). No "show me the WIF I just imported" affordance.
|
||||
- **Import from clipboard by malicious page** — a page holding
|
||||
`navigator.clipboard.readText()` permission could feed material INTO the
|
||||
import flow. Mitigation: **import is a settings-page action only**, never
|
||||
reachable from `window.bcnr` or WizardConnect. There is no
|
||||
`bcnr.importWallet()` method. Ever.
|
||||
- **Import from disk by malicious extension** — Theseus itself can't fully
|
||||
defend against this (§1.4 base doc), but the imported material lives in a
|
||||
separately-encrypted file so a compromised in-memory purpose-root leak does
|
||||
not leak the imports.
|
||||
|
||||
### 2.2 New surface: rendering many wallets in one UI
|
||||
|
||||
The user's clicks now cost more, because a wrong-account signature is
|
||||
irrecoverable. Mitigations:
|
||||
|
||||
- **Explicit signer selection per sign-request.** The sign modal shows
|
||||
`Signing as: [Sirius.x · BNS name buyer ▾]` with the account picker OPEN by
|
||||
default (not collapsed). If a page requested a specific account via
|
||||
`bcnr.requestAccount({ account: 'sirius.x' })`, the modal still shows every
|
||||
account the user could have chosen — the requested one is pre-selected and
|
||||
the picker collapsed, but expanding it is one click.
|
||||
- **Category badges everywhere the account appears.** The wallet metadata
|
||||
already carries a `category` field (`bns`, `bns-infra`, `chipnet-test`,
|
||||
`operational`, …). The modal chip is coloured by category so `sirius.x`
|
||||
(BNS) is visually distinct from `gmx` (operational) even if the user only
|
||||
glanced at the modal.
|
||||
- **"Recently used" is per-origin.** `deviant.bch` remembers which account you
|
||||
last signed with — but it does not silently reuse it; it pre-selects it in
|
||||
the modal, and a category change ("last time you used a `bns` account here,
|
||||
now the page wants an `operational` one") gets a red warning banner.
|
||||
|
||||
### 2.3 What we still do NOT defend against (unchanged from base doc §1.4)
|
||||
|
||||
Imports of a seed the user already leaked, RCE on Theseus itself, keylogger.
|
||||
These remain out-of-scope; the amendment does not widen the scope, only the
|
||||
attack surface within it.
|
||||
|
||||
---
|
||||
|
||||
## 3. Storage model
|
||||
|
||||
### 3.1 The primary vault stays as designed
|
||||
|
||||
`<userData>/wallet.enc` (from `DESIGN-integrated-wallet.md` §6) holds the
|
||||
profile's single seed. Every primary sub-account is derived on demand via
|
||||
`seedToPurposeRoot(seed, "wallet/0")` → BIP32-style index. Nothing about the
|
||||
existing design changes.
|
||||
|
||||
### 3.2 New file: `<userData>/wallet-imports.enc`
|
||||
|
||||
Same crypto envelope as `wallet.enc` (PBKDF2-SHA256 → AES-256-GCM), same
|
||||
master password, separate KDF salt and IV. This is the ONLY place external key
|
||||
material lives. Format after decryption:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "silentmode/wallet-imports/1",
|
||||
"generated": "2026-09-09T12:00:00Z",
|
||||
"accounts": {
|
||||
"sirius-x": {
|
||||
"kind": "seed",
|
||||
"seed": "…",
|
||||
"path": "m/44'/145'/0'/0/0",
|
||||
"cashaddr": "bchtest:qzy92wznza359wzqz5r732wylfyrgl4djsl2agdp0p",
|
||||
"label": "Sirius.x · BNS name buyer",
|
||||
"category": "bns",
|
||||
"source": "imported-from-D:/Dev/Deviant/Keys/chipnet-keystore.json#sirius-x",
|
||||
"createdAt": 1725840000000
|
||||
},
|
||||
"gmx": {
|
||||
"kind": "wif",
|
||||
"wif": "…",
|
||||
"cashaddr": "bchtest:qz040z8hza8n96llrk5kewp5dmyr5rd7csj8rasu9d",
|
||||
"label": "GMX platform operator",
|
||||
"category": "operational",
|
||||
"source": "imported-from-D:/Dev/Deviant/Keys/chipnet-keystore.json#gmx",
|
||||
"createdAt": 1725840000001
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `accounts` shape deliberately mirrors the fields already used by Deviant's
|
||||
`chipnet-keystore/1` format (`cashaddr`, `label`, `category`, `source`, `path`,
|
||||
`seed`, `wif`) so a Deviant → Theseus import is a one-to-one field mapping,
|
||||
not a schema translation.
|
||||
|
||||
**Why a separate file, not one file with two sections?** Blast radius. A bug
|
||||
that corrupts `wallet-imports.enc` cannot destroy the primary seed. A revoke
|
||||
"remove all imports" clears one file — the primary vault is untouched. This
|
||||
is the same discipline `DESIGN-password-manager.md` uses to keep the password
|
||||
vault distinct from the seed vault: distinct files, same master password.
|
||||
|
||||
### 3.3 One-way pointer: primary → imports, never the other way
|
||||
|
||||
The primary vault gets a new small field:
|
||||
|
||||
```json
|
||||
{ …existing wallet.enc payload…, "importsExist": true }
|
||||
```
|
||||
|
||||
...updated on every import/revoke. Loading the primary vault tells Theseus
|
||||
whether it should also try to decrypt `wallet-imports.enc`. The **imports
|
||||
file NEVER references the primary** — an attacker who exfiltrates
|
||||
`wallet-imports.enc` learns nothing about the profile seed, not even its
|
||||
existence.
|
||||
|
||||
### 3.4 What the master password unlocks in one session
|
||||
|
||||
On `unlockVault(masterPw)`:
|
||||
|
||||
1. Derive `vaultKey` (PBKDF2 with `wallet.enc`'s salt).
|
||||
2. Decrypt `wallet.enc` → get profile seed → derive `purposes/wallet/0`,
|
||||
`purposes/passwords/0`, `purposes/messenger/0`.
|
||||
3. If `importsExist`: derive `vaultKey'` (PBKDF2 with
|
||||
`wallet-imports.enc`'s DIFFERENT salt — deliberately not the same key
|
||||
material) and decrypt.
|
||||
|
||||
Both keys are held in RAM for the session; both are wiped on auto-lock. A
|
||||
malicious page that gets an in-memory read of the wallet purpose root learns
|
||||
nothing about imports.
|
||||
|
||||
---
|
||||
|
||||
## 4. UX
|
||||
|
||||
### 4.1 Settings > Wallet — the accounts panel
|
||||
|
||||
Replaces the base doc's "Account row: address, balance, backup phrase".
|
||||
|
||||
```
|
||||
── Accounts ─────────────────────────────────────────────────────
|
||||
[+ Create sub-account] [+ Import external wallet]
|
||||
|
||||
● Primary [rename ▎revoke]
|
||||
bchtest:qxxx…yyy · category "primary"
|
||||
|
||||
● Trading (primary sub-account #1) [rename ▎revoke]
|
||||
bchtest:qaaa…bbb · category "primary"
|
||||
|
||||
── Imported ─────────────────────────────────────────────────
|
||||
● Sirius.x · BNS name buyer [rename ▎revoke]
|
||||
bchtest:qzy…dp0p · category "bns"
|
||||
source: Deviant/Keys/chipnet-keystore.json#sirius-x
|
||||
|
||||
● BNS TLD Beacon (.asm/.x) [rename ▎revoke]
|
||||
bchtest:qzc…pmerh · category "bns-infra"
|
||||
source: Deviant/Keys/chipnet-keystore.json#bns-tld-beacon
|
||||
|
||||
● GMX platform operator [rename ▎revoke]
|
||||
bchtest:qz0…rasu9d · category "operational"
|
||||
source: Deviant/Keys/chipnet-keystore.json#gmx
|
||||
─────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
- Primary and sub-accounts always appear above imports. This is not just
|
||||
cosmetic — it reflects that the profile seed is the wallet's identity.
|
||||
- Imports are grouped by `category` when there are more than 5. `bns`,
|
||||
`bns-infra`, `operational`, `chipnet-test` collapse into collapsible groups.
|
||||
- Revoke removes an import (from `wallet-imports.enc`); it does NOT touch the
|
||||
on-chain material and warns clearly: "The on-chain wallet still exists. Its
|
||||
seed/WIF is only removed from this Theseus profile."
|
||||
- **No affordance to view seed / WIF material after import.** Recovery lives
|
||||
in the SOURCE (Deviant's keystore, or wherever the user got it from). §2.1
|
||||
shoulder-surf mitigation.
|
||||
|
||||
### 4.2 Sign-request modal — the account picker
|
||||
|
||||
Same modal as base doc §5, extended:
|
||||
|
||||
- Account row becomes `Signing as: [dropdown ▾]`.
|
||||
- Dropdown lists every unlocked account, grouped: Primary → sub-accounts → imports.
|
||||
- Each row shows label + truncated cashaddr + category chip.
|
||||
- Origin's "recently used" account is pre-selected (§2.2 above).
|
||||
- If the calling page passed `bcnr.requestAccount({ account: 'sirius.x' })`
|
||||
and the account exists, it's pre-selected. If it doesn't exist, the modal
|
||||
says "This site is asking for an account you don't have. Sign as:" and the
|
||||
user picks from what they do have.
|
||||
|
||||
### 4.3 Import flow
|
||||
|
||||
Two entry points, both in Settings > Wallet:
|
||||
|
||||
1. **"Import external wallet" → paste seed OR WIF.**
|
||||
The pasted string never renders back; the modal shows only what will be
|
||||
stored (`kind`, derived `cashaddr` truncated, `label` input, `category`
|
||||
picker).
|
||||
|
||||
2. **"Import from Deviant keystore" (if `D:/Dev/Deviant/Keys/chipnet-keystore.json`
|
||||
is reachable).** Detects the file, prompts for its master password (which
|
||||
must equal Theseus's — refuses otherwise with a clear message: "The Deviant
|
||||
keystore uses a different master password. Change one of them first."),
|
||||
decrypts, shows a preview list of every entry (label + cashaddr + category
|
||||
only), user picks which to import. Bulk-select shortcuts by category
|
||||
("all `bns`", "all `operational`").
|
||||
|
||||
The "different master password" rejection is a deliberate ergonomic
|
||||
constraint: we choose the pain of "unify your passwords once" over the pain
|
||||
of "which password unlocks what in this profile".
|
||||
|
||||
---
|
||||
|
||||
## 5. API surface for pages (deltas from §3 of base doc)
|
||||
|
||||
Backwards-compatible additions only:
|
||||
|
||||
```ts
|
||||
bcnr.requestAccount({ account?: string, category?: string }): Promise<string | null>
|
||||
// If neither `account` nor `category` given: current behaviour (returns cashaddr
|
||||
// of the default account, or null if not granted).
|
||||
// If `account`: requests a specific labelled account. Modal pre-selects it; if
|
||||
// it doesn't exist, the modal falls back to a picker over what the user has.
|
||||
// If `category`: requests any account in that category (e.g. "bns"). Useful
|
||||
// for the SilentMode registrar UI which knows it wants a BNS-holding wallet
|
||||
// but not which one.
|
||||
|
||||
bcnr.getAccounts({ category?: string }): Promise<Array<{
|
||||
cashaddr: string;
|
||||
label: string;
|
||||
category: string;
|
||||
}>>
|
||||
// Returns granted accounts. Optionally filtered by category. Note: the user
|
||||
// grants per-account, not per-category — this method never leaks accounts the
|
||||
// origin was not granted access to.
|
||||
```
|
||||
|
||||
The `bcnr.signMessage` / `bcnr.sendPayment` / `bcnr.registerName` signatures
|
||||
gain an optional `account?: string` parameter that pre-selects an account in
|
||||
the modal. Non-passing preserves current behaviour.
|
||||
|
||||
**Not added:** no method to import, revoke, or rename. All state-modifying
|
||||
account operations are settings-page only (§2.1).
|
||||
|
||||
---
|
||||
|
||||
## 6. Compatibility with Option A (the cross-repo loader that shipped 2026-09-09)
|
||||
|
||||
Option A lets `Argus/src/lib/wallet.js:loadWallet('sirius.x')` transparently
|
||||
read Deviant's encrypted keystore. That path is authoritative today and stays
|
||||
authoritative after this amendment ships:
|
||||
|
||||
- Theseus imports are **copies**, not sources of truth. Revoking an import in
|
||||
Theseus does not affect Deviant's keystore or SilentMode's `wallets.json`.
|
||||
- If the user rotates a key in Deviant's keystore, the corresponding Theseus
|
||||
import goes stale. Theseus should detect this by comparing derived
|
||||
`cashaddr` on unlock — a mismatch surfaces a banner: "The Deviant source of
|
||||
Sirius.x has changed since this import. [Re-import] or [Remove]."
|
||||
- The two systems remain independent by design. This is not a bug; it is the
|
||||
same discipline that keeps password-vault seeds separate from wallet seeds
|
||||
(§3.4 base doc).
|
||||
|
||||
---
|
||||
|
||||
## 7. Sequencing — where this slots into the base roadmap
|
||||
|
||||
Adds to the base doc's §7:
|
||||
|
||||
| Phase | What ships | Depends on |
|
||||
|---|---|---|
|
||||
| B.3d | Sub-account creation (primary purpose subtree, indexes 1..N) — `Trading` / `Savings` labels | B.3a shipped |
|
||||
| **M.1** | Import external seed / WIF, `wallet-imports.enc` file, account picker in sign modal | B.3b + `password-vault.js` shipped ✓ |
|
||||
| **M.2** | Import from Deviant keystore (file detection + bulk-select UX) | M.1 + `chipnet-keystore/2-encrypted` format stable ✓ |
|
||||
| **M.3** | `bcnr.requestAccount({ account, category })` + `getAccounts({ category })` API extensions | M.1 |
|
||||
| **M.4** | Stale-import detection (source-file cashaddr comparison) | M.2 |
|
||||
|
||||
M.1 is the load-bearing phase — everything else composes on top of the
|
||||
`wallet-imports.enc` file. M.2 through M.4 are refinements the user's specific
|
||||
setup makes worthwhile.
|
||||
|
||||
Do NOT ship M.2 (Deviant integration) before M.1 (generic import). The
|
||||
generic-first path keeps the design honest — if the amendment cannot be used
|
||||
by a user who never touches Deviant, we've over-fitted.
|
||||
|
||||
---
|
||||
|
||||
## 8. Open questions — decide before writing M.1 code
|
||||
|
||||
1. **What's the primary account's "category"?** Options: `primary` (mirrors
|
||||
the model), leave the field null, or use the user-picked purpose ("Personal
|
||||
spending"). *Recommend `primary` — it's the one category name that never
|
||||
collides with an import.*
|
||||
|
||||
2. **How does WizardConnect surface multi-account?** External pairings via
|
||||
`wiz://` — the `@wizardconnect/wallet@0.2.2` SDK's WalletAdapter has one
|
||||
`getXpub(path)` and one `signTransaction(request)`. Neither takes an
|
||||
account parameter. Options: pair-per-account (each account has its own
|
||||
`wiz://` URI); pair-per-profile with account selection at sign time (like
|
||||
in-page dApps); or accept that WizardConnect only exposes the primary
|
||||
account. *Recommend option 3 for M.1 (only-primary), revisit when a user
|
||||
asks. Multi-account WizardConnect is a real cross-cutting design that
|
||||
deserves its own doc.*
|
||||
|
||||
3. **Do we let the profile primary seed be *replaced* by an import?** The
|
||||
proposal above says no — imports are always in the imports file, and the
|
||||
primary purpose subtrees stay tied to the profile seed. A user who wants
|
||||
"my Deviant seed as the profile seed" would create a fresh profile and
|
||||
restore that seed at profile-creation. *Recommend keeping the restriction
|
||||
— it makes the sub-account / import distinction fundamental rather than
|
||||
optional.*
|
||||
|
||||
4. **Auto-lock behaviour with imports.** Auto-lock re-encrypts the primary
|
||||
purpose root under a session key (§6 base doc). Do we do the same for the
|
||||
imports? Or wipe the imports outright and force a re-decrypt on unlock?
|
||||
*Recommend the same treatment as primary — session-key re-encryption. The
|
||||
cost is symmetric.*
|
||||
|
||||
5. **Export.** Can the user export an imported wallet's key back out of
|
||||
Theseus? *Recommend no by default (§4.1 no-view-material rule), but a
|
||||
"Show recovery WIF for this import" behind master-password reprompt AND
|
||||
"why is this dangerous" panel (like the base doc §8.6 for the profile
|
||||
seed) is a reasonable escape hatch for users who need to move a wallet
|
||||
between machines.*
|
||||
|
||||
6. **Sub-account discovery.** If a user restores their profile seed on a new
|
||||
Theseus install, do we auto-scan chipnet for used sub-account addresses?
|
||||
*Recommend a "Scan for used sub-accounts" button in settings, not
|
||||
automatic. Scanning is a chain-load event; make the user ask for it.*
|
||||
|
||||
7. **Category taxonomy.** The Deviant keystore uses `bns`, `bns-infra`,
|
||||
`chipnet-test`, `operational`, `primary`, `hd-general`. Should Theseus
|
||||
enforce a fixed set or allow free-form strings? *Recommend free-form
|
||||
strings with the six above as autocomplete suggestions. Constraining now
|
||||
would force a v2 migration when a user coins a new category.*
|
||||
|
||||
---
|
||||
|
||||
## 9. What this amendment does NOT decide
|
||||
|
||||
- The wallet-imports file format after v1. Version-tag it now; iterate as
|
||||
needed. The `version: "silentmode/wallet-imports/1"` field exists precisely
|
||||
so a v2 migration is a well-defined event, not a guess.
|
||||
- The Deviant-side story. Deviant's `chipnet-keystore.json` continues to be
|
||||
read by Deviant scripts (via `scripts/lib/chipnet-keystore.mjs`) and by
|
||||
SilentMode's `Argus/src/lib/wallet.js` (via the Option A fall-through). This
|
||||
amendment adds a THIRD reader (Theseus) — it does not consolidate the two
|
||||
existing readers.
|
||||
- The mobile story. Ariadne (mobile companion, base doc §9) is out of scope.
|
||||
When it lands, the same `wallet-imports.enc` format ports over — that's the
|
||||
point of designing it version-tagged and portable.
|
||||
|
||||
---
|
||||
|
||||
## 10. Suggested acceptance path
|
||||
|
||||
If the reader agrees with this amendment:
|
||||
|
||||
1. Merge M.1 into the roadmap between B.3b and B.4 in
|
||||
`ROADMAP-identity-wallet.md`.
|
||||
2. Move the base doc's §0 "Multi-account UX. One account per Theseus profile
|
||||
in v1." to §9 "What this design does NOT decide, in v1 — this is now
|
||||
addressed by [`DESIGN-wallet-multi-account-amendment.md`](DESIGN-wallet-multi-account-amendment.md)".
|
||||
3. Address the open questions in §8 above in the roadmap discussion, not by
|
||||
editing this file — the design is stable, only the answers are open.
|
||||
|
||||
If the reader disagrees, the fallback path is what the base doc already
|
||||
implies: **host the Deviant wallet dApp inside Theseus, once `window.bcnr`
|
||||
ships** (base doc §4.4 — "External dApp using WizardConnect = Nostr relay",
|
||||
minus the Nostr relay because the dApp is loaded IN Theseus, not paired
|
||||
externally). That path requires no Theseus code changes beyond what B.2–B.4
|
||||
already deliver, and it inherits Deviant's own multi-account UX for free. The
|
||||
trade-off is that "my wallet" and "the Deviant wallet loaded in my wallet
|
||||
browser" become two things instead of one; this amendment is the case for
|
||||
one.
|
||||
Loading…
Add table
Reference in a new issue