@interop/wallet-core 0.39.0 → 0.41.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 (139) hide show
  1. package/README.md +5 -3
  2. package/dist/clients/listing.d.ts +4 -3
  3. package/dist/clients/listing.d.ts.map +1 -1
  4. package/dist/clients/listing.js.map +1 -1
  5. package/dist/clients/policy.d.ts +3 -2
  6. package/dist/clients/policy.d.ts.map +1 -1
  7. package/dist/clients/policy.js +3 -3
  8. package/dist/clients/policy.js.map +1 -1
  9. package/dist/clients/revocation.d.ts +14 -4
  10. package/dist/clients/revocation.d.ts.map +1 -1
  11. package/dist/clients/revocation.js +32 -22
  12. package/dist/clients/revocation.js.map +1 -1
  13. package/dist/enrollment/enrollment.d.ts +30 -2
  14. package/dist/enrollment/enrollment.d.ts.map +1 -1
  15. package/dist/enrollment/enrollment.js +44 -4
  16. package/dist/enrollment/enrollment.js.map +1 -1
  17. package/dist/enrollment/index.d.ts +4 -1
  18. package/dist/enrollment/index.d.ts.map +1 -1
  19. package/dist/enrollment/index.js +4 -1
  20. package/dist/enrollment/index.js.map +1 -1
  21. package/dist/keyring/fetch.d.ts +2 -1
  22. package/dist/keyring/fetch.d.ts.map +1 -1
  23. package/dist/keyring/fetch.js +7 -2
  24. package/dist/keyring/fetch.js.map +1 -1
  25. package/dist/keyring/index.d.ts +16 -9
  26. package/dist/keyring/index.d.ts.map +1 -1
  27. package/dist/keyring/index.js +15 -8
  28. package/dist/keyring/index.js.map +1 -1
  29. package/dist/keyring/kdf.d.ts +3 -1
  30. package/dist/keyring/kdf.d.ts.map +1 -1
  31. package/dist/keyring/kdf.js +16 -2
  32. package/dist/keyring/kdf.js.map +1 -1
  33. package/dist/keyring/record.d.ts +236 -50
  34. package/dist/keyring/record.d.ts.map +1 -1
  35. package/dist/keyring/record.js +348 -46
  36. package/dist/keyring/record.js.map +1 -1
  37. package/dist/keyring/unlockSpace.d.ts +25 -0
  38. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  39. package/dist/keyring/unlockSpace.js +31 -2
  40. package/dist/keyring/unlockSpace.js.map +1 -1
  41. package/dist/keys/index.d.ts +4 -2
  42. package/dist/keys/index.d.ts.map +1 -1
  43. package/dist/keys/index.js +2 -1
  44. package/dist/keys/index.js.map +1 -1
  45. package/dist/keys/rosterLogStore.d.ts +18 -1
  46. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  47. package/dist/keys/rosterLogStore.js +34 -6
  48. package/dist/keys/rosterLogStore.js.map +1 -1
  49. package/dist/keys/userKeyCascade.d.ts +10 -3
  50. package/dist/keys/userKeyCascade.d.ts.map +1 -1
  51. package/dist/keys/userKeyCascade.js +10 -4
  52. package/dist/keys/userKeyCascade.js.map +1 -1
  53. package/dist/keys/userKeyRoster.d.ts +39 -24
  54. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  55. package/dist/keys/userKeyRoster.js +28 -77
  56. package/dist/keys/userKeyRoster.js.map +1 -1
  57. package/dist/recovery/index.d.ts +16 -3
  58. package/dist/recovery/index.d.ts.map +1 -1
  59. package/dist/recovery/index.js +14 -2
  60. package/dist/recovery/index.js.map +1 -1
  61. package/dist/recovery/recoveryCode.d.ts +7 -0
  62. package/dist/recovery/recoveryCode.d.ts.map +1 -1
  63. package/dist/recovery/recoveryCode.js +10 -0
  64. package/dist/recovery/recoveryCode.js.map +1 -1
  65. package/dist/recovery/recoveryDelegation.d.ts +120 -0
  66. package/dist/recovery/recoveryDelegation.d.ts.map +1 -0
  67. package/dist/recovery/recoveryDelegation.js +216 -0
  68. package/dist/recovery/recoveryDelegation.js.map +1 -0
  69. package/dist/recovery/recoveryRecord.d.ts +138 -46
  70. package/dist/recovery/recoveryRecord.d.ts.map +1 -1
  71. package/dist/recovery/recoveryRecord.js +231 -30
  72. package/dist/recovery/recoveryRecord.js.map +1 -1
  73. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  74. package/dist/recovery/recoveryWebvh.js +20 -14
  75. package/dist/recovery/recoveryWebvh.js.map +1 -1
  76. package/dist/request/index.d.ts +1 -1
  77. package/dist/request/index.js +1 -1
  78. package/dist/request/matching.d.ts +24 -5
  79. package/dist/request/matching.d.ts.map +1 -1
  80. package/dist/request/matching.js +36 -39
  81. package/dist/request/matching.js.map +1 -1
  82. package/dist/request/walletInput.d.ts.map +1 -1
  83. package/dist/request/walletInput.js +3 -6
  84. package/dist/request/walletInput.js.map +1 -1
  85. package/dist/resourceLog/controller.d.ts +7 -4
  86. package/dist/resourceLog/controller.d.ts.map +1 -1
  87. package/dist/resourceLog/controller.js +17 -35
  88. package/dist/resourceLog/controller.js.map +1 -1
  89. package/dist/resourceLog/index.d.ts +1 -0
  90. package/dist/resourceLog/index.d.ts.map +1 -1
  91. package/dist/resourceLog/index.js +1 -0
  92. package/dist/resourceLog/index.js.map +1 -1
  93. package/dist/resourceLog/seal.d.ts +9 -1
  94. package/dist/resourceLog/seal.d.ts.map +1 -1
  95. package/dist/resourceLog/seal.js +21 -11
  96. package/dist/resourceLog/seal.js.map +1 -1
  97. package/dist/resourceLog/verify.d.ts.map +1 -1
  98. package/dist/resourceLog/verify.js +26 -9
  99. package/dist/resourceLog/verify.js.map +1 -1
  100. package/dist/resourceLog/vmFragment.d.ts +33 -0
  101. package/dist/resourceLog/vmFragment.d.ts.map +1 -0
  102. package/dist/resourceLog/vmFragment.js +39 -0
  103. package/dist/resourceLog/vmFragment.js.map +1 -0
  104. package/dist/space/publicLink.d.ts +2 -0
  105. package/dist/space/publicLink.d.ts.map +1 -1
  106. package/dist/space/publicLink.js +13 -1
  107. package/dist/space/publicLink.js.map +1 -1
  108. package/dist/space/wasLink.d.ts +5 -0
  109. package/dist/space/wasLink.d.ts.map +1 -1
  110. package/dist/space/wasLink.js +7 -2
  111. package/dist/space/wasLink.js.map +1 -1
  112. package/dist/webvh/didWeb.d.ts +3 -11
  113. package/dist/webvh/didWeb.d.ts.map +1 -1
  114. package/dist/webvh/didWeb.js +5 -1
  115. package/dist/webvh/didWeb.js.map +1 -1
  116. package/dist/webvh/didWebvh.d.ts +72 -1
  117. package/dist/webvh/didWebvh.d.ts.map +1 -1
  118. package/dist/webvh/didWebvh.js +111 -12
  119. package/dist/webvh/didWebvh.js.map +1 -1
  120. package/dist/webvh/index.d.ts +9 -2
  121. package/dist/webvh/index.d.ts.map +1 -1
  122. package/dist/webvh/index.js +8 -2
  123. package/dist/webvh/index.js.map +1 -1
  124. package/dist/webvh/keyAgreement.d.ts +56 -0
  125. package/dist/webvh/keyAgreement.d.ts.map +1 -0
  126. package/dist/webvh/keyAgreement.js +47 -0
  127. package/dist/webvh/keyAgreement.js.map +1 -0
  128. package/dist/webvh/listClients.d.ts +69 -18
  129. package/dist/webvh/listClients.d.ts.map +1 -1
  130. package/dist/webvh/listClients.js +141 -36
  131. package/dist/webvh/listClients.js.map +1 -1
  132. package/dist/webvh/revokeClient.d.ts +21 -11
  133. package/dist/webvh/revokeClient.d.ts.map +1 -1
  134. package/dist/webvh/revokeClient.js +31 -14
  135. package/dist/webvh/revokeClient.js.map +1 -1
  136. package/dist/webvh/verifyLog.d.ts.map +1 -1
  137. package/dist/webvh/verifyLog.js +5 -1
  138. package/dist/webvh/verifyLog.js.map +1 -1
  139. package/package.json +4 -4
