@interop/wallet-core 0.16.0 → 0.18.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 (175) hide show
  1. package/README.md +13 -13
  2. package/dist/clients/index.d.ts +4 -3
  3. package/dist/clients/index.d.ts.map +1 -1
  4. package/dist/clients/index.js +3 -2
  5. package/dist/clients/index.js.map +1 -1
  6. package/dist/clients/policy.d.ts +3 -3
  7. package/dist/clients/policy.d.ts.map +1 -1
  8. package/dist/clients/policy.js +1 -1
  9. package/dist/clients/revocation.d.ts +18 -15
  10. package/dist/clients/revocation.d.ts.map +1 -1
  11. package/dist/clients/revocation.js +42 -26
  12. package/dist/clients/revocation.js.map +1 -1
  13. package/dist/clients/rosterPolicy.d.ts +46 -24
  14. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  15. package/dist/clients/rosterPolicy.js +106 -48
  16. package/dist/clients/rosterPolicy.js.map +1 -1
  17. package/dist/descriptors/refresh.d.ts +3 -1
  18. package/dist/descriptors/refresh.d.ts.map +1 -1
  19. package/dist/descriptors/refresh.js +3 -1
  20. package/dist/descriptors/refresh.js.map +1 -1
  21. package/dist/display/alignment.d.ts +8 -2
  22. package/dist/display/alignment.d.ts.map +1 -1
  23. package/dist/display/alignment.js +11 -8
  24. package/dist/display/alignment.js.map +1 -1
  25. package/dist/display/displayFields.d.ts +6 -2
  26. package/dist/display/displayFields.d.ts.map +1 -1
  27. package/dist/display/displayFields.js.map +1 -1
  28. package/dist/display/evidence.d.ts +9 -3
  29. package/dist/display/evidence.d.ts.map +1 -1
  30. package/dist/display/evidence.js +3 -1
  31. package/dist/display/evidence.js.map +1 -1
  32. package/dist/display/index.d.ts +1 -1
  33. package/dist/display/index.d.ts.map +1 -1
  34. package/dist/display/index.js +1 -1
  35. package/dist/display/index.js.map +1 -1
  36. package/dist/display/issuer.d.ts +12 -4
  37. package/dist/display/issuer.d.ts.map +1 -1
  38. package/dist/display/issuer.js.map +1 -1
  39. package/dist/display/obv3.d.ts +7 -2
  40. package/dist/display/obv3.d.ts.map +1 -1
  41. package/dist/display/obv3.js +14 -24
  42. package/dist/display/obv3.js.map +1 -1
  43. package/dist/display/parse.d.ts +6 -2
  44. package/dist/display/parse.d.ts.map +1 -1
  45. package/dist/display/parse.js +6 -2
  46. package/dist/display/parse.js.map +1 -1
  47. package/dist/display/subject.d.ts +4 -0
  48. package/dist/display/subject.d.ts.map +1 -1
  49. package/dist/display/subject.js +12 -10
  50. package/dist/display/subject.js.map +1 -1
  51. package/dist/display/text.d.ts +11 -0
  52. package/dist/display/text.d.ts.map +1 -1
  53. package/dist/display/text.js +20 -4
  54. package/dist/display/text.js.map +1 -1
  55. package/dist/display/types.js +1 -1
  56. package/dist/display/types.js.map +1 -1
  57. package/dist/display/validity.js +4 -4
  58. package/dist/display/validity.js.map +1 -1
  59. package/dist/display/verificationView.d.ts +21 -7
  60. package/dist/display/verificationView.d.ts.map +1 -1
  61. package/dist/display/verificationView.js.map +1 -1
  62. package/dist/enrollment/enrollment.d.ts +21 -19
  63. package/dist/enrollment/enrollment.d.ts.map +1 -1
  64. package/dist/enrollment/enrollment.js +98 -34
  65. package/dist/enrollment/enrollment.js.map +1 -1
  66. package/dist/enrollment/index.d.ts +1 -1
  67. package/dist/enrollment/index.js +1 -1
  68. package/dist/index.d.ts +2 -2
  69. package/dist/index.js +2 -2
  70. package/dist/keys/clientKeyRecord.d.ts +19 -17
  71. package/dist/keys/clientKeyRecord.d.ts.map +1 -1
  72. package/dist/keys/clientKeyRecord.js +77 -41
  73. package/dist/keys/clientKeyRecord.js.map +1 -1
  74. package/dist/keys/index.d.ts +19 -17
  75. package/dist/keys/index.d.ts.map +1 -1
  76. package/dist/keys/index.js +16 -14
  77. package/dist/keys/index.js.map +1 -1
  78. package/dist/keys/rosterStore.d.ts +3 -3
  79. package/dist/keys/rosterStore.d.ts.map +1 -1
  80. package/dist/keys/rosterStore.js +13 -13
  81. package/dist/keys/rosterStore.js.map +1 -1
  82. package/dist/keys/userKey.d.ts +43 -0
  83. package/dist/keys/userKey.d.ts.map +1 -0
  84. package/dist/keys/{puk.js → userKey.js} +23 -21
  85. package/dist/keys/userKey.js.map +1 -0
  86. package/dist/keys/{pukCascade.d.ts → userKeyCascade.d.ts} +69 -69
  87. package/dist/keys/userKeyCascade.d.ts.map +1 -0
  88. package/dist/keys/{pukCascade.js → userKeyCascade.js} +77 -75
  89. package/dist/keys/userKeyCascade.js.map +1 -0
  90. package/dist/keys/{pukRoster.d.ts → userKeyRoster.d.ts} +141 -64
  91. package/dist/keys/userKeyRoster.d.ts.map +1 -0
  92. package/dist/keys/{pukRoster.js → userKeyRoster.js} +200 -72
  93. package/dist/keys/userKeyRoster.js.map +1 -0
  94. package/dist/recovery/index.d.ts +1 -1
  95. package/dist/recovery/index.js +1 -1
  96. package/dist/recovery/recoveryCode.d.ts +1 -1
  97. package/dist/recovery/recoveryCode.js +6 -6
  98. package/dist/recovery/recoveryRecord.d.ts +1 -1
  99. package/dist/recovery/recoveryWebvh.d.ts +1 -1
  100. package/dist/recovery/recoveryWebvh.js +1 -1
  101. package/dist/request/classify.d.ts +15 -1
  102. package/dist/request/classify.d.ts.map +1 -1
  103. package/dist/request/classify.js +38 -14
  104. package/dist/request/classify.js.map +1 -1
  105. package/dist/request/composeVp.d.ts.map +1 -1
  106. package/dist/request/composeVp.js +10 -3
  107. package/dist/request/composeVp.js.map +1 -1
  108. package/dist/request/matching.d.ts +6 -0
  109. package/dist/request/matching.d.ts.map +1 -1
  110. package/dist/request/matching.js +33 -8
  111. package/dist/request/matching.js.map +1 -1
  112. package/dist/request/parse.d.ts +5 -2
  113. package/dist/request/parse.d.ts.map +1 -1
  114. package/dist/request/parse.js +30 -5
  115. package/dist/request/parse.js.map +1 -1
  116. package/dist/request/presentationSuite.d.ts.map +1 -1
  117. package/dist/request/presentationSuite.js +6 -2
  118. package/dist/request/presentationSuite.js.map +1 -1
  119. package/dist/request/processRequest.js +1 -1
  120. package/dist/request/processRequest.js.map +1 -1
  121. package/dist/space/activity.d.ts +22 -8
  122. package/dist/space/activity.d.ts.map +1 -1
  123. package/dist/space/activity.js +19 -7
  124. package/dist/space/activity.js.map +1 -1
  125. package/dist/space/collections.d.ts +33 -21
  126. package/dist/space/collections.d.ts.map +1 -1
  127. package/dist/space/collections.js +34 -22
  128. package/dist/space/collections.js.map +1 -1
  129. package/dist/space/index.d.ts +2 -2
  130. package/dist/space/index.d.ts.map +1 -1
  131. package/dist/space/index.js +2 -2
  132. package/dist/space/index.js.map +1 -1
  133. package/dist/space/wasLink.d.ts +6 -2
  134. package/dist/space/wasLink.d.ts.map +1 -1
  135. package/dist/space/wasLink.js +5 -2
  136. package/dist/space/wasLink.js.map +1 -1
  137. package/dist/sync/contactsConflict.d.ts +1 -1
  138. package/dist/sync/contactsConflict.js +1 -1
  139. package/dist/sync/engine.d.ts +33 -11
  140. package/dist/sync/engine.d.ts.map +1 -1
  141. package/dist/sync/engine.js +4 -3
  142. package/dist/sync/engine.js.map +1 -1
  143. package/dist/sync/pull.d.ts +5 -3
  144. package/dist/sync/pull.d.ts.map +1 -1
  145. package/dist/sync/pull.js +34 -10
  146. package/dist/sync/pull.js.map +1 -1
  147. package/dist/sync/push.d.ts.map +1 -1
  148. package/dist/sync/push.js +24 -8
  149. package/dist/sync/push.js.map +1 -1
  150. package/dist/sync/types.d.ts +30 -6
  151. package/dist/sync/types.d.ts.map +1 -1
  152. package/dist/webvh/didWebvh.d.ts +29 -1
  153. package/dist/webvh/didWebvh.d.ts.map +1 -1
  154. package/dist/webvh/didWebvh.js +46 -11
  155. package/dist/webvh/didWebvh.js.map +1 -1
  156. package/dist/webvh/index.d.ts +1 -1
  157. package/dist/webvh/index.d.ts.map +1 -1
  158. package/dist/webvh/index.js +1 -1
  159. package/dist/webvh/index.js.map +1 -1
  160. package/dist/webvh/listClients.d.ts +19 -0
  161. package/dist/webvh/listClients.d.ts.map +1 -1
  162. package/dist/webvh/listClients.js +37 -1
  163. package/dist/webvh/listClients.js.map +1 -1
  164. package/dist/webvh/revokeClient.d.ts +11 -3
  165. package/dist/webvh/revokeClient.d.ts.map +1 -1
  166. package/dist/webvh/revokeClient.js +83 -14
  167. package/dist/webvh/revokeClient.js.map +1 -1
  168. package/package.json +3 -3
  169. package/dist/keys/puk.d.ts +0 -42
  170. package/dist/keys/puk.d.ts.map +0 -1
  171. package/dist/keys/puk.js.map +0 -1
  172. package/dist/keys/pukCascade.d.ts.map +0 -1
  173. package/dist/keys/pukCascade.js.map +0 -1
  174. package/dist/keys/pukRoster.d.ts.map +0 -1
  175. package/dist/keys/pukRoster.js.map +0 -1
