@interop/wallet-core 0.6.0 → 0.8.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.
Files changed (62) hide show
  1. package/README.md +31 -3
  2. package/dist/descriptors/acquire.d.ts +110 -0
  3. package/dist/descriptors/acquire.d.ts.map +1 -0
  4. package/dist/descriptors/acquire.js +86 -0
  5. package/dist/descriptors/acquire.js.map +1 -0
  6. package/dist/descriptors/cipher.d.ts +56 -0
  7. package/dist/descriptors/cipher.d.ts.map +1 -0
  8. package/dist/descriptors/cipher.js +73 -0
  9. package/dist/descriptors/cipher.js.map +1 -0
  10. package/dist/descriptors/index.d.ts +32 -0
  11. package/dist/descriptors/index.d.ts.map +1 -0
  12. package/dist/descriptors/index.js +31 -0
  13. package/dist/descriptors/index.js.map +1 -0
  14. package/dist/descriptors/refresh.d.ts +60 -0
  15. package/dist/descriptors/refresh.d.ts.map +1 -0
  16. package/dist/descriptors/refresh.js +67 -0
  17. package/dist/descriptors/refresh.js.map +1 -0
  18. package/dist/enrollment/enrollment.d.ts +4 -4
  19. package/dist/enrollment/enrollment.d.ts.map +1 -1
  20. package/dist/enrollment/enrollment.js +4 -4
  21. package/dist/enrollment/enrollment.js.map +1 -1
  22. package/dist/index.d.ts +9 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +9 -4
  25. package/dist/index.js.map +1 -1
  26. package/dist/keys/index.d.ts +7 -6
  27. package/dist/keys/index.d.ts.map +1 -1
  28. package/dist/keys/index.js +7 -6
  29. package/dist/keys/index.js.map +1 -1
  30. package/dist/keys/pukRoster.d.ts +24 -20
  31. package/dist/keys/pukRoster.d.ts.map +1 -1
  32. package/dist/keys/pukRoster.js +27 -24
  33. package/dist/keys/pukRoster.js.map +1 -1
  34. package/dist/keys/rosterStore.d.ts +6 -6
  35. package/dist/keys/rosterStore.d.ts.map +1 -1
  36. package/dist/keys/rosterStore.js +7 -7
  37. package/dist/keys/rosterStore.js.map +1 -1
  38. package/dist/recovery/index.d.ts +31 -0
  39. package/dist/recovery/index.d.ts.map +1 -0
  40. package/dist/recovery/index.js +28 -0
  41. package/dist/recovery/index.js.map +1 -0
  42. package/dist/recovery/recoveryCode.d.ts +105 -0
  43. package/dist/recovery/recoveryCode.d.ts.map +1 -0
  44. package/dist/recovery/recoveryCode.js +155 -0
  45. package/dist/recovery/recoveryCode.js.map +1 -0
  46. package/dist/recovery/recoveryRecord.d.ts +75 -0
  47. package/dist/recovery/recoveryRecord.d.ts.map +1 -0
  48. package/dist/recovery/recoveryRecord.js +89 -0
  49. package/dist/recovery/recoveryRecord.js.map +1 -0
  50. package/dist/recovery/recoveryWebvh.d.ts +126 -0
  51. package/dist/recovery/recoveryWebvh.d.ts.map +1 -0
  52. package/dist/recovery/recoveryWebvh.js +379 -0
  53. package/dist/recovery/recoveryWebvh.js.map +1 -0
  54. package/dist/space/collections.d.ts +1 -1
  55. package/dist/space/collections.js +1 -1
  56. package/dist/sync/collections.d.ts +2 -1
  57. package/dist/sync/collections.d.ts.map +1 -1
  58. package/dist/webvh/didWebvh.d.ts +79 -0
  59. package/dist/webvh/didWebvh.d.ts.map +1 -1
  60. package/dist/webvh/didWebvh.js +5 -5
  61. package/dist/webvh/didWebvh.js.map +1 -1
  62. package/package.json +14 -2