@@ -1,12 +1,158 @@
1
- import { createEdvDocCipher, initRecipients, ownerRecipient } from '@interop/was-client/edv';
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The keyring record codec: the `{ version, encryption, wrapped, proof }`
6
+ * envelope stored as the one resource of an account's unlock Space. Its
7
+ * plaintext carries the account controller, the email captured at bind time,
8
+ * the account pointer, and the bind timestamp -- and deliberately no key
9
+ * material of any kind, so the record locates an account without authorizing
10
+ * anything against it.
11
+ *
12
+ * The wrap is an EDV document envelope sealed under the record's own key
13
+ * epoch: every EDV envelope seals to an epoch key, so the record carries its
14
+ * one-epoch descriptor in its `encryption` member, epoch[0] wrapped to the
15
+ * unlock key-agreement key. The record stays self-contained -- unlock KAK in,
16
+ * contents out. The cipher's `keyring` collection context labels errors only
17
+ * (the codec is agnostic to it).
18
+ *
19
+ * The authenticity layer is the `proof` member, and it is load-bearing: the
20
+ * unlock KAK's public half is derivable from the unlock did:key the server
21
+ * stores as the unlock Space's controller, so a malicious storage host can
22
+ * seal a record of its own that decrypts perfectly. Confidentiality was never
23
+ * the missing property. So a record carries an eddsa-jcs-2022 Data Integrity
24
+ * proof over its sibling members (`version`, `encryption`, `wrapped`), signed
25
+ * by the unlock identity's Ed25519 key -- which derives from the unlock secret,
26
+ * so a fresh client holds the verification prior by construction and the
27
+ * server never holds the signing key. The proof is verified BEFORE the record
28
+ * is decrypted, and there is no unwrap path that skips it. Because the
29
+ * signature covers the ciphertext, the encrypted bind timestamp is covered
30
+ * transitively while staying inside the plaintext, so bind times do not leak
31
+ * to a reader of the unlock Space.
32
+ */
33
+ import { createDataIntegrityProofTemplate, defaultWebvhLogVerifier, signDataIntegrityProof, signerFromExternalKey, verifyEntryProofs } from '@interop/did-method-webvh';
34
+ import { createEdvDocCipher, createEdvEncryptOnlyDocCipher, initRecipients, ownerRecipient } from '@interop/was-client/edv';
2
35
  import { KEYRING_COLLECTION } from '../space/collections.js';