@@ -2,14 +2,13 @@
2
2
  * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
3
  */
4
4
  /**
5
- * The PUK wrap set: the `key-map/puk.json` roster resource. Its body is a
6
- * `CollectionEncryption` descriptor verbatim, whose current epoch IS the
7
- * current
8
- * per-user key -- the epoch id is the PUK's did:key and the wrapped secret is
9
- * the PUK's raw 32-byte key, wrapped to each enrolled client's key-agreement
10
- * key. The roster is the delivery channel for PUK rotation: each client keeps
11
- * the PUK in its own local state under the unlock layer, and the roster's
12
- * epoch stamp marks a cached copy stale.
5
+ * The user key wrap set: the `key-map/user-key.json` roster resource. Its body
6
+ * is a `CollectionEncryption` descriptor verbatim, whose current epoch IS the
7
+ * current user key -- the epoch id is the user key's did:key and the wrapped
8
+ * secret is the user key's raw 32-byte key, wrapped to each enrolled client's
9
+ * key-agreement key. The roster is the delivery channel for user key rotation:
10
+ * each client keeps the user key in its own local state under the unlock layer,
11
+ * and the roster's epoch stamp marks a cached copy stale.
13
12
  *
14
13
  * Everything mutates through was-client's descriptor-store seam (the
15
14
  * plain-resource adapter): read-with-etag, compare-and-swap writes, and a
@@ -18,38 +17,50 @@
18
17
  *
19
18
  * A resource-hosted descriptor gets NONE of the server-side epoch invariants a
20
19
  * Collection Description enforces (append-only epochs, monotone
21
- * `currentEpoch`), so three client-side compensations are load-bearing alone
20
+ * `currentEpoch`), so four client-side compensations are load-bearing alone
22
21
  * against a tampering host:
23
22
  *
24
23
  * - **`epochsMac`** -- the epoch configuration is authenticated under the
25
24
  * current epoch's secret, which the server never holds; a fabricated
26
- * configuration fails the MAC (`PukRosterIntegrityError`).
25
+ * configuration fails the MAC (`UserKeyRosterIntegrityError`).
27
26
  * - **The epoch pin** -- the latest-seen roster epoch is pinned locally by the
28
27
  * consuming app (beside the account-pointer pin); a served
29
28
  * roster that rolls back behind the pin is refused
30
- * (`PukRosterContinuityError`) rather than followed. Stale-roster replay
29
+ * (`UserKeyRosterContinuityError`) rather than followed. Stale-roster replay
31
30
  * thereby lands in the same accepted continuity class as a substituted
32
31
  * account pointer.
33
32
  * - **The roster delivers, never sources** -- the recipient-key source of
34
33
  * record is the locally verified did:webvh document (one `keyAgreement`
35
34
  * verification method per enrolled client). When an epoch rotates, each
36
35
  * remaining recipient's key is resolved from that document
37
- * (`pukRosterRecipientResolver`); a roster entry with no matching document
36
+ * (`userKeyRosterRecipientResolver`); a roster entry with no matching document
38
37
  * verification method is dropped and never receives a wrap, so a
39
38
  * server-injected entry sits ignored. Wraps are minted only by enrolled
40
39
  * clients, against log-verified keys.
40
+ * - **`epochsSig`** -- the epoch configuration is additionally SIGNED by the
41
+ * writing client's enrolled Ed25519 key (`userKeyRosterEpochsSigner`), and a
42
+ * read that adopts an epoch this client has not vouched for itself (a
43
+ * rotated read, or a freshly enrolled client's first read) verifies that
44
+ * signature against the locally verified did:webvh document
45
+ * (`verifyUserKeyRosterEpochsSig`). This is the check the `epochsMac` alone
46
+ * cannot make on those paths: the MAC is keyed by a secret unwrapped from
47
+ * the served descriptor itself, so a host that mints its own epoch, wraps
48
+ * it to this client's world-readable key-agreement key, and MACs the
49
+ * fabricated configuration under the same minted secret passes the MAC --
50
+ * but it cannot produce a signature by a key the document backs.
41
51
  */