@@ -0,0 +1,379 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The did:webvh half of recovery-code lifecycle: the split posture the
6
+ * roster identity model gives a code. At issuance the document gains the
7
+ * code's `keyAgreement` verification method (an ordinary Multikey entry --
8
+ * deliberately unmarked; a recovery key is distinguishable structurally,
9
+ * since it appears ONLY under `keyAgreement` while every enrolled client
10
+ * also publishes signing relationships, so client listings key on
11
+ * `capabilityInvocation` and never see it) and `nextKeyHashes` gains the
12
+ * code's update-key hash -- decryption standing, authority latent: the
13
+ * code's update key joins `updateKeys` nowhere, and its material exists
14
+ * nowhere until the code is typed.
15
+ *
16
+ * At recovery time the pre-committed update key reveals itself to sign the
17
+ * self-enrolling continuation, two entries:
18
+ *
19
+ * 1. **Reveal + commit**: the code's update key joins `updateKeys` (its hash
20
+ * stands committed since issuance, which is what makes the entry verify)
21
+ * and `nextKeyHashes` extends with the NEW ordinary client's update- and
22
+ * staged-key hashes plus the replacement code's update-key hash.
23
+ * 2. **Add + retire**: signed by the new client's update key (revealed from
24
+ * the commit), this entry publishes the new client's verification methods
25
+ * and update key, removes the spent code's `keyAgreement` VM, publishes
26
+ * the replacement code's, and drops the spent code's update key and hash
27
+ * -- so no recovery authority stands afterwards.
28
+ *
29
+ * Both entries are written through the caller's store seam; the recovery
30
+ * continuation publishes ONLY `did.jsonl` (the delegation the record carries
31
+ * covers nothing else -- narrow scope preserves loudness), and hands back the
32
+ * final `webDoc` so the recovered session can republish `did.json` once it is
33
+ * the authorized controller. Every step is idempotent/resumable: re-running
34
+ * with the same key material converges without forking the log.
35
+ */
36
+ import { deriveNextKeyHash, logToJsonlString, updateDID } from '@interop/did-method-webvh';
37
+ import { DID_LOG_RESOURCE } from '../space/collections.js';
38
+ import { MULTIKEY_VM_TYPE, publishWebvhLog, readPublishedLog, relationIds, updateKeyMultibase, updateKeySigner } from '../webvh/didWebvh.js';
39
+ /**
40
+ * The verification-method id a code's key-agreement key publishes under --
41
+ * the ordinary `<did>#<multibase>` form, indistinguishable by id from any
42
+ * other keyAgreement entry. Consumers that must exclude recovery entries do
43
+ * it structurally (an enrolled client is a `capabilityInvocation` entry; a
44
+ * recovery key never has one) or by the registry's recorded multibase.
45
+ *
46
+ * @param options {object}
47
+ * @param options.did {string} the account's did:webvh
48
+ * @param options.keyAgreementKeyMultibase {string}
49
+ * @returns {string}
50
+ */
51
+ export function recoveryVmId({ did, keyAgreementKeyMultibase }) {
52
+ return `${did}#${keyAgreementKeyMultibase}`;
53
+ }
54
+ /**
55
+ * Thrown by the recovery continuation when the log carries neither the code's
56
+ * update key nor its committed hash -- the code was revoked (or never
57
+ * issued), so no continuation can verify.
58
+ */
59
+ export class RecoveryKeyNotCommittedError extends Error {
60
+ constructor(message = 'The account log no longer commits this recovery code; the ' +
61
+ 'code has been revoked or was never issued.') {
62
+ super(message);
63
+ this.name = 'RecoveryKeyNotCommittedError';
64
+ }
65
+ }
66
+ /**
67
+ * Reads and resolves the published log through the narrow recovery seam.
68
+ *
69
+ * @param options {object}
70
+ * @param options.store {RecoveryLogStore}
71
+ * @returns {Promise<PublishedWebvhLog>}
72
+ */
73
+ async function readLogOrThrow({ store }) {
74
+ // readPublishedLog only calls getIdResourceRaw, so the narrow seam is safe.
75
+ const published = await readPublishedLog({
76
+ idStore: store
77
+ });
78
+ if (!published) {
79
+ throw new Error('did:webvh: did.jsonl is missing; nothing to recover.');
80
+ }
81
+ return published;
82
+ }
83
+ /**
84
+ * Publishes `did.jsonl` through the narrow recovery seam -- the log only,
85
+ * never `did.json` (the delegation covers nothing else; the recovered
86
+ * session republishes the projection once it is the controller).
87
+ *
88
+ * @param options {object}
89
+ * @param options.store {RecoveryLogStore}
90
+ * @param options.log {object}
91
+ * @returns {Promise<void>}
92
+ */
93
+ async function publishLogOnly({ store, log }) {
94
+ await store.putIdResource({
95
+ resourceId: DID_LOG_RESOURCE,
96
+ content: logToJsonlString(log),
97
+ contentType: 'text/jsonl'
98
+ });
99
+ }
100
+ /**
101
+ * Asserts the carry-over commitment convention holds for every currently
102
+ * authorized update key -- the precondition for any entry that re-states
103
+ * `updateKeys` (the resolver checks the re-stated set against the previous
104
+ * entry's `nextKeyHashes`).
105
+ *
106
+ * @param options {object}
107
+ * @param options.published {PublishedWebvhLog}
108
+ * @returns {Promise<void>}
109
+ */
110
+ async function assertCarryOverCommitments({ published }) {
111
+ for (const key of published.updateKeys) {
112
+ if (!published.nextKeyHashes.includes(await deriveNextKeyHash(key))) {
113
+ throw new Error('did:webvh: the published log does not carry the active update ' +
114
+ "keys' own hashes in nextKeyHashes (it predates the carry-over " +
115
+ 'commitment convention); re-provision the account first.');
116
+ }
117
+ }
118
+ }
119
+ /**
120
+ * ISSUANCE (run by an enrolled client, root authority): publishes a recovery
121
+ * code's split posture into the document -- one entry adding the code's
122
+ * `keyAgreement` verification method (an ordinary, unmarked Multikey entry)
123
+ * and committing its update-key hash in `nextKeyHashes`. The code's update
124
+ * key joins `updateKeys` nowhere. Idempotent: a posture already published is
125
+ * a no-op, so re-running a torn issuance converges.
126
+ *
127
+ * @param options {object}
128
+ * @param options.idStore {WebvhIdStore}
129
+ * @param options.updateKeys {ClientWebvhUpdateKeys} the ISSUING client's
130
+ * own did:webvh update-key seeds
131
+ * @param options.recovery {RecoveryPublicKeys} the code's public halves
132
+ * @returns {Promise<{ did: string }>}
133
+ */
134
+ export async function publishRecoveryKey({ idStore, updateKeys, recovery }) {
135
+ const published = await readLogOrThrow({ store: idStore });
136
+ const { did, doc } = published;
137
+ const recoveryHash = await deriveNextKeyHash(recovery.updateKeyMultibase);
138
+ const vmId = recoveryVmId({
139
+ did,
140
+ keyAgreementKeyMultibase: recovery.keyAgreementKeyMultibase
141
+ });
142
+ const vmPresent = (doc.verificationMethod ?? []).some(method => method.id === vmId);
143
+ const hashCommitted = published.nextKeyHashes.includes(recoveryHash);
144
+ if (vmPresent && hashCommitted) {
145
+ return { did };
146
+ }
147
+ const activeKey = await updateKeyMultibase({ seed: updateKeys.updateSeed });
148
+ if (!published.updateKeys.includes(activeKey)) {
149
+ throw new Error("did:webvh: the published log does not authorize this client's active " +
150
+ 'update key; finalize the pending rotation before issuing a ' +
151
+ 'recovery code.');
152
+ }
153
+ await assertCarryOverCommitments({ published });
154
+ const existingMethods = (doc.verificationMethod ?? []);
155
+ const recoveryMethod = {
156
+ id: vmId,
157
+ type: MULTIKEY_VM_TYPE,
158
+ controller: did,
159
+ publicKeyMultibase: recovery.keyAgreementKeyMultibase
160
+ };
161
+ const signer = await updateKeySigner({ seed: updateKeys.updateSeed });
162
+ const updated = await updateDID({
163
+ log: published.log,
164
+ signer,
165
+ updateKeys: published.updateKeys,
166
+ nextKeyHashes: [...new Set([...published.nextKeyHashes, recoveryHash])],
167
+ verificationMethods: [
168
+ ...existingMethods.filter(method => method.id !== vmId),
169
+ recoveryMethod
170
+ ],
171
+ authentication: relationIds(doc.authentication),
172
+ assertionMethod: relationIds(doc.assertionMethod),
173
+ keyAgreement: [...new Set([...relationIds(doc.keyAgreement), vmId])],
174
+ capabilityInvocation: relationIds(doc.capabilityInvocation),
175
+ capabilityDelegation: relationIds(doc.capabilityDelegation)
176
+ });
177
+ if (!updated.webDoc) {
178
+ throw new Error('did:webvh: updateDID returned no webDoc despite the did:web alsoKnownAs.');
179
+ }
180
+ await publishWebvhLog({ idStore, log: updated.log, webDoc: updated.webDoc });
181
+ return { did: updated.did };
182
+ }
183
+ /**
184
+ * REVOCATION (run by an enrolled client, root authority): removes a recovery
185
+ * code's posture from the document -- its `keyAgreement` verification method
186
+ * and its committed update-key hash -- in one entry. Idempotent. The
187
+ * roster-side half (rotating the PUK epoch off the code's wrap) is the
188
+ * caller's, and runs after this so the resolver's document no longer backs
189
+ * the removed entry.
190
+ *
191
+ * @param options {object}
192
+ * @param options.idStore {WebvhIdStore}
193
+ * @param options.updateKeys {ClientWebvhUpdateKeys} the REVOKING client's
194
+ * own did:webvh update-key seeds
195
+ * @param options.recovery {RecoveryPublicKeys} the code's public halves
196
+ * @returns {Promise<{ did: string }>}
197
+ */
198
+ export async function removeRecoveryKey({ idStore, updateKeys, recovery }) {
199
+ const published = await readLogOrThrow({ store: idStore });
200
+ const { did, doc } = published;
201
+ const recoveryHash = await deriveNextKeyHash(recovery.updateKeyMultibase);
202
+ const vmId = recoveryVmId({
203
+ did,
204
+ keyAgreementKeyMultibase: recovery.keyAgreementKeyMultibase
205
+ });
206
+ const vmPresent = (doc.verificationMethod ?? []).some(method => method.id === vmId);
207
+ const hashCommitted = published.nextKeyHashes.includes(recoveryHash);
208
+ if (!vmPresent && !hashCommitted) {
209
+ return { did };
210
+ }
211
+ const activeKey = await updateKeyMultibase({ seed: updateKeys.updateSeed });
212
+ if (!published.updateKeys.includes(activeKey)) {
213
+ throw new Error("did:webvh: the published log does not authorize this client's active " +
214
+ 'update key; finalize the pending rotation before revoking a ' +
215
+ 'recovery code.');
216
+ }
217
+ await assertCarryOverCommitments({ published });
218
+ const existingMethods = (doc.verificationMethod ?? []);
219
+ const signer = await updateKeySigner({ seed: updateKeys.updateSeed });
220
+ const updated = await updateDID({
221
+ log: published.log,
222
+ signer,
223
+ updateKeys: published.updateKeys,
224
+ nextKeyHashes: published.nextKeyHashes.filter(hash => hash !== recoveryHash),
225
+ verificationMethods: existingMethods.filter(method => method.id !== vmId),
226
+ authentication: relationIds(doc.authentication),
227
+ assertionMethod: relationIds(doc.assertionMethod),
228
+ keyAgreement: relationIds(doc.keyAgreement).filter(id => id !== vmId),
229
+ capabilityInvocation: relationIds(doc.capabilityInvocation),
230
+ capabilityDelegation: relationIds(doc.capabilityDelegation)
231
+ });
232
+ if (!updated.webDoc) {
233
+ throw new Error('did:webvh: updateDID returned no webDoc despite the did:web alsoKnownAs.');
234
+ }
235
+ await publishWebvhLog({ idStore, log: updated.log, webDoc: updated.webDoc });
236
+ return { did: updated.did };
237
+ }
238
+ /**
239
+ * RECOVERY (run by the code-derived client through the delegated `did.jsonl`
240
+ * PUT): writes the self-enrolling continuation described in the module doc --
241
+ * the reveal-and-commit entry signed by the code's pre-committed update key,
242
+ * then the add-and-retire entry signed by the new ordinary client's update
243
+ * key. Resumable from durable state alone: a completed continuation is
244
+ * detected by the new client's update key already being authorized (no-op),
245
+ * a torn one by the standing commitments (the commit step re-runs
246
+ * convergently -- the spent code's hash is deliberately carried through the
247
+ * commit entry, so a resumed commit can re-state the revealed key).
248
+ *
249
+ * @param options {object}
250
+ * @param options.store {RecoveryLogStore} public log read + delegated PUT
251
+ * @param options.recovery {object} the spent code's update seed and public
252
+ * halves
253
+ * @param options.recovery.updateSeed {Uint8Array}
254
+ * @param options.recovery.keyAgreementKeyMultibase {string}
255
+ * @param options.recovery.updateKeyMultibase {string}
256
+ * @param options.newClientKeys {WebvhEnrollmentKeys} the new ordinary
257
+ * client's public halves
258
+ * @param options.newClientUpdateSeeds {ClientWebvhUpdateKeys} the new
259
+ * client's update-key seeds (minted by the recovery flow, which therefore
260
+ * holds them and can sign the add entry)
261
+ * @param options.replacement {RecoveryPublicKeys} the replacement code's
262
+ * public halves, committed and published in the same continuation
263
+ * @returns {Promise<{ did: string, webDoc?: object }>} the account DID and,
264
+ * when the add entry ran here, the final `did.json` projection for the
265
+ * recovered session to republish
266
+ */
267
+ export async function recoverWebvhClient({ store, recovery, newClientKeys, newClientUpdateSeeds, replacement }) {
268
+ let published = await readLogOrThrow({ store });
269
+ // Already complete (a torn earlier run finished the add entry): the new
270
+ // client's update key is authorized, which only the add entry writes.
271
+ if (published.updateKeys.includes(newClientKeys.updateKeyMultibase)) {
272
+ return { did: published.did };
273
+ }
274
+ const recoveryHash = await deriveNextKeyHash(recovery.updateKeyMultibase);
275
+ const newUpdateHash = await deriveNextKeyHash(newClientKeys.updateKeyMultibase);
276
+ const newStagedHash = await deriveNextKeyHash(newClientKeys.stagedUpdateKeyMultibase);
277
+ const replacementHash = await deriveNextKeyHash(replacement.updateKeyMultibase);
278
+ // The reveal-and-commit entry, skipped when a torn earlier run already
279
+ // published it (the revealed key authorized AND every needed hash
280
+ // committed).
281
+ const revealed = published.updateKeys.includes(recovery.updateKeyMultibase);
282
+ const committed = [newUpdateHash, newStagedHash, replacementHash].every(hash => published.nextKeyHashes.includes(hash));
283
+ if (!revealed || !committed) {
284
+ if (!revealed && !published.nextKeyHashes.includes(recoveryHash)) {
285
+ throw new RecoveryKeyNotCommittedError();
286
+ }
287
+ await assertCarryOverCommitments({ published });
288
+ const signer = await updateKeySigner({ seed: recovery.updateSeed });
289
+ const updated = await updateDID({
290
+ log: published.log,
291
+ signer,
292
+ updateKeys: [
293
+ ...new Set([...published.updateKeys, recovery.updateKeyMultibase])
294
+ ],
295
+ // The spent code's own hash is kept through this entry (so a resumed
296
+ // commit can re-state the revealed key); the add entry drops it.
297
+ nextKeyHashes: [
298
+ ...new Set([
299
+ ...published.nextKeyHashes,
300
+ recoveryHash,
301
+ newUpdateHash,
302
+ newStagedHash,
303
+ replacementHash
304
+ ])
305
+ ]
306
+ });
307
+ await publishLogOnly({ store, log: updated.log });
308
+ published = await readLogOrThrow({ store });
309
+ }
310
+ // The add-and-retire entry: the new client's verification methods and
311
+ // update key in; the spent code's VM, update key, and hash out; the
312
+ // replacement code's VM in. Signed by the new client's update key, whose
313
+ // hash the commit entry just committed.
314
+ const { did, doc } = published;
315
+ const vmId = (publicKeyMultibase) => `${did}#${publicKeyMultibase}`;
316
+ const spentVmId = recoveryVmId({
317
+ did,
318
+ keyAgreementKeyMultibase: recovery.keyAgreementKeyMultibase
319
+ });
320
+ const replacementVmId = recoveryVmId({
321
+ did,
322
+ keyAgreementKeyMultibase: replacement.keyAgreementKeyMultibase
323
+ });
324
+ const addedMethods = [
325
+ {
326
+ id: vmId(newClientKeys.signingKeyMultibase),
327
+ publicKeyMultibase: newClientKeys.signingKeyMultibase
328
+ },
329
+ {
330
+ id: vmId(newClientKeys.keyAgreementKeyMultibase),
331
+ publicKeyMultibase: newClientKeys.keyAgreementKeyMultibase
332
+ },
333
+ {
334
+ id: replacementVmId,
335
+ publicKeyMultibase: replacement.keyAgreementKeyMultibase
336
+ }
337
+ ].map(method => ({
338
+ ...method,
339
+ type: MULTIKEY_VM_TYPE,
340
+ controller: did
341
+ }));
342
+ const existingMethods = (doc.verificationMethod ?? []);
343
+ const verificationMethods = [
344
+ ...existingMethods.filter(method => method.id !== spentVmId &&
345
+ !addedMethods.some(added => added.id === method.id)),
346
+ ...addedMethods
347
+ ];
348
+ const withReference = (relation, id) => [...new Set([...relationIds(relation), id])];
349
+ const signingVmId = vmId(newClientKeys.signingKeyMultibase);
350
+ const signer = await updateKeySigner({
351
+ seed: newClientUpdateSeeds.updateSeed
352
+ });
353
+ const updated = await updateDID({
354
+ log: published.log,
355
+ signer,
356
+ updateKeys: [
357
+ ...new Set([
358
+ ...published.updateKeys.filter(key => key !== recovery.updateKeyMultibase),
359
+ newClientKeys.updateKeyMultibase
360
+ ])
361
+ ],
362
+ nextKeyHashes: published.nextKeyHashes.filter(hash => hash !== recoveryHash),
363
+ verificationMethods,
364
+ authentication: withReference(doc.authentication, signingVmId),
365
+ assertionMethod: withReference(doc.assertionMethod, signingVmId),
366
+ keyAgreement: [
367
+ ...new Set([
368
+ ...relationIds(doc.keyAgreement).filter(id => id !== spentVmId),
369
+ vmId(newClientKeys.keyAgreementKeyMultibase),
370
+ replacementVmId
371
+ ])
372
+ ],
373
+ capabilityInvocation: withReference(doc.capabilityInvocation, signingVmId),
374
+ capabilityDelegation: withReference(doc.capabilityDelegation, signingVmId)
375
+ });
376
+ await publishLogOnly({ store, log: updated.log });
377
+ return { did: updated.did, webDoc: updated.webDoc };
378
+ }
379
+ //# sourceMappingURL=recoveryWebvh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recoveryWebvh.js","sourceRoot":"","sources":["../../src/recovery/recoveryWebvh.ts"],"names":[],"mappings":"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"}
@@ -110,7 +110,7 @@ export declare const DID_LOG_RESOURCE = "did.jsonl";
110
110
  export declare const DID_KEYS_RESOURCE = "keys.json";