3
36
  /**
4
- * The version stamped on the stored `{ version, encryption, wrapped }` keyring
5
- * envelope: the record whose envelope seals under the record's own key epoch
6
- * (the `encryption` member). Any other version is refused as unusable -- such
7
- * accounts are re-provisioned, not migrated.
37
+ * The version stamped on the stored `{ version, encryption, wrapped, proof }`
38
+ * keyring envelope: the signed record, whose envelope seals under the record's
39
+ * own key epoch (the `encryption` member) and whose sibling members carry a
40
+ * Data Integrity proof by the unlock identity's signing key. Any other version
41
+ * is refused as unusable -- such accounts are re-provisioned, not migrated.
42
+ */
43
+ export const KEYRING_RECORD_VERSION = 2;
44
+ /**
45
+ * A record's proof is absent, malformed, signed by a key this client does not
46
+ * accept, or does not verify over the record's own members. Its own class,
47
+ * distinct from a decrypt failure or an unusable-version refusal: this is the
48
+ * refusal that says the storage host forged or tampered with the record, which
49
+ * an app maps to its own login copy.
50
+ */
51
+ export class RecordProofError extends Error {
52
+ constructor(message, options) {
53
+ super(message, options);
54
+ this.name = 'RecordProofError';
55
+ }
56
+ }
57
+ /**
58
+ * Adapts a signing key agent (the unlock identity's `CapabilityAgent`, or an
59
+ * enrolled client's own key agent) to the record signer seam: the agent's
60
+ * did:key id supplies the public multibase, its signer the raw signature.
61
+ *
62
+ * @param options {object}
63
+ * @param options.keyAgent {object} a did:key `CapabilityAgent`-shaped agent
64
+ * @returns {RecordSigner}
65
+ */
66
+ export function recordSignerFromAgent({ keyAgent }) {
67
+ const [scheme, method, keyMultibase] = keyAgent.id.split(':');
68
+ if (scheme !== 'did' || method !== 'key' || !keyMultibase) {
69
+ throw new Error(`Not a did:key agent id: "${keyAgent.id}".`);
70
+ }
71
+ const signer = keyAgent.getSigner();
72
+ return {
73
+ keyMultibase,
74
+ async sign({ data }) {
75
+ const signature = await signer.sign({ data });
76
+ // Re-wrap as a plain Uint8Array: a signer may return a Node Buffer (or
77
+ // a cross-realm view), which the kernel's strict byte check rejects.
78
+ return new Uint8Array(signature.buffer, signature.byteOffset, signature.byteLength);
79
+ }
80
+ };
81
+ }
82
+ /**
83
+ * Signs a record's frame members and returns the stored signed record. Shared
84
+ * by the keyring and recovery wrap paths (and available to an app's own record
85
+ * kinds), so one construction produces every signed record: the proof covers
86
+ * `{ version, encryption, wrapped }` plus any record-kind members under JCS
87
+ * canonicalization.
88
+ *
89
+ * @param options {object}
90
+ * @param options.version {number} the frame version to stamp
91
+ * @param options.encryption {CollectionEncryption} the record's descriptor
92
+ * @param options.wrapped {unknown} the sealed envelope
93
+ * @param options.signer {RecordSigner} the signing key
94
+ * @param [options.members] {object} additional record-kind frame members the
95
+ * proof must cover (e.g. the recovery record's `binding`)
96
+ * @returns {Promise<SignedRecord>}
97
+ */
98
+ export async function signRecordFrame({ version, encryption, wrapped, signer, members }) {
99
+ const frame = { version, encryption, wrapped, ...(members ?? {}) };
100
+ const proofTemplate = createDataIntegrityProofTemplate({
101
+ verificationMethod: `did:key:${signer.keyMultibase}#${signer.keyMultibase}`
102
+ });
103
+ const proof = await signDataIntegrityProof(
104
+ // The kernel types its signable documents as did:webvh artifacts, but the
105
+ // construction is generic (JCS canonicalization over whatever it is
106
+ // handed), so the record frame rides through as one.
107
+ frame, proofTemplate, signerFromExternalKey({
108
+ publicKeyMultibase: signer.keyMultibase,
109
+ sign: signer.sign
110
+ }));
111
+ return { ...frame, proof: proof };
112
+ }
113
+ /**
114
+ * Structural check of a record's `proof` member against the fixed shape,
115
+ * before any cryptography runs.
116
+ *
117
+ * @param options {object}
118
+ * @param options.proof {unknown}
119
+ * @param options.label {string} names the record kind in the refusal
120
+ * @returns {RecordProof}
8
121
  */
