@interop/wallet-core 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -127,6 +127,17 @@ The subpaths:
127
127
  (connect code, approval, completion) plus the onboarding-response envelope
128
128
  that carries a connect code back over an exchange.
129
129
 
130
+ - **`@interop/wallet-core/genesis`** -- the account-genesis ceremony: the local
131
+ mint of a brand-new account's complete key set (`mintAccountKeySet`: Space id,
132
+ client identity seed, user key, did:webvh update keys) and the staged
133
+ provisioning both apps must encode identically (`ensureAccountGenesis`: Space
134
+ provisioning, the optional KMS key-map acquisition, did:webvh genesis,
135
+ user-key roster genesis after DID publication, epoch[0] on every encrypted
136
+ roster collection, and the Space-controller promotion, also exported standing
137
+ alone as `ensurePromotedSpaceController`). Idempotent end to end: a torn run
138
+ heals by re-running. The keyring bind is deliberately not a stage, so a wallet
139
+ with no unlock method bound at creation drives the same ceremony.
140
+
130
141
  - **`@interop/wallet-core/recovery`** -- recovery codes on the roster identity
131
142
  model: a code as a minimal always-enrolled wallet client (format and
132
143
  derivation, the recovery record, the document half of issuance / revocation /
@@ -22,6 +22,15 @@
22
22
  * epoch after the one refresh is spent) propagates. A refresh that itself
23
23
  * fails does not count as spent -- the original `UnknownEpochError` is
24
24
  * rethrown and a later decrypt may try again.
25
+ *
26
+ * Only `UnknownEpochError` drives that refresh, and by design. The client
27
+ * splits the two ways a decrypt can find no key: an epoch the descriptor does
28
+ * not list at all raises `UnknownEpochError`, because a fresher descriptor may
29
+ * well list it; an epoch the descriptor does list but this reader holds no key
30
+ * for raises `KeyUnwrapError` (never a recipient, or removed and the epoch
31
+ * rotated). The second is rethrown immediately, with the refresh left
32
+ * untouched, since re-reading the same descriptor cannot produce a key the
33
+ * reader was not given.
25
34
  */
26
35
  import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
27
36
  import { type DocCipher } from '@interop/was-client/edv';