111
111
  /**
112
112
  * The per-user-key (PUK) wrap-set roster, sibling of `keys.json` in the same
113
- * private `key-map` collection: a `CollectionEncryption` marker stored
113
+ * private `key-map` collection: a `CollectionEncryption` descriptor stored
114
114
  * verbatim as the resource body, whose current epoch IS the current PUK (the
115
115
  * epoch id is the PUK's did:key; the wrapped secret is the PUK's raw key,
116
116
  * wrapped to each enrolled client's key-agreement key). Read directly with a
@@ -101,7 +101,7 @@ export const DID_LOG_RESOURCE = 'did.jsonl';
101
101
  export const DID_KEYS_RESOURCE = 'keys.json';
102
102
  /**
103
103
  * The per-user-key (PUK) wrap-set roster, sibling of `keys.json` in the same
104
- * private `key-map` collection: a `CollectionEncryption` marker stored
104
+ * private `key-map` collection: a `CollectionEncryption` descriptor stored
105
105
  * verbatim as the resource body, whose current epoch IS the current PUK (the
106
106
  * epoch id is the PUK's did:key; the wrapped secret is the PUK's raw key,
107
107
  * wrapped to each enrolled client's key-agreement key). Read directly with a
@@ -31,7 +31,8 @@ import type { DocCipher, Json, ResolveConflict, SyncStore, WasSyncPort } from '.
31
31
  * for insert-only content-addressed collections whose push settlement covers
32
32
  * every 412.
33
33
  *
34
- * `encryption` selects the doc cipher and the server-side collection marker:
34
+ * `encryption` selects the doc cipher and the server-side encryption
35
+ * declaration:
35
36
  * `'edv'` (the default) envelopes every doc, `'plaintext'` ships it verbatim;
36
37
  * `isPublic` grants collection-level world read on the server. Both replicas
37
38
  * MUST agree on `collectionId` / `idDerivation` / `encryption` / `isPublic` for
@@ -1 +1 @@
1
- {"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/sync/collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EACV,SAAS,EACT,IAAI,EACJ,eAAe,EACf,SAAS,EACT,WAAW,EACZ,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAoB,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,GAAG,IAAI;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAA;IAClC,UAAU,CAAC,EAAE,KAAK,GAAG,WAAW,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C,aAAa,EAAE,CACb,EAAE,EAAE,EAAE,EACN,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,IAAI,KACV,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,aAAa,EAAE,CACb,EAAE,EAAE,EAAE,EACN,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,aAAa,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAChD,OAAO,EAAE,CAAC,OAAO,EAAE;QACjB,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,SAAS,CAAA;QACjB,MAAM,CAAC,EAAE,WAAW,CAAA;KACrB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC9B,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,SAAS,CAAA;QACjB,IAAI,EAAE,WAAW,CAAA;QACjB,KAAK,EAAE,SAAS,CAAA;KACjB,KAAK,eAAe,CAAA;CACtB"}
1
+ {"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/sync/collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EACV,SAAS,EACT,IAAI,EACJ,eAAe,EACf,SAAS,EACT,WAAW,EACZ,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,oBAAoB,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,GAAG,IAAI;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAA;IAClC,UAAU,CAAC,EAAE,KAAK,GAAG,WAAW,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C,aAAa,EAAE,CACb,EAAE,EAAE,EAAE,EACN,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,IAAI,KACV,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,aAAa,EAAE,CACb,EAAE,EAAE,EAAE,EACN,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,aAAa,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAChD,OAAO,EAAE,CAAC,OAAO,EAAE;QACjB,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,SAAS,CAAA;QACjB,MAAM,CAAC,EAAE,WAAW,CAAA;KACrB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC9B,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,SAAS,CAAA;QACjB,IAAI,EAAE,WAAW,CAAA;QACjB,KAAK,EAAE,SAAS,CAAA;KACjB,KAAK,eAAe,CAAA;CACtB"}
@@ -1,3 +1,4 @@
1
+ import type { DIDDoc, DIDLog, Signer } from '@interop/did-method-webvh';
1
2
  import type { KeystoreAgent } from '@interop/webkms-client';
2
3
  import type { DidWebKeyMap } from './didWeb.js';
3
4
  /**
@@ -36,6 +37,15 @@ export interface WebvhIdStore {
36
37
  content: object;
37
38
  }): Promise<void>;
38
39
  }
40
+ /**
41
+ * The Multikey verification-method type the did:webvh data model uses for both
42
+ * the Ed25519 (authentication/assertionMethod/capability*) and X25519
43
+ * (keyAgreement) keys. The same key material and multibase are carried as by
44
+ * the 2020 suite types, only `type` and `@context` change, and credential
45
+ * verifiers verify `Ed25519Signature2020` / `eddsa-rdfc-2022` proofs against
46
+ * it.
47
+ */
48
+ export declare const MULTIKEY_VM_TYPE = "Multikey";
39
49
  /**
40
50
  * The client-held did:webvh update-key material: 32-byte Ed25519 seeds.
41
51
  * `pendingStagedSeed` is present only mid-rotation (minted and persisted
@@ -108,6 +118,65 @@ export declare function mintClientWebvhUpdateKeys(): Promise<ClientWebvhUpdateKe
108
118
  export declare function updateKeyMultibase({ seed }: {
109
119
  seed: Uint8Array;
110
120
  }): Promise<string>;
121
+ /**
122
+ * Bridges a client-held update-key seed to the did:webvh `Signer` interface via
123
+ * the library's `signerFromExternalKey`. The only wallet-side seam is the shape
124
+ * adapter: the key pair's `signer().sign({ data })` matches the factory's
125
+ * `sign({ data })` bridge exactly, so the proof-value multibase encoding and
126
+ * the load-bearing `did:key:<pkm>#<pkm>` verification-method id (which the
127
+ * resolver matches against the entry's authorized `updateKeys`) are owned by
128
+ * the library, not duplicated here.
129
+ *
130
+ * @param options {object}
131
+ * @param options.seed {Uint8Array} the 32-byte update-key seed
132
+ * @returns {Promise<Signer>}
133
+ */
134
+ export declare function updateKeySigner({ seed }: {
135
+ seed: Uint8Array;
136
+ }): Promise<Signer>;
137
+ /**
138
+ * Publishes an already-created log: PUT `did.jsonl` (`text/jsonl`) then PUT
139
+ * `did.json` from `webDoc` (`application/did+json`, adopting the webvh
140
+ * projection). Both land in the `id` collection, whose collection-level
141
+ * `PublicCanRead` policy (set at provisioning) makes them world-readable, so
142
+ * the publish tail no longer sets per-resource policies. The shared publish
143
+ * tail of the create and rotate paths.
144
+ *
145
+ * @param options {object}
146
+ * @param options.idStore {WebvhIdStore}
147
+ * @param options.log {DIDLog}
148
+ * @param options.webDoc {object}
149
+ * @returns {Promise<void>}
150
+ */
151
+ export declare function publishWebvhLog({ idStore, log, webDoc }: {
152
+ idStore: WebvhIdStore;
153
+ log: DIDLog;
154
+ webDoc: object;
155
+ }): Promise<void>;
156
+ /**
157
+ * The verified state of the published log: the log itself, the resolved DID
158
+ * and document, and the effective update-key parameters (the authorized
159
+ * `updateKeys` and the standing `nextKeyHashes` commitments).
160
+ */
161
+ export interface PublishedWebvhLog {
162
+ log: DIDLog;
163
+ did: string;
164
+ doc: DIDDoc;
165
+ updateKeys: string[];
166
+ nextKeyHashes: string[];
167
+ }
168
+ /**
169
+ * Reads and resolves the published `did.jsonl`, or returns `undefined` when
170
+ * the log is not published. A log that exists but fails to resolve throws --
171
+ * a published-but-broken log is never silently re-created over.
172
+ *
173
+ * @param options {object}
174
+ * @param options.idStore {WebvhIdStore}
175
+ * @returns {Promise<PublishedWebvhLog | undefined>}
176
+ */
177
+ export declare function readPublishedLog({ idStore }: {
178
+ idStore: WebvhIdStore;
179
+ }): Promise<PublishedWebvhLog | undefined>;
111
180
  /**
112
181
  * Idempotently provisions and publishes the user's did:webvh DID log, run
113
182
  * directly after the did:web provisioning (non-fatal). The durable anchor is
@@ -186,6 +255,16 @@ export interface WebvhEnrollmentKeys extends WebvhClientKeys {
186
255
  updateKeyMultibase: string;
187
256
  stagedUpdateKeyMultibase: string;
188
257
  }
258
+ /**
259
+ * The relationship references of a resolved document as verification-method
260
+ * ids, tolerating embedded objects beside string references.
261
+ *
262
+ * @param relation {Array} the relationship array, when present
263
+ * @returns {string[]}
264
+ */
265
+ export declare function relationIds(relation: Array<string | {
266
+ id?: string;
267
+ }> | undefined): string[];
189
268
  /**
190
269
  * Enrolls a second wallet client into the published did:webvh document -- the
191
270
  * log half of the enrollment ceremony (the PUK roster wrap happens first,
@@ -1 +1 @@
1
- {"version":3,"file":"didWebvh.d.ts","sourceRoot":"","sources":["../../src/webvh/didWebvh.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"didWebvh.d.ts","sourceRoot":"","sources":["../../src/webvh/didWebvh.ts"],"names":[],"mappings":"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"}
@@ -58,7 +58,7 @@ import { multibaseOf } from './didWeb.js';
58
58
  * verifiers verify `Ed25519Signature2020` / `eddsa-rdfc-2022` proofs against
59
59
  * it.
60
60
  */