9
- export const KEYRING_RECORD_VERSION = 1;
122
+ function checkRecordProofShape({ proof, label }) {
123
+ const candidate = proof;
124
+ if (candidate === null ||
125
+ typeof candidate !== 'object' ||
126
+ candidate.type !== 'DataIntegrityProof' ||
127
+ candidate.cryptosuite !== 'eddsa-jcs-2022' ||
128
+ candidate.proofPurpose !== 'assertionMethod' ||
129
+ typeof candidate.verificationMethod !== 'string' ||
130
+ typeof candidate.proofValue !== 'string') {
131
+ throw new RecordProofError(`The ${label} record carries no proof in the fixed shape ` +
132
+ `(DataIntegrityProof / eddsa-jcs-2022 / assertionMethod).`);
133
+ }
134
+ return candidate;
135
+ }
136
+ /**
137
+ * The signing key's public multibase named by a proof's `verificationMethod`:
138
+ * its fragment. The signer emits `did:key:<multibase>#<multibase>`; the DID
139
+ * half is not what authorizes anything -- the multibase IS the key, and the
140
+ * caller's allowlist decides whether it may sign this record.
141
+ *
142
+ * @param options {object}
143
+ * @param options.verificationMethod {string}
144
+ * @param options.label {string} names the record kind in the refusal
145
+ * @returns {string}
146
+ */
147
+ export function recordProofKeyMultibase({ verificationMethod, label }) {
148
+ const hashIndex = verificationMethod.lastIndexOf('#');
149
+ const keyMultibase = hashIndex === -1 ? '' : verificationMethod.slice(hashIndex + 1);
150
+ if (!keyMultibase) {
151
+ throw new RecordProofError(`The ${label} record's proof names a verification method with no key ` +
152
+ `fragment.`);
153
+ }
154
+ return keyMultibase;
155
+ }
10
156
  /**
11
157
  * Mints the one-epoch descriptor a fresh record is sealed under: epoch[0]
12
158
  * wrapped to the given KAK alone, built through `initRecipients` against a
@@ -40,12 +186,14 @@ export async function mintRecordEncryption({ keyAgreementKey }) {
40
186
  });
41
187
  }
42
188
  /**
43
- * Builds the record cipher: an EDV cipher over the record's own descriptor.
44
- * Shared by the wrap and unwrap paths (and by the recovery record, which
45
- * reuses the keyring cipher context verbatim); an app's own record kind
46
- * passes its own `collectionId` so its failures name the record kind. The
47
- * context labels errors only -- the codec is agnostic to it, so a record
48
- * kind's real swap protection is its contents validation on unwrap.
189
+ * Builds the record's reading cipher: an EDV cipher over the record's own
190
+ * descriptor, from the reader's key-agreement key. The unwrap paths' cipher
191
+ * (and the recovery record's, which reuses the keyring cipher context
192
+ * verbatim); the wrap paths seal through {@link recordSealCipher} instead. An
193
+ * app's own record kind passes its own `collectionId` so its failures name
194
+ * the record kind. The context labels errors only -- the codec is agnostic to
195
+ * it, so a record kind's real swap protection is its contents validation on
196
+ * unwrap.
49
197
  *
50
198
  * @param options {object}
51
199
  * @param options.keyAgreementKey {IKeyAgreementKey} the wrapping KAK (for
@@ -64,12 +212,36 @@ export async function recordCipher({ keyAgreementKey, keyResolver, encryption, c
64
212
  encryption
65
213
  });
66
214
  }
215
+ /**
216
+ * Builds the record's sealing cipher: an encrypt-only EDV cipher over the
217
+ * record's own descriptor, needing no key-agreement secret -- a write seals to
218
+ * the descriptor's epoch public key, reconstructed from the epoch id. This is
219
+ * what lets the recovery re-mint, which holds only the code's unlock KAK
220
+ * public half, re-seal a record it can never open; the issuance wraps go
221
+ * through the same construction and produce the same envelope shape. Decrypt
222
+ * on it refuses with was-client's typed `EncryptOnlyCipherError`.
223
+ *
224
+ * @param options {object}
225
+ * @param options.encryption {CollectionEncryption} the record's descriptor
226
+ * @param [options.collectionId] {string} the cipher context failures are
227
+ * labeled with; defaults to the keyring context
228
+ * @returns {Promise<DocCipher>}
229
+ */
230
+ export async function recordSealCipher({ encryption, collectionId = KEYRING_COLLECTION.id }) {
231
+ return createEdvEncryptOnlyDocCipher({ collectionId, encryption });
232
+ }
67
233
  /**
68
234
  * Validates the common `{ version, encryption, wrapped }` frame of a stored
69
235
  * record (keyring or recovery -- `label` names the refusals) and returns its
70
- * members. Exported so an app's own record kinds open their records through
71
- * the same frame validation the codec here seals with, rather than re-deriving
72
- * the version and shape checks.
236
+ * members, the `proof` among them for the signed frame. Exported so an app's
237
+ * own record kinds open their records through the same frame validation the
238
+ * codec here seals with, rather than re-deriving the version and shape checks.
239
+ *
240
+ * A frame at the keyring record version is the signed frame, so it must carry
241
+ * a fixed-shape proof; a record kind stamping its own version is unaffected
242
+ * (its authenticity story is its own). Validating the shape here does not
243
+ * verify it -- {@link verifyRecordProof} does, and every unwrap path in this
244
+ * module runs it before decrypting.
73
245
  *
74
246
  * @param options {object}
75
247
  * @param options.record {unknown}
@@ -77,56 +249,128 @@ export async function recordCipher({ keyAgreementKey, keyResolver, encryption, c
77
249
  * kind's own label
78
250
  * @param [options.version] {number} the version the frame must carry;
79
251
  * defaults to the keyring record version
80
- * @returns {{ encryption: CollectionEncryption, wrapped: unknown }}
252
+ * @returns {{ encryption: CollectionEncryption, wrapped: unknown,
253
+ * proof?: RecordProof }}
81
254
  */