42
52
  import type { IKeyAgreementKey } from '@interop/data-integrity-core';
43
53
  import type { CollectionEncryption } from '@interop/was-client';
44
- import { type EncryptionDescriptorStore, type RecipientPublicKey } from '@interop/was-client/edv';
45
- import type { Puk } from './puk.js';
54
+ import { type EncryptionDescriptorStore, type EpochsSigner, type RecipientPublicKey } from '@interop/was-client/edv';
55
+ import { type ICapabilityAgent } from '../webvh/zcap.js';
56
+ import type { UserKey } from './userKey.js';
46
57
  /**
47
58
  * Thrown when a served roster fails its client-side authentication: a
48
59
  * missing/unsupported/invalid `epochsMac`, or a descriptor whose `currentEpoch`
49
60
  * names no epoch in its own list. The server (or whoever can write to it) has
50
61
  * produced a configuration no enrolled client authenticated.
51
62
  */
52
- export declare class PukRosterIntegrityError extends Error {
63
+ export declare class UserKeyRosterIntegrityError extends Error {
53
64
  constructor(message: string);
54
65
  }
55
66
  /**
@@ -59,7 +70,7 @@ export declare class PukRosterIntegrityError extends Error {
59
70
  * an older consistent configuration, which a valid `epochsMac` alone cannot
60
71
  * catch; refused rather than followed.
61
72
  */
62
- export declare class PukRosterContinuityError extends Error {
73
+ export declare class UserKeyRosterContinuityError extends Error {
63
74
  pinnedEpochId: string;
64
75
  constructor({ pinnedEpochId }: {
65
76
  pinnedEpochId: string;
@@ -68,10 +79,10 @@ export declare class PukRosterContinuityError extends Error {
68
79
  /**
69
80
  * Thrown when this client holds no usable wrap in the roster's current epoch
70
81
  * (no recipient entry for its key-agreement key, or the entry fails to
71
- * unwrap). The client cannot obtain the current PUK -- it may have been
82
+ * unwrap). The client cannot obtain the current user key -- it may have been
72
83
  * rotated off the roster.
73
84
  */
74
- export declare class PukRosterUnwrapError extends Error {
85
+ export declare class UserKeyRosterUnwrapError extends Error {
75
86
  constructor(message: string);
76
87
  }
77
88
  /**
@@ -89,6 +100,41 @@ export interface RosterRecipientDocument {
89
100
  publicKeyMultibase?: string;
90
101
  }>;
91
102
  }
103
+ /**
104
+ * The roster's epoch-configuration signer: signs each roster write's epoch
105
+ * configuration with this client's own Ed25519 signing key, under a `kid`
106
+ * that is the key's public multibase -- exactly the string enrolled as this
107
+ * client's verification method in the did:webvh document, so a reader
108
+ * resolves the signature against the document rather than anything the
109
+ * roster (or the server) supplies.
110
+ *
111
+ * @param options {object}
112
+ * @param options.keyAgent {ICapabilityAgent} this client's signing key
113
+ * agent (the `keyAgent` of `agentsFromSeed`)
114
+ * @returns {EpochsSigner} the `signEpochs` hook for roster writes
115
+ */
116
+ export declare function userKeyRosterEpochsSigner({ keyAgent }: {
117
+ keyAgent: ICapabilityAgent;
118
+ }): EpochsSigner;
119
+ /**
120
+ * Verifies a served roster's `epochsSig` against the locally verified
121
+ * did:webvh document -- the root of trust the server cannot mint. The
122
+ * signature must be present and supported, its `kid` must be the public
123
+ * multibase of one of the document's verification methods (an enrolled
124
+ * client's signing key), and it must verify over the canonical
125
+ * epoch-configuration payload. Throws {@link UserKeyRosterIntegrityError}
126
+ * otherwise: a configuration no enrolled client signed.
127
+ *
128
+ * @param options {object}
129
+ * @param options.descriptor {CollectionEncryption} the served roster
130
+ * @param options.document {RosterRecipientDocument} the locally verified
131
+ * did:webvh document (never a server-supplied roster field)
132
+ * @returns {Promise<void>}
133
+ */
134
+ export declare function verifyUserKeyRosterEpochsSig({ descriptor, document }: {
135
+ descriptor: CollectionEncryption;
136
+ document: RosterRecipientDocument;
137
+ }): Promise<void>;
92
138
  /**
93
139
  * A wallet client's roster kid: its key-agreement key's id exactly as
94
140
  * `agentsFromSeed` derives it at the client's own logins
@@ -122,32 +168,36 @@ export declare function rosterRecipientKid({ signingKeyMultibase, keyAgreementKe
122
168
  * did:webvh document (never a server-supplied roster field)
123
169
  * @returns {function} a `resolveRecipientKey` for `removeRecipient`
124
170
  */
125
- export declare function pukRosterRecipientResolver({ document }: {
171
+ export declare function userKeyRosterRecipientResolver({ document }: {
126
172
  document: RosterRecipientDocument;
127
173
  }): (kid: string) => Promise<RecipientPublicKey | null>;
128
174
  /**
129
- * Ensures the roster exists, create-if-absent: an absent roster is
130
- * initialized with the account's existing PUK installed as the first epoch,
131
- * wrapped to this client's key-agreement key; an existing roster is returned
132
- * as-is (authentication is the read path's job, and provisioning must never
133
- * clobber an established roster). Idempotent -- losing the guarded-create
134
- * race to a concurrent first init converges on the winner's roster.
175
+ * Ensures the roster exists, create-if-absent: an absent roster is initialized
176
+ * with the account's existing user key installed as the first epoch, wrapped to
177
+ * this client's key-agreement key; an existing roster is returned as-is
178
+ * (authentication is the read path's job, and provisioning must never clobber
179
+ * an established roster). Idempotent -- losing the guarded-create race to a
180
+ * concurrent first init converges on the winner's roster.
135
181
  *
136
182
  * @param options {object}
137
183
  * @param options.store {EncryptionDescriptorStore} the roster's descriptor
138
184
  * store
139
- * @param options.puk {Puk} the account's per-user key
185
+ * @param options.userKey {UserKey} the account's user key
140
186
  * @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
141
187
  * (identity) key-agreement key -- the roster recipient
188
+ * @param options.signEpochs {EpochsSigner} this client's epoch-configuration
189
+ * signer ({@link userKeyRosterEpochsSigner}), so the first configuration is
190
+ * vouched for by an enrollable key rather than only its own MAC
142
191
  * @returns {Promise<CollectionEncryption>} the roster descriptor
143
192
  */
144
- export declare function ensurePukRoster({ store, puk, clientKeyAgreementKey }: {
193
+ export declare function ensureUserKeyRoster({ store, userKey, clientKeyAgreementKey, signEpochs }: {
145
194
  store: EncryptionDescriptorStore;
146
- puk: Puk;
195
+ userKey: UserKey;
147
196
  clientKeyAgreementKey: IKeyAgreementKey;
197
+ signEpochs: EpochsSigner;
148
198
  }): Promise<CollectionEncryption>;
149
199
  /**
150
- * Wraps the PUK to a client being enrolled -- the roster half of the
200
+ * Wraps the user key to a client being enrolled -- the roster half of the
151
201
  * enrollment ceremony, and deliberately its FIRST write (decryption material
152
202
  * before authorization, the push order): the wrap lands before the did:webvh
153
203
  * log entries, so no enrolled client is ever authorized but blind, and a tear
@@ -172,22 +222,22 @@ export declare function ensurePukRoster({ store, puk, clientKeyAgreementKey }: {
172
222
  * re-wrapping
173
223
  * @returns {Promise<CollectionEncryption>} the refreshed roster descriptor
174
224
  */
175
- export declare function addPukRosterRecipient({ store, recipient, ownerKeyAgreementKey }: {
225
+ export declare function addUserKeyRosterRecipient({ store, recipient, ownerKeyAgreementKey }: {
176
226
  store: EncryptionDescriptorStore;
177
227
  recipient: RecipientPublicKey;
178
228
  ownerKeyAgreementKey: IKeyAgreementKey;
179
229
  }): Promise<CollectionEncryption>;
180
230
  /**
181
- * Rotates the PUK roster off one recipient -- the roster half of revoking an
182
- * enrolled wallet client or a recovery code. A thin, deliberate composition
231
+ * Rotates the user key roster off one recipient -- the roster half of revoking
232
+ * an enrolled wallet client or a recovery code. A thin, deliberate composition
183
233
  * of was-client's `removeRecipient` with the two roster-specific choices
184
- * spelled once: the remaining recipients are resolved from the locally
185
- * verified did:webvh document ("the roster delivers, never sources" -- an
186
- * entry with no matching `keyAgreement` verification method is dropped and
187
- * never receives a wrap), and the pull axis is a no-op, because for a roster
188
- * recipient the pull axis IS the document edit the caller performed first --
189
- * under the current-key-set rule the removed party's server-side access died
190
- * the moment its verification method left the document.
234
+ * spelled once: the remaining recipients are resolved from the locally verified
235
+ * did:webvh document ("the roster delivers, never sources" -- an entry with no
236
+ * matching `keyAgreement` verification method is dropped and never receives a
237
+ * wrap), and the pull axis is a no-op, because for a roster recipient the pull
238
+ * axis IS the document edit the caller performed first -- under the
239
+ * current-key-set rule the removed party's server-side access died the moment
240
+ * its verification method left the document.
191
241
  *
192
242
  * @param options {object}
193
243
  * @param options.store {EncryptionDescriptorStore} the roster's descriptor
@@ -196,18 +246,22 @@ export declare function addPukRosterRecipient({ store, recipient, ownerKeyAgreem
196
246
  * did:webvh document, AFTER the removal edit
197
247
  * @param options.retireRecipientId {string} the removed recipient's roster
198
248
  * kid
249
+ * @param options.signEpochs {EpochsSigner} the rotating client's
250
+ * epoch-configuration signer ({@link userKeyRosterEpochsSigner}), vouching for
251
+ * the fresh epoch so other clients' rotated reads accept it
199
252
  * @returns {Promise<CollectionEncryption>} the rotated roster descriptor
200
253
  */
201
- export declare function rotatePukRoster({ store, document, retireRecipientId }: {
254
+ export declare function rotateUserKeyRoster({ store, document, retireRecipientId, signEpochs }: {
202
255
  store: EncryptionDescriptorStore;
203
256
  document: RosterRecipientDocument;
204
257
  retireRecipientId: string;
258
+ signEpochs: EpochsSigner;
205
259
  }): Promise<CollectionEncryption>;
206
260
  /**
207
261
  * Converges the roster onto the account document: the standing detector for a
208
262
  * revocation cascade torn between its two halves. The cascade edits the
209
263
  * document first and rotates the roster second, so a client that crashes in
210
- * between leaves a roster that keeps wrapping the CURRENT per-user key to a
264
+ * between leaves a roster that keeps wrapping the CURRENT user key to a
211
265
  * recipient the document no longer keys -- durable, silent, and permanent,
212
266
  * since the revoked client's document edit will never be re-run.
213
267
  *
@@ -215,7 +269,7 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
215
269
  * document-backed resolver cannot answer for is exactly a recipient the
216
270
  * document no longer keys, so a healthy account reads the descriptor and
217
271
  * writes nothing. When any such recipient is found the roster is rotated away
218
- * from ALL of them at once -- a single {@link rotatePukRoster} suffices,
272
+ * from ALL of them at once -- a single {@link rotateUserKeyRoster} suffices,
219
273
  * because the resolver drops every unbacked entry from the fresh epoch, not
220
274
  * just the one named as retiring.
221
275
  *
@@ -224,8 +278,8 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
224
278
  * account), not a cascade to finish, and completing it would lock every
225
279
  * client out of the account.
226
280
  *
227
- * The fresh per-user key itself is not returned: the caller adopts it the
228
- * ordinary way, by re-reading the roster ({@link readPukRoster}) once
281
+ * The fresh user key itself is not returned: the caller adopts it the
282
+ * ordinary way, by re-reading the roster ({@link readUserKeyRoster}) once
229
283
  * `rotated` says there is something to adopt, and then runs the collection
230
284
  * fan-out.
231
285
  *
@@ -237,14 +291,18 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
237
291
  * @param [options.descriptor] {CollectionEncryption} a descriptor the caller
238
292
  * has just read (a login-time roster read), to save a re-read; omitted, the
239
293
  * roster is read fresh
294
+ * @param options.signEpochs {EpochsSigner} the converging client's
295
+ * epoch-configuration signer ({@link userKeyRosterEpochsSigner}), for the
296
+ * rotation this call may perform
240
297
  * @returns {Promise<object>} whether the roster rotated on this call, the
241
298
  * stale recipient kids found, and the roster descriptor as it now stands
242
299
  * (`null` when the account has no roster yet)
243
300
  */
244
- export declare function convergePukRosterToDocument({ store, document, descriptor }: {
301
+ export declare function convergeUserKeyRosterToDocument({ store, document, descriptor, signEpochs }: {
245
302
  store: EncryptionDescriptorStore;
246
303
  document: RosterRecipientDocument;
247
304
  descriptor?: CollectionEncryption;
305
+ signEpochs: EpochsSigner;
248
306
  }): Promise<{
249
307
  rotated: boolean;
250
308
  staleRecipientIds: string[];
@@ -252,13 +310,13 @@ export declare function convergePukRosterToDocument({ store, document, descripto
252
310
  }>;
253
311
  /**
254
312
  * What a roster read resolves to: the authenticated descriptor, the current
255
- * PUK (the cached one confirmed current, or a fresh one unwrapped from a
313
+ * user key (the cached one confirmed current, or a fresh one unwrapped from a
256
314
  * rotated epoch -- `rotated` says which), and the epoch id the caller must pin
257
315
  * as the new latest-seen.
258
316
  */
259
- export interface PukRosterReadResult {
317
+ export interface UserKeyRosterReadResult {
260
318
  descriptor: CollectionEncryption;
261
- puk: Puk;
319
+ userKey: UserKey;
262
320
  rotated: boolean;
263
321
  latestEpochId: string;
264
322
  }
@@ -269,37 +327,56 @@ export interface PukRosterReadResult {
269
327
  *
270
328
  * 1. **Continuity**: the served epochs must contain the pinned latest-seen
271
329
  * epoch, and `currentEpoch` must not precede it in the append-only list
272
- * (`PukRosterContinuityError` -- the rollback/replay refusal).
273
- * 2. **Possession**: `currentEpoch === puk.id` confirms the cached PUK
330
+ * (`UserKeyRosterContinuityError` -- the rollback/replay refusal).
331
+ * 2. **Possession**: `currentEpoch === userKey.id` confirms the cached user key
274
332
  * current; otherwise the current epoch was rotated by another client and
275
333
  * this client's wrap is unwrapped with its own key-agreement key
276
- * (`PukRosterUnwrapError` when it holds none).
277
- * 3. **Authentication**: the descriptor's `epochsMac` is verified under the
278
- * current epoch's secret (`PukRosterIntegrityError` on any mismatch -- a
334
+ * (`UserKeyRosterUnwrapError` when it holds none).
335
+ * 3. **Provenance** (the rotated/first-read path only): the epoch
336
+ * configuration's `epochsSig` is verified against the locally verified
337
+ * did:webvh document ({@link verifyUserKeyRosterEpochsSig}) BEFORE the epoch
338
+ * it delivers is adopted. On this path the `epochsMac` alone proves
339
+ * nothing against the host -- its key is unwrapped from the served
340
+ * descriptor itself -- so an epoch no enrolled client signed is refused
341
+ * (`UserKeyRosterIntegrityError`). The cached-current path needs no signature:
342
+ * there the MAC is keyed by a secret this client already trusts.
343
+ * 4. **Authentication**: the descriptor's `epochsMac` is verified under the
344
+ * current epoch's secret (`UserKeyRosterIntegrityError` on any mismatch -- a
279
345
  * fabricated configuration).
280
346
  *
281
- * A rotated read returns the fresh PUK; its Ed25519 signing seed does not
347
+ * A rotated read returns the fresh user key; its Ed25519 signing seed does not
282
348
  * travel through the roster (the roster wraps the key-agreement secret
283
- * alone), so the returned PUK carries none.
349
+ * alone), so the returned user key carries none.
284
350
  *
285
- * A caller with no cached PUK at all -- a freshly enrolled client making its
286
- * first post-enrollment read -- omits `puk` and always takes the unwrap path;
287
- * the result's `rotated` is then true (the PUK was adopted from the roster).
351
+ * A caller with no cached user key at all -- a freshly enrolled client making
352
+ * its first post-enrollment read -- omits `userKey` and always takes the unwrap
353
+ * path; the result's `rotated` is then true (the user key was adopted from the
354
+ * roster). Every unwrap-path caller must therefore supply the account document
355
+ * (or a way to resolve it): `document` when it already holds a verified copy,
356
+ * or `resolveDocument` to fetch-and-verify lazily, only when the read actually
357
+ * rotates.
288
358
  *
289
359
  * @param options {object}
290
360
  * @param options.store {EncryptionDescriptorStore} the roster's descriptor
291
361
  * store
292
- * @param [options.puk] {Puk} this client's cached PUK, when it holds one
362
+ * @param [options.userKey] {UserKey} this client's cached user key, when it holds one
293
363
  * @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
294
364
  * (identity) key-agreement key, unwrapping a rotated epoch
295
365
  * @param [options.pinnedEpochId] {string} the locally pinned latest-seen
296
366
  * roster epoch, when this client has seen the roster before
297
- * @returns {Promise<PukRosterReadResult | null>}
367
+ * @param [options.document] {RosterRecipientDocument} the locally verified
368
+ * did:webvh document, when the caller already holds one
369
+ * @param [options.resolveDocument] {function} resolves the locally verified
370
+ * did:webvh document on demand; called only when the read takes the
371
+ * rotated/first-read path
372
+ * @returns {Promise<UserKeyRosterReadResult | null>}
298
373
  */
299
- export declare function readPukRoster({ store, puk, clientKeyAgreementKey, pinnedEpochId }: {
374
+ export declare function readUserKeyRoster({ store, userKey, clientKeyAgreementKey, pinnedEpochId, document, resolveDocument }: {
300
375
  store: EncryptionDescriptorStore;
301
- puk?: Puk;
376
+ userKey?: UserKey;
302
377
  clientKeyAgreementKey: IKeyAgreementKey;
303
378
  pinnedEpochId?: string | null;
304
- }): Promise<PukRosterReadResult | null>;
305
- //# sourceMappingURL=pukRoster.d.ts.map
379
+ document?: RosterRecipientDocument;
380
+ resolveDocument?: () => Promise<RosterRecipientDocument>;
381
+ }): Promise<UserKeyRosterReadResult | null>;
382
+ //# sourceMappingURL=userKeyRoster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userKeyRoster.d.ts","sourceRoot":"","sources":["../../src/keys/userKeyRoster.ts"],"names":[],"mappings":"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"}