61
- const MULTIKEY_VM_TYPE = 'Multikey';
61
+ export const MULTIKEY_VM_TYPE = 'Multikey';
62
62
  /**
63
63
  * The byte length of a did:webvh update-key seed (an Ed25519 secret seed).
64
64
  */
@@ -125,7 +125,7 @@ export async function updateKeyMultibase({ seed }) {
125
125
  * @param options.seed {Uint8Array} the 32-byte update-key seed
126
126
  * @returns {Promise<Signer>}
127
127
  */
128
- async function updateKeySigner({ seed }) {
128
+ export async function updateKeySigner({ seed }) {
129
129
  const keyPair = await Ed25519VerificationKey.generate({ seed });
130
130
  const { publicKeyMultibase } = keyPair;
131
131
  // The key pair refuses to hand out a signer without an id; the did:key form
@@ -248,7 +248,7 @@ async function createWebvhLog({ wasServerUrl, spaceId, didWebKeys, clientKeys, u
248
248
  * @param options.webDoc {object}
249
249
  * @returns {Promise<void>}
250
250
  */
251
- async function publishWebvhLog({ idStore, log, webDoc }) {
251
+ export async function publishWebvhLog({ idStore, log, webDoc }) {
252
252
  await idStore.putIdResource({
253
253
  resourceId: DID_LOG_RESOURCE,
254
254
  content: logToJsonlString(log),
@@ -283,7 +283,7 @@ async function writeKeysJson({ idStore, didWebKeys, webvh }) {
283
283
  * @param options.idStore {WebvhIdStore}
284
284
  * @returns {Promise<PublishedWebvhLog | undefined>}
285
285
  */
286
- async function readPublishedLog({ idStore }) {
286
+ export async function readPublishedLog({ idStore }) {
287
287
  const logText = await idStore.getIdResourceRaw({
288
288
  resourceId: DID_LOG_RESOURCE
289
289
  });
@@ -539,7 +539,7 @@ export async function rotateWebvhUpdateKey({ idStore, updateKeys, persistUpdateK
539
539
  * @param relation {Array} the relationship array, when present
540
540
  * @returns {string[]}
541
541
  */
542
- function relationIds(relation) {
542
+ export function relationIds(relation) {
543
543
  const ids = [];
544
544
  for (const entry of relation ?? []) {
545
545
  const id = typeof entry === 'string' ? entry : entry?.id;