82
255
  export function parseRecordFrame({ record, label, version = KEYRING_RECORD_VERSION }) {
83
256
  if (record === null || typeof record !== 'object') {
84
257
  throw new Error(`Malformed ${label} record.`);
85
258
  }
86
- const { version: recordVersion, encryption, wrapped } = record;
259
+ const { version: recordVersion, encryption, wrapped, proof } = record;
87
260
  if (recordVersion !== version) {
261
+ // Two retired version-1 shapes are named rather than reported as an
262
+ // unsupported number, so neither refusal is read as corruption: the
263
+ // pre-extraction record (a data-seed wrap with no descriptor) and the
264
+ // unsigned envelope this version's proof replaced. Both are unusable.
265
+ if (version === KEYRING_RECORD_VERSION && recordVersion === 1) {
266
+ if (encryption === undefined) {
267
+ throw new Error(`The ${label} record uses the retired pre-extraction version 1 ` +
268
+ 'shape (a data-seed wrap with no encryption descriptor); such ' +
269
+ 'accounts are re-provisioned, not migrated.');
270
+ }
271
+ throw new Error(`The ${label} record uses the retired unsigned version 1 shape (no ` +
272
+ 'proof over its frame, so a storage host could substitute it); ' +
273
+ 'such accounts are re-provisioned, not migrated.');
274
+ }
88
275
  throw new Error(`Unsupported ${label} record version "${String(recordVersion)}".`);
89
276
  }
90
277
  if (wrapped === undefined || wrapped === null) {
91
278
  throw new Error(`Malformed ${label} record.`);
92
279
  }
93
- // A version-1 frame carrying a wrap but no descriptor is the retired
94
- // pre-extraction record shape, which shipped under this same version number
95
- // and wrapped a data seed. It is unusable, not merely damaged -- name the
96
- // shape so the refusal is not read as corruption.
97
- if (encryption === undefined && version === KEYRING_RECORD_VERSION) {
98
- throw new Error(`The ${label} record uses the retired pre-extraction version 1 shape ` +
99
- '(a data-seed wrap with no encryption descriptor); such accounts are ' +
100
- 're-provisioned, not migrated.');
101
- }
102
280
  if (encryption === null || typeof encryption !== 'object') {
103
281
  throw new Error(`The ${label} record is missing its encryption descriptor.`);
104
282
  }
105
- return { encryption: encryption, wrapped };
283
+ return {
284
+ encryption: encryption,
285
+ wrapped,
286
+ ...(version === KEYRING_RECORD_VERSION
287
+ ? { proof: checkRecordProofShape({ proof, label }) }
288
+ : {})
289
+ };
290
+ }
291
+ /**
292
+ * Verifies a stored record's proof: the fixed proof shape, the signing key
293
+ * against the caller's allowlist, and the signature over the record's sibling
294
+ * members (everything except `proof`, JCS-canonicalized). Refuses with
295
+ * {@link RecordProofError} in every failing case -- a class of its own, so an
296
+ * app tells "the host forged or tampered with this record" apart from a wrong
297
+ * unlock secret or an unusable version.
298
+ *
299
+ * Standalone as well as internal, because the recovery record's re-minted
300
+ * signer is only knowable after the record is decrypted (see
301
+ * `unwrapRecoveryRecord`).
302
+ *
303
+ * @param options {object}
304
+ * @param options.record {unknown} the stored record, proof included
305
+ * @param options.allowedKeyMultibases {string | string[]} the signing keys
306
+ * this caller accepts, as public multibases or as verification-method ids
307
+ * whose fragment is one
308
+ * @param [options.label] {string} names the record kind in refusals;
309
+ * defaults to the keyring record
310
+ * @returns {Promise<string>} the verified signing key's public multibase
311
+ */
312
+ export async function verifyRecordProof({ record, allowedKeyMultibases, label = 'keyring' }) {
313
+ if (record === null || typeof record !== 'object') {
314
+ throw new RecordProofError(`Malformed ${label} record.`);
315
+ }
316
+ const { proof, ...frame } = record;
317
+ const checked = checkRecordProofShape({ proof, label });
318
+ const keyMultibase = recordProofKeyMultibase({
319
+ verificationMethod: checked.verificationMethod,
320
+ label
321
+ });
322
+ const allowed = new Set((typeof allowedKeyMultibases === 'string'
323
+ ? [allowedKeyMultibases]
324
+ : allowedKeyMultibases).map(entry => {
325
+ const hashIndex = entry.lastIndexOf('#');
326
+ return hashIndex === -1 ? entry : entry.slice(hashIndex + 1);
327
+ }));
328
+ if (!allowed.has(keyMultibase)) {
329
+ throw new RecordProofError(`The ${label} record is signed by a key this client does not accept ` +
330
+ `for it ("${keyMultibase}").`);
331
+ }
332
+ try {
333
+ await verifyEntryProofs({ ...frame, proof: checked }, {
334
+ verifier: defaultWebvhLogVerifier,
335
+ // Authorization is the allowlist check above, made before any
336
+ // cryptography runs; the key material resolves from the proof's own
337
+ // verification method, which that check has already pinned.
338
+ authorize: () => { },
339
+ resolveVM: async () => ({ publicKeyMultibase: keyMultibase })
340
+ });
341
+ }
342
+ catch (err) {
343
+ throw new RecordProofError(`The ${label} record's proof does not verify over its contents.`, { cause: err });
344
+ }
345
+ return keyMultibase;
106
346
  }