@@ -1 +1 @@
1
- {"version":3,"file":"cipher.d.ts","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EACb,EAAE;IACD,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACnC,MAAM,CAAC,EAAE,0BAA0B,CAAA;IACnC,KAAK,EAAE,yBAAyB,CAAA;IAChC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,GAAG,OAAO,CAAC,SAAS,CAAC,CAoFrB"}
1
+ {"version":3,"file":"cipher.d.ts","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EACb,EAAE;IACD,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACnC,MAAM,CAAC,EAAE,0BAA0B,CAAA;IACnC,KAAK,EAAE,yBAAyB,CAAA;IAChC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,GAAG,OAAO,CAAC,SAAS,CAAC,CAoFrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"AA6BA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,EACjD,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EASb;IACC,MAAM,KAAK,GAAG,KAAK,IAAwB,EAAE;QAC3C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;YACzC,MAAM;YACN,KAAK;YACL,YAAY;YACZ,YAAY;SACb,CAAC,CAAA;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,eAAe,YAAY,2CAA2C;gBACpE,kEAAkE;gBAClE,oEAAoE,CACvE,CAAA;QACH,CAAC;QACD,OAAO,kBAAkB,CAAC;YACxB,eAAe;YACf,WAAW;YACX,YAAY;YACZ,YAAY;YACZ,UAAU;SACX,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,IAAI,KAAK,GAAG,MAAM,KAAK,EAAE,CAAA;IACzB,0EAA0E;IAC1E,yEAAyE;IACzE,+CAA+C;IAC/C,IAAI,SAAS,GAAyB,IAAI,CAAA;IAE1C,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAE1C,aAAa,EAAE,OAAO,CAAC,EAAE;YACvB,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,eAAe,YAAY,kCAAkC,CAC9D,CAAA;YACH,CAAC;YACD,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE;YACxB,IAAI,CAAC;gBACH,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC1C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,GAAG,YAAY,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACnD,MAAM,GAAG,CAAA;gBACX,CAAC;gBACD,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;wBACpC,KAAK,GAAG,MAAM,CAAA;oBAChB,CAAC,CAAC,CAAA;oBACF,SAAS,GAAG,OAAO,CAAA;oBACnB,qEAAqE;oBACrE,oEAAoE;oBACpE,qEAAqE;oBACrE,mEAAmE;oBACnE,iEAAiE;oBACjE,0BAA0B;oBAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;wBACjB,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;4BAC1B,SAAS,GAAG,IAAI,CAAA;wBAClB,CAAC;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC;gBACD,IAAI,CAAC;oBACH,MAAM,SAAS,CAAA;gBACjB,CAAC;gBAAC,MAAM,CAAC;oBACP,mEAAmE;oBACnE,gEAAgE;oBAChE,+DAA+D;oBAC/D,mDAAmD;oBACnD,MAAM,GAAG,CAAA;gBACX,CAAC;gBACD,iEAAiE;gBACjE,8DAA8D;gBAC9D,+DAA+D;gBAC/D,iEAAiE;gBACjE,2BAA2B;gBAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YACpC,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"AAsCA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,EACjD,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EASb;IACC,MAAM,KAAK,GAAG,KAAK,IAAwB,EAAE;QAC3C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;YACzC,MAAM;YACN,KAAK;YACL,YAAY;YACZ,YAAY;SACb,CAAC,CAAA;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,eAAe,YAAY,2CAA2C;gBACpE,kEAAkE;gBAClE,oEAAoE,CACvE,CAAA;QACH,CAAC;QACD,OAAO,kBAAkB,CAAC;YACxB,eAAe;YACf,WAAW;YACX,YAAY;YACZ,YAAY;YACZ,UAAU;SACX,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,IAAI,KAAK,GAAG,MAAM,KAAK,EAAE,CAAA;IACzB,0EAA0E;IAC1E,yEAAyE;IACzE,+CAA+C;IAC/C,IAAI,SAAS,GAAyB,IAAI,CAAA;IAE1C,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAE1C,aAAa,EAAE,OAAO,CAAC,EAAE;YACvB,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,eAAe,YAAY,kCAAkC,CAC9D,CAAA;YACH,CAAC;YACD,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE;YACxB,IAAI,CAAC;gBACH,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC1C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,GAAG,YAAY,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACnD,MAAM,GAAG,CAAA;gBACX,CAAC;gBACD,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;wBACpC,KAAK,GAAG,MAAM,CAAA;oBAChB,CAAC,CAAC,CAAA;oBACF,SAAS,GAAG,OAAO,CAAA;oBACnB,qEAAqE;oBACrE,oEAAoE;oBACpE,qEAAqE;oBACrE,mEAAmE;oBACnE,iEAAiE;oBACjE,0BAA0B;oBAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;wBACjB,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;4BAC1B,SAAS,GAAG,IAAI,CAAA;wBAClB,CAAC;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC;gBACD,IAAI,CAAC;oBACH,MAAM,SAAS,CAAA;gBACjB,CAAC;gBAAC,MAAM,CAAC;oBACP,mEAAmE;oBACnE,gEAAgE;oBAChE,+DAA+D;oBAC/D,mDAAmD;oBACnD,MAAM,GAAG,CAAA;gBACX,CAAC;gBACD,iEAAiE;gBACjE,8DAA8D;gBAC9D,+DAA+D;gBAC/D,iEAAiE;gBACjE,2BAA2B;gBAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YACpC,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,206 @@
1
+ import type { CollectionEncryption, WasClient } from '@interop/was-client';
2
+ import type { EncryptionDescriptorStore } from '@interop/was-client/edv';
3
+ import type { IKeyAgreementKey } from '@interop/data-integrity-core';
4
+ import { type ClientWebvhUpdateKeys, type DidWebKeyMapV2, type ICapabilityAgent, type WebvhIdStore } from '../webvh/index.js';
5
+ import { type UserKey, type WalletSpaceEpochsResult } from '../keys/index.js';
6
+ import type { ResourceLogPinStore } from '../resourceLog/index.js';
7
+ /**
8
+ * The complete key set a brand-new account mints locally before anything
9
+ * touches the network: the data Space id, this founding client's identity
10
+ * seed, the account's user key, and the client-held did:webvh update-key
11
+ * seeds. Persisting the set durably (under the app's unlock layer) is the
12
+ * caller's job, and for the update keys it must happen BEFORE
13
+ * {@link ensureAccountGenesis} publishes anything -- the seeds are the only
14
+ * update authority the log will ever accept.
15
+ */
16
+ export interface AccountKeySet {
17
+ spaceId: string;
18
+ clientSeed: Uint8Array;
19
+ userKey: Required<UserKey>;
20
+ updateKeys: ClientWebvhUpdateKeys;
21
+ }
22
+ /**
23
+ * Mints a fresh data-Space id: 32 random bytes, base64url without padding.
24
+ * Random rather than controller-derived on purpose: the Space's controller is
25
+ * promoted to a did:webvh whose id embeds this Space id, so a
26
+ * controller-derived id would be circular.
27
+ *
28
+ * @returns {string}
29
+ */
30
+ export declare function mintSpaceId(): string;
31
+ /**
32
+ * Mints the complete key set of a brand-new account: a fresh Space id, a
33
+ * 32-byte client identity seed (expanded to the founding client's agents via
34
+ * `agentsFromSeed`), the account's user key, and the did:webvh update-key
35
+ * pair. Pure minting -- nothing here touches the network or any store.
36
+ *
37
+ * @returns {Promise<AccountKeySet>}
38
+ */
39
+ export declare function mintAccountKeySet(): Promise<AccountKeySet>;
40
+ /**
41
+ * What the promotion stage found and did: `promoted` (the Space Description
42
+ * named another controller -- on a fresh signup, this founding client's
43
+ * did:key -- and the ceremony moved it to the account DID), `confirmed` (the
44
+ * Space already names the account DID; nothing written), or `healed` (the
45
+ * Description was unreadable under the session's signing identity -- the torn
46
+ * state where the controller PUT never landed -- and the re-PUT signed as the
47
+ * stored did:key controller landed it).
48
+ */
49
+ export type SpaceControllerPromotion = 'promoted' | 'confirmed' | 'healed';
50
+ /**
51
+ * Promotes the data Space's controller to the account's did:webvh, as a state
52
+ * machine over the Space Description so every state a torn earlier run can
53
+ * leave behind converges:
54
+ *
55
+ * - The Description reads and already names `did`: nothing to do.
56
+ * - The Description reads and names another controller (a fresh signup: this
57
+ * founding client's did:key, which `was` is then signing as): one configure
58
+ * PUT moves it to `did`.
59
+ * - The Description is unreadable (`null` covers both absent and
60
+ * unauthorized): the torn case, where the session already signs under the
61
+ * did:webvh but the controller PUT never landed, so the server still
62
+ * authorizes only the stored did:key controller. The re-PUT goes through
63
+ * `wasAsClient`, the handle signing under this client's plain did:key.
64
+ *
65
+ * The PUT always carries the full `{ name, controller }` description, so the
66
+ * unreadable-Description merge guard in was-client's `configure` never
67
+ * defaults anything from a state this ceremony cannot see.
68
+ *
69
+ * @param options {object}
70
+ * @param options.was {WasClient} signing as the session currently signs
71
+ * (this client's did:key on a fresh signup; the promoted did:webvh keyId on
72
+ * a heal re-run)
73
+ * @param [options.wasAsClient] {WasClient} signing under this client's
74
+ * plain did:key, for the torn-promotion heal; omitted, that branch refuses
75
+ * instead of healing
76
+ * @param options.spaceId {string}
77
+ * @param options.did {string} the account's did:webvh DID
78
+ * @returns {Promise<SpaceControllerPromotion>}
79
+ */
80
+ export declare function ensurePromotedSpaceController({ was, wasAsClient, spaceId, did }: {
81
+ was: WasClient;
82
+ wasAsClient?: WasClient;
83
+ spaceId: string;
84
+ did: string;
85
+ }): Promise<SpaceControllerPromotion>;
86
+ /**
87
+ * The Space-provisioning stage of {@link ensureAccountGenesis} failed: the
88
+ * Space (or part of its collection roster) could not be ensured, so nothing
89
+ * downstream ran. Raised as its own class with a stable `name`, so a caller
90
+ * that treats the later stages as non-fatal can still let a missing Space
91
+ * propagate -- match it on `err.name === 'AccountGenesisSpaceError'`, never
92
+ * `instanceof` (the error can be raised by a linked or duplicated copy of
93
+ * this package).
94
+ */
95
+ export declare class AccountGenesisSpaceError extends Error {
96
+ constructor(options: {
97
+ spaceId: string;
98
+ cause: unknown;
99
+ });
100
+ }
101
+ /**
102
+ * The stages whose failures the ceremony collects instead of throwing (see
103
+ * the module doc for the split).
104
+ */
105
+ export type AccountGenesisStage = 'didWebKeys' | 'roster' | 'epochs' | 'promotion';
106
+ /**
107
+ * What a completed ceremony reports: the account DID, each collected stage's
108
+ * outcome where it ran (the roster descriptor, the per-collection epoch
109
+ * install -- whose own `failed` list stays inside it -- and what the
110
+ * promotion found), and the stages that failed on this run. A result with
111
+ * `failed` entries is a resumable success: the account exists and is
112
+ * identified, and a naive re-run of the whole ceremony finishes the rest.
113
+ */
114
+ export interface AccountGenesisResult {
115
+ did: string;
116
+ rosterDescriptor?: CollectionEncryption;
117
+ epochs?: WalletSpaceEpochsResult;
118
+ promotion?: SpaceControllerPromotion;
119
+ failed: Array<{
120
+ stage: AccountGenesisStage;
121
+ error: unknown;
122
+ }>;
123
+ }
124
+ /**
125
+ * Runs the account-genesis ceremony against an already-minted
126
+ * {@link AccountKeySet} (whose update-key seeds the caller has already
127
+ * persisted durably). Idempotent end to end: every stage adopts what an
128
+ * earlier run landed, so a torn run -- and a lost create race against a
129
+ * concurrent provisioner -- heals by re-running.
130
+ *
131
+ * Stage order (the module doc has the why): Space provisioning, the optional
132
+ * KMS key-map acquisition, did:webvh genesis, user-key roster genesis, the
133
+ * encrypted collections' epoch[0] install, Space-controller promotion.
134
+ *
135
+ * @param options {object}
136
+ * @param options.was {WasClient} signing as the session currently signs:
137
+ * this client's did:key on a fresh signup, the promoted did:webvh keyId on
138
+ * a heal re-run over an already-promoted account
139
+ * @param [options.wasAsClient] {WasClient} signing under this client's
140
+ * plain did:key, for the torn-promotion heal (see
141
+ * {@link ensurePromotedSpaceController})
142
+ * @param options.wasServerUrl {string} the storage server the account
143
+ * lives on; the did:webvh id embeds its host
144
+ * @param options.spaceId {string}
145
+ * @param options.keyAgent {ICapabilityAgent} this founding client's signing
146
+ * key agent (`agentsFromSeed` over the key set's `clientSeed`); its did:key
147
+ * id is the Space's controller at creation
148
+ * @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
149
+ * (identity) key-agreement key -- its published `keyAgreement` verification
150
+ * method, and the roster's first recipient
151
+ * @param options.userKey {UserKey} the account's user key, recipient zero
152
+ * of every encrypted collection and the roster's first epoch
153
+ * @param options.updateKeys {ClientWebvhUpdateKeys} the client-held
154
+ * did:webvh update-key seeds, already durably persisted
155
+ * @param options.idStore {WebvhIdStore} the account's `id` collection
156
+ * store the did:webvh ceremony reads and publishes through
157
+ * @param options.rosterStoreFor {Function} `({ did }) =>
158
+ * EncryptionDescriptorStore` -- builds the user-key roster's descriptor
159
+ * store once the account DID is known (the log-governed store's controller
160
+ * view and chain-head pin are the app's wiring)
161
+ * @param [options.provideDidWebKeys] {Function} `() =>
162
+ * Promise<DidWebKeyMapV2 | undefined>` -- the KMS key-map acquisition (a
163
+ * wallet that keeps a KMS runs its did:web provisioning here, after the
164
+ * Space exists); absent or resolving `undefined`, the genesis is
165
+ * client-keys-only and no `keys.json` is ever written. A throw is
166
+ * collected, not fatal: the genesis proceeds client-keys-only and a later
167
+ * run heals the document with the convenience key
168
+ * @param [options.expectedDid] {string} the account's did:webvh from the
169
+ * caller's stored account pointer, when it already names one; the genesis
170
+ * read then refuses a published log resolving to any other account
171
+ * @param [options.accountLogPinStore] {ResourceLogPinStore} this client's
172
+ * chain-head pin for the account log
173
+ * @param [options.onDidPublished] {Function} `({ did }) => Promise<void>`
174
+ * -- runs between the DID publication and the roster genesis, so the app
175
+ * can adopt the DID (and drop any verified-log memo) before the roster
176
+ * store's controller view resolves against the published document
177
+ * @param [options.promoteController] {boolean} whether to run the
178
+ * promotion stage (default `true`). An app whose account pointer must
179
+ * durably name the DID BEFORE the controller PUT lands -- and whose
180
+ * pointer write lives outside this call (freewallet's keyring re-bind) --
181
+ * passes `false` and runs {@link ensurePromotedSpaceController} itself
182
+ * after that write
183
+ * @returns {Promise<AccountGenesisResult>}
184
+ */
185
+ export declare function ensureAccountGenesis({ was, wasAsClient, wasServerUrl, spaceId, keyAgent, clientKeyAgreementKey, userKey, updateKeys, idStore, rosterStoreFor, provideDidWebKeys, expectedDid, accountLogPinStore, onDidPublished, promoteController }: {
186
+ was: WasClient;
187
+ wasAsClient?: WasClient;
188
+ wasServerUrl: string;
189
+ spaceId: string;
190
+ keyAgent: ICapabilityAgent;
191
+ clientKeyAgreementKey: IKeyAgreementKey;
192
+ userKey: UserKey;
193
+ updateKeys: ClientWebvhUpdateKeys;
194
+ idStore: WebvhIdStore;
195
+ rosterStoreFor: (options: {
196
+ did: string;
197
+ }) => EncryptionDescriptorStore;
198
+ provideDidWebKeys?: () => Promise<DidWebKeyMapV2 | undefined>;
199
+ expectedDid?: string;
200
+ accountLogPinStore?: ResourceLogPinStore;
201
+ onDidPublished?: (published: {
202
+ did: string;
203
+ }) => Promise<void>;
204
+ promoteController?: boolean;
205
+ }): Promise<AccountGenesisResult>;
206
+ //# sourceMappingURL=accountGenesis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountGenesis.d.ts","sourceRoot":"","sources":["../../src/genesis/accountGenesis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,294 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The account-genesis ceremony: minting a brand-new wallet account's key set
6
+ * and provisioning its data Space, in the one stage order every wallet app
7
+ * must encode identically -- Space provisioning, did:webvh genesis, user-key
8
+ * roster genesis (after DID publication, so the roster log's entry proofs
9
+ * anchor in the published document), epoch[0] on every encrypted roster
10
+ * collection, and Space-controller promotion.
11
+ *
12
+ * Two callers, one ceremony. A wallet that keeps a KMS (freewallet) supplies
13
+ * `provideDidWebKeys` and gets the KMS-backed did:webvh genesis; a wallet
14
+ * with no KMS anywhere in the path (dcw) supplies nothing and gets the
15
+ * client-keys-only genesis. The keyring bind is deliberately NOT a stage:
16
+ * where an app binds an unlock method (and whether it binds one at all)
17
+ * stays app-side, as does the `userExists` probe -- that probe exists only
18
+ * because a passphrase signup can collide with an existing account, which is
19
+ * an unlock-layer concern, not an account-genesis one.
20
+ *
21
+ * Every stage detects its own completion from durable state alone (the
22
+ * cascade/sweep posture): the Space provisioning and the epoch install are
23
+ * create-if-absent and adopt what an earlier provisioner landed, the
24
+ * did:webvh genesis probes `did.jsonl` and adopts a log its seeds still
25
+ * authorize, the roster genesis returns an existing roster untouched, and
26
+ * the promotion is a state machine over the Space Description. So a torn run
27
+ * heals by naively re-running the whole ceremony, backstopped by the
28
+ * login-time sweeps.
29
+ *
30
+ * The essential identity chain -- Space provisioning and the did:webvh
31
+ * genesis -- throws on failure (nothing downstream can proceed without it);
32
+ * the stages after it are collected in `failed` instead, so a transient
33
+ * failure on one never costs the caller the others' outcomes -- a completed
34
+ * call with `failed` entries is a resumable success, finished by a re-run.
35
+ */
36
+ import { base64urlnopad } from '@scure/base';
37
+ import { provisionWalletSpace, WALLET_SPACE_NAME } from '../space/index.js';
38
+ import { clientSigningKeyMultibase, ensureDidWebvh, mintClientWebvhUpdateKeys } from '../webvh/index.js';
39
+ import { ensureUserKeyRoster, ensureWalletSpaceEpochs, mintUserKey } from '../keys/index.js';
40
+ /**
41
+ * The byte length of a freshly minted data-Space id.
42
+ */
43
+ const SPACE_ID_BYTES = 32;
44
+ /**
45
+ * Mints a fresh data-Space id: 32 random bytes, base64url without padding.
46
+ * Random rather than controller-derived on purpose: the Space's controller is
47
+ * promoted to a did:webvh whose id embeds this Space id, so a
48
+ * controller-derived id would be circular.
49
+ *
50
+ * @returns {string}
51
+ */
52
+ export function mintSpaceId() {
53
+ return base64urlnopad.encode(crypto.getRandomValues(new Uint8Array(SPACE_ID_BYTES)));
54
+ }
55
+ /**
56
+ * Mints the complete key set of a brand-new account: a fresh Space id, a
57
+ * 32-byte client identity seed (expanded to the founding client's agents via
58
+ * `agentsFromSeed`), the account's user key, and the did:webvh update-key
59
+ * pair. Pure minting -- nothing here touches the network or any store.
60
+ *
61
+ * @returns {Promise<AccountKeySet>}
62
+ */
63
+ export async function mintAccountKeySet() {
64
+ const clientSeed = crypto.getRandomValues(new Uint8Array(32));
65
+ return {
66
+ spaceId: mintSpaceId(),
67
+ clientSeed,
68
+ userKey: await mintUserKey(),
69
+ updateKeys: await mintClientWebvhUpdateKeys()
70
+ };
71
+ }
72
+ /**
73
+ * Promotes the data Space's controller to the account's did:webvh, as a state
74
+ * machine over the Space Description so every state a torn earlier run can
75
+ * leave behind converges:
76
+ *
77
+ * - The Description reads and already names `did`: nothing to do.
78
+ * - The Description reads and names another controller (a fresh signup: this
79
+ * founding client's did:key, which `was` is then signing as): one configure
80
+ * PUT moves it to `did`.
81
+ * - The Description is unreadable (`null` covers both absent and
82
+ * unauthorized): the torn case, where the session already signs under the
83
+ * did:webvh but the controller PUT never landed, so the server still
84
+ * authorizes only the stored did:key controller. The re-PUT goes through
85
+ * `wasAsClient`, the handle signing under this client's plain did:key.
86
+ *
87
+ * The PUT always carries the full `{ name, controller }` description, so the
88
+ * unreadable-Description merge guard in was-client's `configure` never
89
+ * defaults anything from a state this ceremony cannot see.
90
+ *
91
+ * @param options {object}
92
+ * @param options.was {WasClient} signing as the session currently signs
93
+ * (this client's did:key on a fresh signup; the promoted did:webvh keyId on
94
+ * a heal re-run)
95
+ * @param [options.wasAsClient] {WasClient} signing under this client's
96
+ * plain did:key, for the torn-promotion heal; omitted, that branch refuses
97
+ * instead of healing
98
+ * @param options.spaceId {string}
99
+ * @param options.did {string} the account's did:webvh DID
100
+ * @returns {Promise<SpaceControllerPromotion>}
101
+ */
102
+ export async function ensurePromotedSpaceController({ was, wasAsClient, spaceId, did }) {
103
+ const space = was.space(spaceId);
104
+ const description = await space.describe();
105
+ if (description !== null) {
106
+ if (description.controller === did) {
107
+ return 'confirmed';
108
+ }
109
+ await space.configure({ name: WALLET_SPACE_NAME, controller: did });
110
+ return 'promoted';
111
+ }
112
+ if (!wasAsClient) {
113
+ throw new Error('The Space Description is unreadable under the current signing ' +
114
+ 'identity and no did:key-signed client was supplied to heal a torn ' +
115
+ 'controller promotion.');
116
+ }
117
+ await wasAsClient
118
+ .space(spaceId)
119
+ .configure({ name: WALLET_SPACE_NAME, controller: did });
120
+ return 'healed';
121
+ }
122
+ /**
123
+ * The Space-provisioning stage of {@link ensureAccountGenesis} failed: the
124
+ * Space (or part of its collection roster) could not be ensured, so nothing
125
+ * downstream ran. Raised as its own class with a stable `name`, so a caller
126
+ * that treats the later stages as non-fatal can still let a missing Space
127
+ * propagate -- match it on `err.name === 'AccountGenesisSpaceError'`, never
128
+ * `instanceof` (the error can be raised by a linked or duplicated copy of
129
+ * this package).
130
+ */
131
+ export class AccountGenesisSpaceError extends Error {
132
+ constructor(options) {
133
+ super(`Provisioning the wallet Space "${options.spaceId}" failed; ` +
134
+ 'the account-genesis ceremony did not proceed.', { cause: options.cause });
135
+ this.name = 'AccountGenesisSpaceError';
136
+ }
137
+ }
138
+ /**
139
+ * Runs the account-genesis ceremony against an already-minted
140
+ * {@link AccountKeySet} (whose update-key seeds the caller has already
141
+ * persisted durably). Idempotent end to end: every stage adopts what an
142
+ * earlier run landed, so a torn run -- and a lost create race against a
143
+ * concurrent provisioner -- heals by re-running.
144
+ *
145
+ * Stage order (the module doc has the why): Space provisioning, the optional
146
+ * KMS key-map acquisition, did:webvh genesis, user-key roster genesis, the
147
+ * encrypted collections' epoch[0] install, Space-controller promotion.
148
+ *
149
+ * @param options {object}
150
+ * @param options.was {WasClient} signing as the session currently signs:
151
+ * this client's did:key on a fresh signup, the promoted did:webvh keyId on
152
+ * a heal re-run over an already-promoted account
153
+ * @param [options.wasAsClient] {WasClient} signing under this client's
154
+ * plain did:key, for the torn-promotion heal (see
155
+ * {@link ensurePromotedSpaceController})
156
+ * @param options.wasServerUrl {string} the storage server the account
157
+ * lives on; the did:webvh id embeds its host
158
+ * @param options.spaceId {string}
159
+ * @param options.keyAgent {ICapabilityAgent} this founding client's signing
160
+ * key agent (`agentsFromSeed` over the key set's `clientSeed`); its did:key
161
+ * id is the Space's controller at creation
162
+ * @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
163
+ * (identity) key-agreement key -- its published `keyAgreement` verification
164
+ * method, and the roster's first recipient
165
+ * @param options.userKey {UserKey} the account's user key, recipient zero
166
+ * of every encrypted collection and the roster's first epoch
167
+ * @param options.updateKeys {ClientWebvhUpdateKeys} the client-held
168
+ * did:webvh update-key seeds, already durably persisted
169
+ * @param options.idStore {WebvhIdStore} the account's `id` collection
170
+ * store the did:webvh ceremony reads and publishes through
171
+ * @param options.rosterStoreFor {Function} `({ did }) =>
172
+ * EncryptionDescriptorStore` -- builds the user-key roster's descriptor
173
+ * store once the account DID is known (the log-governed store's controller
174
+ * view and chain-head pin are the app's wiring)
175
+ * @param [options.provideDidWebKeys] {Function} `() =>
176
+ * Promise<DidWebKeyMapV2 | undefined>` -- the KMS key-map acquisition (a
177
+ * wallet that keeps a KMS runs its did:web provisioning here, after the
178
+ * Space exists); absent or resolving `undefined`, the genesis is
179
+ * client-keys-only and no `keys.json` is ever written. A throw is
180
+ * collected, not fatal: the genesis proceeds client-keys-only and a later
181
+ * run heals the document with the convenience key
182
+ * @param [options.expectedDid] {string} the account's did:webvh from the
183
+ * caller's stored account pointer, when it already names one; the genesis
184
+ * read then refuses a published log resolving to any other account
185
+ * @param [options.accountLogPinStore] {ResourceLogPinStore} this client's
186
+ * chain-head pin for the account log
187
+ * @param [options.onDidPublished] {Function} `({ did }) => Promise<void>`
188
+ * -- runs between the DID publication and the roster genesis, so the app
189
+ * can adopt the DID (and drop any verified-log memo) before the roster
190
+ * store's controller view resolves against the published document
191
+ * @param [options.promoteController] {boolean} whether to run the
192
+ * promotion stage (default `true`). An app whose account pointer must
193
+ * durably name the DID BEFORE the controller PUT lands -- and whose
194
+ * pointer write lives outside this call (freewallet's keyring re-bind) --
195
+ * passes `false` and runs {@link ensurePromotedSpaceController} itself
196
+ * after that write
197
+ * @returns {Promise<AccountGenesisResult>}
198
+ */
199
+ export async function ensureAccountGenesis({ was, wasAsClient, wasServerUrl, spaceId, keyAgent, clientKeyAgreementKey, userKey, updateKeys, idStore, rosterStoreFor, provideDidWebKeys, expectedDid, accountLogPinStore, onDidPublished, promoteController = true }) {
200
+ const failed = [];
201
+ // 1. The Space and its collection roster, create-if-absent under this
202
+ // founding client's did:key controller (adopted untouched when it exists).
203
+ // Raised as the typed refusal so a caller that treats the later stages as
204
+ // non-fatal can still propagate a Space that never came up.
205
+ try {
206
+ await provisionWalletSpace({ was, spaceId, controllerDid: keyAgent.id });
207
+ }
208
+ catch (err) {
209
+ throw new AccountGenesisSpaceError({ spaceId, cause: err });
210
+ }
211
+ // 2. The optional KMS key map, acquired only once the Space exists (a
212
+ // KMS-keeping wallet writes keys.json and did.json into it here). A throw
213
+ // degrades to the client-keys-only genesis rather than aborting: every
214
+ // later ceremony anchors in client keys, and the first KMS-capable re-run
215
+ // heals the document with the convenience key.
216
+ let didWebKeys;
217
+ if (provideDidWebKeys) {
218
+ try {
219
+ didWebKeys = await provideDidWebKeys();
220
+ }
221
+ catch (err) {
222
+ failed.push({ stage: 'didWebKeys', error: err });
223
+ }
224
+ }
225
+ // 3. The did:webvh genesis -- probe, adopt, or create-and-publish. Fatal on
226
+ // failure: the account DID is what every remaining stage anchors in.
227
+ const { publicKeyMultibase: keyAgreementKeyMultibase } = clientKeyAgreementKey;
228
+ if (!keyAgreementKeyMultibase) {
229
+ throw new Error('The client key-agreement key has no public multibase.');
230
+ }
231
+ const { did } = await ensureDidWebvh({
232
+ idStore,
233
+ wasServerUrl,
234
+ spaceId,
235
+ ...(didWebKeys ? { didWebKeys } : {}),
236
+ clientKeys: {
237
+ signingKeyMultibase: clientSigningKeyMultibase({ keyAgent }),
238
+ keyAgreementKeyMultibase
239
+ },
240
+ updateKeys,
241
+ ...(expectedDid !== undefined ? { expectedDid } : {}),
242
+ ...(accountLogPinStore ? { pinStore: accountLogPinStore } : {})
243
+ });
244
+ await onDidPublished?.({ did });
245
+ // 4. The user-key roster genesis, strictly after the DID publication: the
246
+ // roster log's entry proofs anchor in the published document, so a roster
247
+ // created first could never verify.
248
+ let rosterDescriptor;
249
+ try {
250
+ rosterDescriptor = await ensureUserKeyRoster({
251
+ store: rosterStoreFor({ did }),
252
+ userKey,
253
+ clientKeyAgreementKey
254
+ });
255
+ }
256
+ catch (err) {
257
+ failed.push({ stage: 'roster', error: err });
258
+ }
259
+ // 5. Epoch[0] on every encrypted roster collection, wrapped to the user
260
+ // key. Its own per-collection failures stay inside the result (`epochs
261
+ // .failed`); only a fan-out that could not run at all lands here.
262
+ let epochs;
263
+ try {
264
+ epochs = await ensureWalletSpaceEpochs({ was, spaceId, userKey });
265
+ }
266
+ catch (err) {
267
+ failed.push({ stage: 'epochs', error: err });
268
+ }
269
+ // 6. The controller promotion, last: every earlier stage ran under the
270
+ // signing identity the Space's stored controller authorizes. Skipped when
271
+ // the caller's account-pointer write must land first (see the JSDoc).
272
+ let promotion;
273
+ if (promoteController) {
274
+ try {
275
+ promotion = await ensurePromotedSpaceController({
276
+ was,
277
+ ...(wasAsClient ? { wasAsClient } : {}),
278
+ spaceId,
279
+ did
280
+ });
281
+ }
282
+ catch (err) {
283
+ failed.push({ stage: 'promotion', error: err });
284
+ }
285
+ }
286
+ return {
287
+ did,
288
+ ...(rosterDescriptor ? { rosterDescriptor } : {}),
289
+ ...(epochs ? { epochs } : {}),
290
+ ...(promotion ? { promotion } : {}),
291
+ failed
292
+ };
293
+ }
294
+ //# sourceMappingURL=accountGenesis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountGenesis.js","sourceRoot":"","sources":["../../src/genesis/accountGenesis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/genesis` subpath: the account-genesis ceremony --
6
+ * minting a brand-new account's key set and provisioning its data Space in
7
+ * the one stage order both wallet apps must encode identically.
8
+ *
9
+ * - `mintAccountKeySet` / `mintSpaceId` -- the local mint of a new account's
10
+ * complete key set (Space id, client identity seed, user key, did:webvh
11
+ * update keys), before anything touches the network.
12
+ * - `ensureAccountGenesis` -- the ceremony itself: Space provisioning, the
13
+ * optional KMS key-map acquisition, did:webvh genesis, user-key roster
14
+ * genesis, epoch[0] on every encrypted roster collection, and
15
+ * Space-controller promotion; idempotent end to end, so a torn run heals
16
+ * by re-running.
17
+ * - `ensurePromotedSpaceController` -- the promotion stage standing alone,
18
+ * the state machine a login-time heal drives directly.
19
+ */
20
+ export { AccountGenesisSpaceError, ensureAccountGenesis, ensurePromotedSpaceController, mintAccountKeySet, mintSpaceId } from './accountGenesis.js';
21
+ export type { AccountGenesisResult, AccountGenesisStage, AccountKeySet, SpaceControllerPromotion } from './accountGenesis.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/genesis/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACZ,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,wBAAwB,EACzB,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/genesis` subpath: the account-genesis ceremony --
6
+ * minting a brand-new account's key set and provisioning its data Space in
7
+ * the one stage order both wallet apps must encode identically.
8
+ *
9
+ * - `mintAccountKeySet` / `mintSpaceId` -- the local mint of a new account's
10
+ * complete key set (Space id, client identity seed, user key, did:webvh
11
+ * update keys), before anything touches the network.
12
+ * - `ensureAccountGenesis` -- the ceremony itself: Space provisioning, the
13
+ * optional KMS key-map acquisition, did:webvh genesis, user-key roster
14
+ * genesis, epoch[0] on every encrypted roster collection, and
15
+ * Space-controller promotion; idempotent end to end, so a torn run heals
16
+ * by re-running.
17
+ * - `ensurePromotedSpaceController` -- the promotion stage standing alone,
18
+ * the state machine a login-time heal drives directly.
19
+ */
20
+ export { AccountGenesisSpaceError, ensureAccountGenesis, ensurePromotedSpaceController, mintAccountKeySet, mintSpaceId } from './accountGenesis.js';
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/genesis/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACZ,MAAM,qBAAqB,CAAA"}
@@ -44,6 +44,8 @@
44
44
  * - `ensureWalletSpaceEpochs` -- the provision-time epoch[0] install for the
45
45
  * wallet Space's encrypted collections, the EDV-bearing second step of
46
46
  * `provisionWalletSpace`.
47
+ * - `ensureIndexedFirstEpoch` -- one collection's epoch[0] plus its
48
+ * blinded-index HMAC key, adopting a pre-blind-index roster as-is.
47
49
  */
48
50
  export { mintUserKey, userKeyVaultKeys } from './userKey.js';
49
51
  export type { UserKey } from './userKey.js';
@@ -56,7 +58,7 @@ export type { UserKeyRosterReadResult, RosterRecipientDocument } from './userKey
56
58
  export { userKeyRosterDescriptorStore } from './rosterStore.js';
57
59
  export { EPOCH_CONFIGURATION_STATE_TYPE, isSealableDescriptorStore, logGovernedDescriptorStore } from './rosterLogStore.js';
58
60
  export type { SealableEncryptionDescriptorStore } from './rosterLogStore.js';
59
- export { ensureWalletSpaceEpochs } from './spaceEpochs.js';
61
+ export { ensureIndexedFirstEpoch, ensureWalletSpaceEpochs } from './spaceEpochs.js';
60
62
  export type { WalletSpaceEpochsResult } from './spaceEpochs.js';
61
63
  export { readClientLabels, removeClientLabel, setClientLabel } from './clientLabels.js';
62
64
  export type { ClientLabelsRecord, ClientLabelsStore } from './clientLabels.js';