107
347
  /**
108
348
  * Wraps the account-pointer contents into a keyring record: the controller,
109
349
  * email, and pointer (+ timestamp) sealed under a freshly minted record epoch
110
- * whose key is wrapped to the unlock KAK. Deliberately carries no key material
111
- * of any kind.
350
+ * whose key is wrapped to the unlock KAK, then signed by the unlock identity's
351
+ * signing key. Deliberately carries no key material of any kind.
352
+ *
353
+ * The timestamp stays inside the plaintext (the signature covers the
354
+ * ciphertext, so it is covered transitively), so bind times do not leak to a
355
+ * reader of the unlock Space.
112
356
  *
113
357
  * @param options {object}
114
358
  * @param options.controller {string} the account did:key
115
359
  * @param [options.email] {string} the account email, when known
116
360
  * @param [options.pointer] {AccountPointer} the account pointer (absent on
117
361
  * no-WAS deployments)
118
- * @param options.keyAgreementKey {IKeyAgreementKey} the unlock KAK
119
- * @param options.keyResolver {IKeyResolver}
120
- * @returns {Promise<{ version: number, encryption: CollectionEncryption,
121
- * wrapped: unknown }>}
362
+ * @param options.keyAgreementKey {IKeyAgreementKey} the unlock KAK (its
363
+ * public half is all the wrap uses: sealing needs no key-agreement secret)
364
+ * @param options.signer {RecordSigner} the unlock identity's signing key
365
+ * (`recordSignerFromAgent` over the unlock agent)
366
+ * @param [options.createdAt] {string} the bind timestamp to stamp, as an ISO
367
+ * string; defaults to now. Supplied by a caller that pins record freshness,
368
+ * so it knows the stamp without unwrapping the record it just wrote.
369
+ * @returns {Promise<SignedRecord>}
122
370
  */
123
- export async function wrapKeyringRecord({ controller, email, pointer, keyAgreementKey, keyResolver }) {
371
+ export async function wrapKeyringRecord({ controller, email, pointer, keyAgreementKey, signer, createdAt }) {
124
372
  const encryption = await mintRecordEncryption({ keyAgreementKey });
125
- const cipher = await recordCipher({
126
- keyAgreementKey,
127
- keyResolver,
128
- encryption
129
- });
373
+ const cipher = await recordSealCipher({ encryption });
130
374
  const { envelope } = await cipher.encrypt({
131
375
  data: {
132
376
  controller,
@@ -140,28 +384,45 @@ export async function wrapKeyringRecord({ controller, email, pointer, keyAgreeme
140
384
  }
141
385
  }
142
386
  : {}),
143
- createdAt: new Date().toISOString()
387
+ createdAt: recordCreatedAtStamp({ createdAt })
144
388
  }
145
389
  });
146
- return { version: KEYRING_RECORD_VERSION, encryption, wrapped: envelope };
390
+ return signRecordFrame({
391
+ version: KEYRING_RECORD_VERSION,
392
+ encryption,
393
+ wrapped: envelope,
394
+ signer
395
+ });
147
396
  }
148
397
  /**
149
- * Unwraps and validates a keyring record. Rejects a record whose `version` is
150
- * not the current one (accounts are re-provisioned, not migrated), and
151
- * sanity-checks the decrypted plaintext (non-empty controller, well-formed
152
- * pointer when present).
398
+ * Unwraps and validates a keyring record. Verifies the record's proof against
399
+ * the unlock identity's own signing key BEFORE decrypting -- there is no
400
+ * unwrap path that skips it, so a record the storage host substituted is
401
+ * refused ({@link RecordProofError}) rather than decrypted and inspected.
402
+ * Rejects a record whose `version` is not the current one (accounts are
403
+ * re-provisioned, not migrated), and sanity-checks the decrypted plaintext
404
+ * (non-empty controller, well-formed pointer when present, a parseable
405
+ * `createdAt`).
153
406
  *
154
407
  * @param options {object}
155
408
  * @param options.record {unknown}
156
409
  * @param options.keyAgreementKey {IKeyAgreementKey} the unlock KAK
157
410
  * @param options.keyResolver {IKeyResolver}
411
+ * @param options.expectedKeyMultibase {string} the unlock identity's signing
412
+ * key multibase, derived from the typed secret -- the only key that may have
413
+ * signed this record
158
414
  * @returns {Promise<KeyringRecordContents>}
159
415
  */
160
- export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver }) {
416
+ export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver, expectedKeyMultibase }) {
161
417
  const { encryption, wrapped } = parseRecordFrame({
162
418
  record,
163
419
  label: 'keyring'
164
420
  });
421
+ await verifyRecordProof({
422
+ record,
423
+ allowedKeyMultibases: expectedKeyMultibase,
424
+ label: 'keyring'
425
+ });
165
426
  const cipher = await recordCipher({
166
427
  keyAgreementKey,
167
428
  keyResolver,
@@ -174,8 +435,13 @@ export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver
174
435
  throw new Error('Keyring record is missing a controller.');
175
436
  }
176
437
  const pointer = parseRecordPointer(plaintext.pointer);
438
+ const createdAt = parseRecordCreatedAt({
439
+ value: plaintext.createdAt,
440
+ label: 'Keyring'
441
+ });
177
442
  return {
178
443
  controller: plaintext.controller,
444
+ createdAt,
179
445
  // A record bound without an email simply has no email; anything
180
446
  // non-string is ignored, not fatal.
181
447
  ...(typeof plaintext.email === 'string' && plaintext.email
@@ -184,6 +450,42 @@ export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver
184
450
  ...(pointer ? { pointer } : {})
185
451
  };
186
452
  }
453
+ /**
454
+ * The bind timestamp a wrap path stamps into a record's plaintext: the
455
+ * caller's, validated as a parseable ISO timestamp, or now. A caller supplies
456
+ * one when it pins record freshness, so it knows the stamp of the record it is
457
+ * writing without reading it back.
458
+ *
459
+ * @param options {object}
460
+ * @param [options.createdAt] {string} the caller's timestamp
461
+ * @returns {string}
462
+ */
463
+ export function recordCreatedAtStamp({ createdAt }) {
464
+ if (createdAt === undefined) {
465
+ return new Date().toISOString();
466
+ }
467
+ if (typeof createdAt !== 'string' || Number.isNaN(Date.parse(createdAt))) {
468
+ throw new Error(`Invalid record createdAt timestamp "${createdAt}".`);
469
+ }
470
+ return createdAt;
471
+ }
472
+ /**
473
+ * Parses and validates the required `createdAt` member of a record plaintext:
474
+ * the moment the record was bound, as an ISO timestamp that must parse. Apps
475
+ * pin freshness on it, so a record that cannot state its own bind time is
476
+ * refused rather than defaulted.
477
+ *
478
+ * @param options {object}
479
+ * @param options.value {unknown} the plaintext's `createdAt` member
480
+ * @param options.label {string} names the record kind in the refusal
481
+ * @returns {string}
482
+ */
483
+ export function parseRecordCreatedAt({ value, label }) {
484
+ if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) {
485
+ throw new Error(`${label} record has no valid createdAt timestamp.`);
486
+ }
487
+ return value;
488
+ }
187
489
  /**
188
490
  * Parses and validates the optional `pointer` member of a keyring record
189
491
  * plaintext. An absent member is a no-WAS record (returns undefined); a
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/keyring/record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/keyring/record.ts"],"names":[],"mappings":"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"}
@@ -59,6 +59,31 @@ export declare function putUnlockKeyring({ storageServerUrl, zcapClient, spaceId
59
59
  spaceId: string;
60
60
  record: object;
61
61
  }): Promise<void>;
62
+ /**
63
+ * Reads the keyring record with an explicitly attached management capability,
64
+ * rather than by root invocation, or returns `null` when it does not exist.
65
+ * The `zcapClient` here is an enrolled client's (not the unlock identity's);
66
+ * the attached `capability` -- the management zcap the unlock identity
67
+ * delegated at bind time, provided it allows GET -- authorizes the read
68
+ * against the unlock Space. This is what lets the revocation cascade's
69
+ * re-mint read a recovery code's standing record without holding the code:
70
+ * the record's code-authenticated binding rides the frame in the clear, so
71
+ * carrying it forward verbatim needs no decryption.
72
+ *
73
+ * @param options {object}
74
+ * @param options.storageServerUrl {string}
75
+ * @param options.zcapClient {ZcapClient} an enrolled client's zcap client
76
+ * @param options.spaceId {string} the unlock Space id
77
+ * @param options.capability {IZcap} the delegated management zcap (must
78
+ * allow GET)
79
+ * @returns {Promise<unknown | null>}
80
+ */
81
+ export declare function getUnlockKeyringWithCapability({ storageServerUrl, zcapClient, spaceId, capability }: {
82
+ storageServerUrl: string;
83
+ zcapClient: ZcapClient;
84
+ spaceId: string;
85
+ capability: IZcap;
86
+ }): Promise<unknown | null>;
62
87
  /**
63
88
  * Writes (upserts) the keyring record with an explicitly attached management
64
89
  * capability, rather than by root invocation. The `zcapClient` here is an
@@ -1 +1 @@
1
- {"version":3,"file":"unlockSpace.d.ts","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AAoIrD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACV,IAAwB,EACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACP,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACN,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
1
+ {"version":3,"file":"unlockSpace.d.ts","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AAoIrD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACV,IAAwB,EACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACP,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACN,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
@@ -20,6 +20,7 @@
20
20
  * surfacing the miss as a 404-shaped `null`.
21
21
  */
22
22
  import { WasClient } from '@interop/was-client';
23
+ import { resourcePath, spacePath } from '@interop/was-client/paths';
23
24
  import { errorStatus } from '@interop/was-client/sync';
24
25
  import { KEYRING_COLLECTION, KEYRING_RESOURCE } from '../space/collections.js';
25
26
  /**
@@ -175,6 +176,34 @@ export async function putUnlockKeyring({ storageServerUrl, zcapClient, spaceId,
175
176
  record
176
177
  });
177
178
  }
179
+ /**
180
+ * Reads the keyring record with an explicitly attached management capability,
181
+ * rather than by root invocation, or returns `null` when it does not exist.
182
+ * The `zcapClient` here is an enrolled client's (not the unlock identity's);
183
+ * the attached `capability` -- the management zcap the unlock identity
184
+ * delegated at bind time, provided it allows GET -- authorizes the read
185
+ * against the unlock Space. This is what lets the revocation cascade's
186
+ * re-mint read a recovery code's standing record without holding the code:
187
+ * the record's code-authenticated binding rides the frame in the clear, so
188
+ * carrying it forward verbatim needs no decryption.
189
+ *
190
+ * @param options {object}
191
+ * @param options.storageServerUrl {string}
192
+ * @param options.zcapClient {ZcapClient} an enrolled client's zcap client
193
+ * @param options.spaceId {string} the unlock Space id
194
+ * @param options.capability {IZcap} the delegated management zcap (must
195
+ * allow GET)
196
+ * @returns {Promise<unknown | null>}
197
+ */
198
+ export async function getUnlockKeyringWithCapability({ storageServerUrl, zcapClient, spaceId, capability }) {
199
+ const was = unlockSpaceClient({ storageServerUrl, zcapClient });
200
+ const result = await was
201
+ .space(spaceId)
202
+ .collection(KEYRING_COLLECTION.id, { capability, encryption: 'plaintext' })
203
+ .resource(KEYRING_RESOURCE)
204
+ .get();
205
+ return result === null ? null : result;
206
+ }
178
207
  /**
179
208
  * Writes (upserts) the keyring record with an explicitly attached management
180
209
  * capability, rather than by root invocation. The `zcapClient` here is an
@@ -200,7 +229,7 @@ export async function putUnlockKeyringWithCapability({ storageServerUrl, zcapCli
200
229
  const body = new TextEncoder().encode(JSON.stringify(record));
201
230
  await was.request({
202
231
  capability,
203
- path: `/space/${spaceId}/${KEYRING_COLLECTION.id}/${KEYRING_RESOURCE}`,
232
+ path: resourcePath(spaceId, KEYRING_COLLECTION.id, KEYRING_RESOURCE),
204
233
  method: 'PUT',
205
234
  headers: { 'content-type': 'application/json' },
206
235
  body
@@ -243,7 +272,7 @@ export async function deleteUnlockSpaceWithCapability({ storageServerUrl, zcapCl
243
272
  try {
244
273
  await was.request({
245
274
  capability,
246
- path: `/space/${spaceId}`,
275
+ path: spacePath(spaceId),
247
276
  method: 'DELETE'
248
277
  });
249
278
  }
@@ -1 +1 @@
1
- {"version":3,"file":"unlockSpace.js","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unlockSpace.js","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"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"}