@interop/wallet-core 0.49.0 → 0.50.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 (160) hide show
  1. package/README.md +5 -2
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +118 -0
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -0
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +174 -0
  5. package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -0
  6. package/dist/clientAnnex/forget.d.ts +138 -0
  7. package/dist/clientAnnex/forget.d.ts.map +1 -0
  8. package/dist/clientAnnex/forget.js +133 -0
  9. package/dist/clientAnnex/forget.js.map +1 -0
  10. package/dist/clientAnnex/forgetLast.d.ts +267 -0
  11. package/dist/clientAnnex/forgetLast.d.ts.map +1 -0
  12. package/dist/clientAnnex/forgetLast.js +374 -0
  13. package/dist/clientAnnex/forgetLast.js.map +1 -0
  14. package/dist/{webvh/companionGc.d.ts → clientAnnex/gc.d.ts} +50 -16
  15. package/dist/clientAnnex/gc.d.ts.map +1 -0
  16. package/dist/{webvh/companionGc.js → clientAnnex/gc.js} +103 -71
  17. package/dist/clientAnnex/gc.js.map +1 -0
  18. package/dist/clientAnnex/index.d.ts +60 -0
  19. package/dist/clientAnnex/index.d.ts.map +1 -0
  20. package/dist/clientAnnex/index.js +60 -0
  21. package/dist/clientAnnex/index.js.map +1 -0
  22. package/dist/{unlock → clientAnnex}/ladder.d.ts +89 -15
  23. package/dist/clientAnnex/ladder.d.ts.map +1 -0
  24. package/dist/clientAnnex/ladder.js +474 -0
  25. package/dist/clientAnnex/ladder.js.map +1 -0
  26. package/dist/clientAnnex/ladderAnchored.d.ts +276 -0
  27. package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -0
  28. package/dist/clientAnnex/ladderAnchored.js +631 -0
  29. package/dist/clientAnnex/ladderAnchored.js.map +1 -0
  30. package/dist/{webvh/companion.d.ts → clientAnnex/log.d.ts} +333 -119
  31. package/dist/clientAnnex/log.d.ts.map +1 -0
  32. package/dist/{webvh/companion.js → clientAnnex/log.js} +583 -199
  33. package/dist/clientAnnex/log.js.map +1 -0
  34. package/dist/clientAnnex/recoveryLadderAnchored.d.ts +103 -0
  35. package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -0
  36. package/dist/clientAnnex/recoveryLadderAnchored.js +263 -0
  37. package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -0
  38. package/dist/{unlock → clientAnnex}/selfEnroll.d.ts +1 -1
  39. package/dist/clientAnnex/selfEnroll.d.ts.map +1 -0
  40. package/dist/{unlock → clientAnnex}/selfEnroll.js +1 -1
  41. package/dist/clientAnnex/selfEnroll.js.map +1 -0
  42. package/dist/clientAnnex/zcap.d.ts +49 -0
  43. package/dist/clientAnnex/zcap.d.ts.map +1 -0
  44. package/dist/clientAnnex/zcap.js +101 -0
  45. package/dist/clientAnnex/zcap.js.map +1 -0
  46. package/dist/clients/index.d.ts +9 -6
  47. package/dist/clients/index.d.ts.map +1 -1
  48. package/dist/clients/index.js +8 -5
  49. package/dist/clients/index.js.map +1 -1
  50. package/dist/clients/listing.d.ts +32 -0
  51. package/dist/clients/listing.d.ts.map +1 -1
  52. package/dist/clients/listing.js +47 -1
  53. package/dist/clients/listing.js.map +1 -1
  54. package/dist/clients/revocation.d.ts +33 -1
  55. package/dist/clients/revocation.d.ts.map +1 -1
  56. package/dist/clients/revocation.js +16 -4
  57. package/dist/clients/revocation.js.map +1 -1
  58. package/dist/enrollment/index.d.ts +6 -4
  59. package/dist/enrollment/index.d.ts.map +1 -1
  60. package/dist/enrollment/index.js +6 -4
  61. package/dist/enrollment/index.js.map +1 -1
  62. package/dist/enrollment/onboardingInvite.d.ts +5 -88
  63. package/dist/enrollment/onboardingInvite.d.ts.map +1 -1
  64. package/dist/enrollment/onboardingInvite.js +5 -168
  65. package/dist/enrollment/onboardingInvite.js.map +1 -1
  66. package/dist/genesis/index.d.ts +5 -0
  67. package/dist/genesis/index.d.ts.map +1 -1
  68. package/dist/genesis/index.js +5 -0
  69. package/dist/genesis/index.js.map +1 -1
  70. package/dist/keys/index.d.ts +1 -1
  71. package/dist/keys/index.d.ts.map +1 -1
  72. package/dist/keys/index.js +1 -1
  73. package/dist/keys/index.js.map +1 -1
  74. package/dist/keys/spaceEpochs.d.ts +7 -2
  75. package/dist/keys/spaceEpochs.d.ts.map +1 -1
  76. package/dist/keys/spaceEpochs.js +8 -2
  77. package/dist/keys/spaceEpochs.js.map +1 -1
  78. package/dist/keys/userKeyRoster.d.ts +39 -0
  79. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  80. package/dist/keys/userKeyRoster.js +43 -1
  81. package/dist/keys/userKeyRoster.js.map +1 -1
  82. package/dist/recovery/index.d.ts +5 -3
  83. package/dist/recovery/index.d.ts.map +1 -1
  84. package/dist/recovery/index.js +4 -2
  85. package/dist/recovery/index.js.map +1 -1
  86. package/dist/recovery/recoveryDelegation.d.ts +35 -12
  87. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  88. package/dist/recovery/recoveryDelegation.js +84 -86
  89. package/dist/recovery/recoveryDelegation.js.map +1 -1
  90. package/dist/recovery/recoveryWebvh.d.ts +32 -1
  91. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  92. package/dist/recovery/recoveryWebvh.js +2 -2
  93. package/dist/recovery/recoveryWebvh.js.map +1 -1
  94. package/dist/request/capabilityRequest.d.ts +33 -0
  95. package/dist/request/capabilityRequest.d.ts.map +1 -0
  96. package/dist/request/capabilityRequest.js +35 -0
  97. package/dist/request/capabilityRequest.js.map +1 -0
  98. package/dist/request/ephemeralExchange.d.ts +118 -0
  99. package/dist/request/ephemeralExchange.d.ts.map +1 -0
  100. package/dist/request/ephemeralExchange.js +224 -0
  101. package/dist/request/ephemeralExchange.js.map +1 -0
  102. package/dist/request/index.d.ts +6 -0
  103. package/dist/request/index.d.ts.map +1 -1
  104. package/dist/request/index.js +6 -0
  105. package/dist/request/index.js.map +1 -1
  106. package/dist/space/activity.d.ts +2 -2
  107. package/dist/space/activity.js +3 -3
  108. package/dist/space/activity.js.map +1 -1
  109. package/dist/unlock/index.d.ts +11 -23
  110. package/dist/unlock/index.d.ts.map +1 -1
  111. package/dist/unlock/index.js +10 -21
  112. package/dist/unlock/index.js.map +1 -1
  113. package/dist/unlock/retire.d.ts +47 -3
  114. package/dist/unlock/retire.d.ts.map +1 -1
  115. package/dist/unlock/retire.js +21 -5
  116. package/dist/unlock/retire.js.map +1 -1
  117. package/dist/unlock/standingWebvh.d.ts +37 -82
  118. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  119. package/dist/unlock/standingWebvh.js +64 -247
  120. package/dist/unlock/standingWebvh.js.map +1 -1
  121. package/dist/unlock/unlockRecord.d.ts +13 -6
  122. package/dist/unlock/unlockRecord.d.ts.map +1 -1
  123. package/dist/unlock/unlockRecord.js +14 -8
  124. package/dist/unlock/unlockRecord.js.map +1 -1
  125. package/dist/webvh/delegatedLogStore.d.ts +5 -5
  126. package/dist/webvh/delegatedLogStore.js +1 -1
  127. package/dist/webvh/didWebvh.d.ts +19 -9
  128. package/dist/webvh/didWebvh.d.ts.map +1 -1
  129. package/dist/webvh/didWebvh.js +16 -16
  130. package/dist/webvh/didWebvh.js.map +1 -1
  131. package/dist/webvh/index.d.ts +9 -25
  132. package/dist/webvh/index.d.ts.map +1 -1
  133. package/dist/webvh/index.js +9 -23
  134. package/dist/webvh/index.js.map +1 -1
  135. package/dist/webvh/revokeClient.d.ts +77 -5
  136. package/dist/webvh/revokeClient.d.ts.map +1 -1
  137. package/dist/webvh/revokeClient.js +154 -61
  138. package/dist/webvh/revokeClient.js.map +1 -1
  139. package/dist/webvh/standingZcap.d.ts +11 -1
  140. package/dist/webvh/standingZcap.d.ts.map +1 -1
  141. package/dist/webvh/standingZcap.js +13 -14
  142. package/dist/webvh/standingZcap.js.map +1 -1
  143. package/dist/webvh/wasIdStore.d.ts +13 -7
  144. package/dist/webvh/wasIdStore.d.ts.map +1 -1
  145. package/dist/webvh/wasIdStore.js +8 -4
  146. package/dist/webvh/wasIdStore.js.map +1 -1
  147. package/dist/webvh/zcap.d.ts +0 -24
  148. package/dist/webvh/zcap.d.ts.map +1 -1
  149. package/dist/webvh/zcap.js +0 -42
  150. package/dist/webvh/zcap.js.map +1 -1
  151. package/package.json +40 -34
  152. package/dist/unlock/ladder.d.ts.map +0 -1
  153. package/dist/unlock/ladder.js +0 -258
  154. package/dist/unlock/ladder.js.map +0 -1
  155. package/dist/unlock/selfEnroll.d.ts.map +0 -1
  156. package/dist/unlock/selfEnroll.js.map +0 -1
  157. package/dist/webvh/companion.d.ts.map +0 -1
  158. package/dist/webvh/companion.js.map +0 -1
  159. package/dist/webvh/companionGc.d.ts.map +0 -1
  160. package/dist/webvh/companionGc.js.map +0 -1
@@ -0,0 +1,474 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The update-key ladder: a standing unlock credential's latent-and-consumed
6
+ * did:webvh update authority. Rungs derive deterministically from a random
7
+ * 32-byte ladder seed carried inside the credential's unlock record -- never
8
+ * from the unlock secret itself, because a revealed rung lives verbatim in
9
+ * the world-readable `updateKeys` forever, where no hash commitment can
10
+ * protect it, so a secret-derived rung would be a standing offline grind
11
+ * oracle against the credential.
12
+ *
13
+ * Between uses only `hash(rung i)` stands in the document's `nextKeyHashes`;
14
+ * each self-enrollment is one loud reveal-and-commit entry signing with rung
15
+ * `i` and committing `hash(rung i + 1)`, after which the add entry retires
16
+ * the spent rung. The credential never holds a standing `updateKeys` member.
17
+ *
18
+ * There is no stored counter: which rung is current is recovered by
19
+ * re-deriving and scanning the published log's standing parameters
20
+ * ({@link attributeLadderRung}), and ambiguity fails closed rather than
21
+ * guessing -- the clients-listing attribution precedent. A lost
22
+ * compare-and-swap race resolves by determinism: the winner's entry commits
23
+ * `hash(rung i + 1)`, which IS the loser's retry key, so a re-run
24
+ * re-attributes and climbs one rung.
25
+ *
26
+ * The rung derivation is wire-level (both wallet apps must climb the same
27
+ * ladder from the same seed), so the salt and info labels are permanent.
28
+ */
29
+ import { deriveNextKeyHash } from '@interop/did-method-webvh';
30
+ import { hkdf } from '@noble/hashes/hkdf.js';
31
+ import { sha256 } from '@noble/hashes/sha2.js';
32
+ import { effectiveParameters, relationIds, updateKeyMultibase } from '../webvh/didWebvh.js';
33
+ import { LADDER_SEED_BYTES } from '../unlock/unlockRecord.js';
34
+ /**
35
+ * The HKDF salt for rung derivation and the per-rung info prefix (the rung
36
+ * index in decimal follows it). Both permanent -- changing either orphans
37
+ * every bound credential's ladder.
38
+ */
39
+ const LADDER_SALT = 'freewallet/unlock/update-ladder/v1';
40
+ const LADDER_RUNG_INFO_PREFIX = 'rung/';
41
+ /**
42
+ * The info label of the ladder VM -- the stable sibling key published in the
43
+ * account document while the account has no enrolled durable client. One salt
44
+ * for everything ladder-seed-derived, with the info namespace doing the
45
+ * separation: `vm` can never collide with a `rung/<n>` label. Permanent.
46
+ */
47
+ const LADDER_VM_INFO = 'vm';
48
+ /**
49
+ * The info-label suffix of a client-annex rung: the label is
50
+ * `<generationId>/rung/<k>` where `<generationId>` is the generation
51
+ * collection's name
52
+ * (`gen-<random>`) and `k` is pinned at 0 -- the annex log's update
53
+ * authority is each standing credential's STATIC rung 0 (chain length one,
54
+ * never advanced), so only `/rung/0` is ever derived. The three families
55
+ * under the one salt stay disjoint: `rung/<n>` labels carry exactly one
56
+ * slash followed by a decimal index, `vm` carries none, and an annex
57
+ * label always carries two slashes behind its `gen-` generation id.
58
+ * Permanent.
59
+ */
60
+ const CLIENT_ANNEX_RUNG_INFO_SUFFIX = '/rung/0';
61
+ /**
62
+ * How many rungs {@link attributeLadderRung} derives before concluding the
63
+ * log commits none of them. Generous: one rung is consumed per
64
+ * self-enrollment, so a real ladder's standing commitment sits at the number
65
+ * of self-enrollments the credential has ever performed.
66
+ */
67
+ export const LADDER_MAX_SCAN = 128;
68
+ /**
69
+ * Thrown when the published log's standing parameters match no derivable rung
70
+ * -- the credential's posture was revoked (or never published), the ladder
71
+ * seed does not belong to this account, or the scan bound was exceeded -- or
72
+ * when they match more than one rung in the same role, which no legitimate
73
+ * history produces. Self-enrollment refuses loudly rather than guessing.
74
+ */
75
+ export class LadderAttributionError extends Error {
76
+ constructor(message) {
77
+ super(message);
78
+ this.name = 'LadderAttributionError';
79
+ }
80
+ }
81
+ /**
82
+ * Generates a fresh random ladder seed.
83
+ *
84
+ * @returns {Uint8Array}
85
+ */
86
+ export function generateLadderSeed() {
87
+ return crypto.getRandomValues(new Uint8Array(LADDER_SEED_BYTES));
88
+ }
89
+ /**
90
+ * The one HKDF invocation of the ladder derivation family. Every
91
+ * ladder-seed-derived key (rungs, the ladder VM) comes through here, so the
92
+ * permanent wire-level triple -- SHA-256, {@link LADDER_SALT}, 32 bytes --
93
+ * lives in exactly one place and only the info label varies.
94
+ *
95
+ * @param options {object}
96
+ * @param options.ladderSeed {Uint8Array}
97
+ * @param options.info {string}
98
+ * @returns {Uint8Array}
99
+ */
100
+ function ladderDerive({ ladderSeed, info }) {
101
+ return hkdf(sha256, ladderSeed, new TextEncoder().encode(LADDER_SALT), new TextEncoder().encode(info), 32);
102
+ }
103
+ /**
104
+ * Derives the 32-byte update-key seed of rung `index`.
105
+ *
106
+ * @param options {object}
107
+ * @param options.ladderSeed {Uint8Array}
108
+ * @param options.index {number} the rung index, from 0
109
+ * @returns {Uint8Array}
110
+ */
111
+ export function ladderRungSeed({ ladderSeed, index }) {
112
+ if (!Number.isInteger(index) || index < 0) {
113
+ throw new Error(`Invalid ladder rung index "${String(index)}".`);
114
+ }
115
+ return ladderDerive({
116
+ ladderSeed,
117
+ info: `${LADDER_RUNG_INFO_PREFIX}${index}`
118
+ });
119
+ }
120
+ /**
121
+ * Derives rung `index` in full: seed and public multibase.
122
+ *
123
+ * @param options {object}
124
+ * @param options.ladderSeed {Uint8Array}
125
+ * @param options.index {number} the rung index, from 0
126
+ * @returns {Promise<LadderRung>}
127
+ */
128
+ export async function ladderRung({ ladderSeed, index }) {
129
+ const seed = ladderRungSeed({ ladderSeed, index });
130
+ return { index, seed, keyMultibase: await updateKeyMultibase({ seed }) };
131
+ }
132
+ /**
133
+ * Derives the 32-byte Ed25519 seed of the ladder VM -- the STABLE SIBLING: a
134
+ * dedicated key derived once from the ladder seed, distinct from every rung,
135
+ * published verbatim in the account document (the seed is random, so the
136
+ * hash-commitment rule permits it) and stable across rung spends, so a
137
+ * delegation it signed survives every ladder advance. It carries the
138
+ * ladder-anchored window's document-visible authority (`assertionMethod` and
139
+ * `capabilityDelegation`), while update authority stays on the rungs -- the
140
+ * two roles never share a key.
141
+ *
142
+ * Because the key is derived, removing its verification method is never the
143
+ * terminal remedy: a later reinstall republishes the same key under the same
144
+ * id, and any still-unexpired delegation it signed resumes verifying the
145
+ * moment the method returns. Revoking the delegations themselves (and,
146
+ * ultimately, rotating the credential) is what actually ends its authority.
147
+ *
148
+ * @param options {object}
149
+ * @param options.ladderSeed {Uint8Array}
150
+ * @returns {Uint8Array}
151
+ */
152
+ export function ladderVmSeed({ ladderSeed }) {
153
+ return ladderDerive({ ladderSeed, info: LADDER_VM_INFO });
154
+ }
155
+ /**
156
+ * The ladder VM's public key multibase, as the document publishes it (see
157
+ * {@link ladderVmSeed} for what the key is).
158
+ *
159
+ * @param options {object}
160
+ * @param options.ladderSeed {Uint8Array}
161
+ * @returns {Promise<string>}
162
+ */
163
+ export async function ladderVmKeyMultibase({ ladderSeed }) {
164
+ return updateKeyMultibase({ seed: ladderVmSeed({ ladderSeed }) });
165
+ }
166
+ /**
167
+ * Derives the 32-byte update-key seed of an annex generation's rung 0 --
168
+ * the credential's STATIC update key on that generation's annex log. The
169
+ * sequence is domain-separated per generation by the generation id
170
+ * (`<generationId>/rung/0` under the one {@link LADDER_SALT}): one shared
171
+ * sequence
172
+ * would hand the storage host, a legitimate reader of the private annex,
173
+ * a revealed key matching the ACCOUNT log's standing commitment, and a fresh
174
+ * per-generation sequence is what makes GC replacement self-healing (no rung
175
+ * index survives the deleted log, and none is needed).
176
+ *
177
+ * The generation id is trusted here rather than re-validated -- the annex
178
+ * ceremonies assert the `gen-<random>` shape (`assertGenerationId`)
179
+ * before any derivation, and the label families stay disjoint for any
180
+ * generation id regardless (an account-rung label carries exactly one
181
+ * slash).
182
+ *
183
+ * @param options {object}
184
+ * @param options.ladderSeed {Uint8Array}
185
+ * @param options.generationId {string} the generation collection's name
186
+ * @returns {Uint8Array}
187
+ */
188
+ export function clientAnnexRungSeed({ ladderSeed, generationId }) {
189
+ return ladderDerive({
190
+ ladderSeed,
191
+ info: `${generationId}${CLIENT_ANNEX_RUNG_INFO_SUFFIX}`
192
+ });
193
+ }
194
+ /**
195
+ * Derives an annex generation's rung 0 in full: seed and public multibase.
196
+ * Deliberately index-free -- the annex chain has length one, so there is
197
+ * no rung to advance to and no attribution scan to run (see
198
+ * {@link clientAnnexRungSeed}).
199
+ *
200
+ * @param options {object}
201
+ * @param options.ladderSeed {Uint8Array}
202
+ * @param options.generationId {string} the generation collection's name
203
+ * @returns {Promise<{ seed: Uint8Array, keyMultibase: string }>}
204
+ */
205
+ export async function clientAnnexRung({ ladderSeed, generationId }) {
206
+ const seed = clientAnnexRungSeed({ ladderSeed, generationId });
207
+ return { seed, keyMultibase: await updateKeyMultibase({ seed }) };
208
+ }
209
+ /**
210
+ * Recovers the ladder's current rung from the published log's standing
211
+ * parameters -- the counter recovery that replaces any stored counter. Scans
212
+ * rungs `0..maxScan - 1`; a rung whose key stands in `updateKeys` is a torn
213
+ * self-enrollment to resume (`'revealed'`), else a rung whose hash stands in
214
+ * `nextKeyHashes` is the standing commitment (`'committed'`). Exactly one
215
+ * revealed rung, or exactly one committed rung beside it, is legitimate --
216
+ * the reveal entry keeps the spent rung's hash committed so a resumed run can
217
+ * re-state it, which is why a revealed rung wins over a committed one.
218
+ * Anything else fails closed with {@link LadderAttributionError}.
219
+ *
220
+ * @param options {object}
221
+ * @param options.ladderSeed {Uint8Array}
222
+ * @param options.published {object} the resolved log's standing parameters
223
+ * @param options.published.updateKeys {string[]}
224
+ * @param options.published.nextKeyHashes {string[]}
225
+ * @param [options.maxScan] {number} how many rungs to derive before giving
226
+ * up; defaults to {@link LADDER_MAX_SCAN}
227
+ * @returns {Promise<{ rung: LadderRung, state: LadderRungState }>}
228
+ */
229
+ export async function attributeLadderRung({ ladderSeed, published, maxScan = LADDER_MAX_SCAN }) {
230
+ const revealed = [];
231
+ const committed = [];
232
+ for (let index = 0; index < maxScan; index++) {
233
+ const rung = await ladderRung({ ladderSeed, index });
234
+ if (published.updateKeys.includes(rung.keyMultibase)) {
235
+ revealed.push(rung);
236
+ }
237
+ else if (published.nextKeyHashes.includes(await deriveNextKeyHash(rung.keyMultibase))) {
238
+ committed.push(rung);
239
+ }
240
+ }
241
+ if (revealed.length > 1 || committed.length > 1) {
242
+ throw new LadderAttributionError('The published log commits more than one rung of this ladder in the ' +
243
+ 'same role; refusing to self-enroll on an ambiguous attribution.');
244
+ }
245
+ if (revealed.length === 1) {
246
+ return { rung: revealed[0], state: 'revealed' };
247
+ }
248
+ if (committed.length === 1) {
249
+ return { rung: committed[0], state: 'committed' };
250
+ }
251
+ throw new LadderAttributionError('The published log commits no rung of this ladder; the credential has ' +
252
+ 'been revoked, was never published, or does not belong to this account.');
253
+ }
254
+ /**
255
+ * Whether a log entry was signed by a key this ladder accounts for. A
256
+ * did:webvh entry proof names its key as `did:key:<multibase>#<multibase>`
257
+ * -- the id form the resolver matches against the entry's authorized
258
+ * `updateKeys` -- so the fragment IS the update-key multibase. The log is
259
+ * caller-verified, so a proof standing here has already been checked against
260
+ * the authorized set; this only asks whose it was.
261
+ *
262
+ * @param options {object}
263
+ * @param options.entry {DIDLogEntry | undefined}
264
+ * @param options.ladderKeys {Set<string>} the rung keys known so far
265
+ * @returns {boolean}
266
+ */
267
+ function ladderSigned({ entry, ladderKeys }) {
268
+ return (entry?.proof ?? []).some(proof => {
269
+ const keyMultibase = proof.verificationMethod?.split('#')[1];
270
+ return keyMultibase !== undefined && ladderKeys.has(keyMultibase);
271
+ });
272
+ }
273
+ /**
274
+ * Whether the document an entry publishes still carries the retiring
275
+ * credential's own `keyAgreement` verification method -- asked at the entry
276
+ * that completes an enrollment the ladder's rung revealed, where it is the
277
+ * test of whether the CREDENTIAL survives its own ceremony. A self-enrollment
278
+ * leaves the credential's posture untouched (it climbs to the next rung),
279
+ * while a spend -- the recovery continuation, whose add-and-retire entry
280
+ * strikes the code's posture and publishes its successor's -- ends it.
281
+ *
282
+ * With no id supplied the question cannot be asked, so the answer is a
283
+ * conservative `false`: a claim the ladder cannot attribute is released rather
284
+ * than struck.
285
+ *
286
+ * @param options {object}
287
+ * @param options.entry {DIDLogEntry | undefined}
288
+ * @param options.vmId {string | undefined} the credential's key-agreement
289
+ * verification-method id, where the caller supplied one
290
+ * @returns {boolean}
291
+ */
292
+ function credentialSurvives({ entry, vmId }) {
293
+ if (vmId === undefined || !entry?.state) {
294
+ return false;
295
+ }
296
+ // The `keyAgreement` RELATION alone, rather than the bare
297
+ // `verificationMethod` array: an entry that dereferences the method while
298
+ // leaving its object behind has ended the credential's posture, and reading
299
+ // that as a climb would claim -- and strike -- a successor credential's
300
+ // commitment.
301
+ return relationIds(entry.state.keyAgreement).includes(vmId);
302
+ }
303
+ /**
304
+ * Attributes a ladder's FULL standing posture from the log -- the retirement
305
+ * counterpart of {@link attributeLadderRung}, which recovers only the single
306
+ * current rung. Retiring a credential must strike every standing artifact its
307
+ * ladder accounts for, so this walks the log's effective parameters forward
308
+ * from an anchor (the recorded bind-time rung, however stale) and tracks the
309
+ * ladder's footprint entry by entry:
310
+ *
311
+ * - a newly authorized key whose hash was a known ladder commitment is a rung
312
+ * REVEAL; the hashes that entry newly commits are claimed by the ladder,
313
+ * as are those of any later entry the ladder itself signed, since the
314
+ * rung's authority stood behind them. Hashes an entry signed by some other
315
+ * key commits stay OUT, even while the rung sits in `updateKeys`: a rung
316
+ * stands revealed indefinitely after a forget (and after a torn
317
+ * self-enrollment), and the account's enrolled clients go on extending the
318
+ * log the whole time;
319
+ * - the entry that retires the revealed rung while authorizing a key whose
320
+ * hash sits among those claims is the enrollment's COMPLETION: the new
321
+ * client's update-key hash and the claim committed immediately after it
322
+ * (its staged hash -- a reveal-and-commit entry appends the credential's
323
+ * own next commitment LAST among its newly committed hashes, the ordering
324
+ * convention in `decisions/0007-ladder-reveal-hash-order.md`) transfer to
325
+ * the client and stop being ladder-owned. What the completion did not
326
+ * transfer stays ladder-owned only where the ladder can say so POSITIVELY:
327
+ * the hash derives from the ladder's own seed (or is the recorded key's),
328
+ * or the credential itself survives the completing entry, which is what
329
+ * makes the residue its next standing commitment. A SPEND -- the recovery
330
+ * continuation, whose one entry retires the code's own posture and
331
+ * publishes its successor's -- leaves the replacement credential's
332
+ * commitment in that position instead, and striking that would leave the
333
+ * replacement unusable and unhealable;
334
+ * - a claim or revealed key that later leaves the parameters without a
335
+ * completion was struck by some other edit and simply stops standing.
336
+ *
337
+ * With the ladder seed in hand (`ladderSeed`), every rung's key and hash are
338
+ * additionally known a priori, so the attribution does not depend on the
339
+ * anchor being current; without it, the walk is anchored on
340
+ * `anchorKeyMultibase` and on `credentialVmId` alone, and a residue neither
341
+ * can attribute is released -- the retirement then strikes what the recorded
342
+ * posture names and nothing more. More than one ladder reveal standing or
343
+ * arriving at once matches no legitimate history and fails closed
344
+ * ({@link LadderAttributionError}).
345
+ *
346
+ * @param options {object}
347
+ * @param options.log {DIDLog} a resolved, caller-verified log
348
+ * @param options.anchorKeyMultibase {string} the credential's recorded
349
+ * update-key multibase (bind-time rung 0, or a refreshed later rung)
350
+ * @param [options.ladderSeed] {Uint8Array} the credential's ladder seed,
351
+ * when the caller holds it
352
+ * @param [options.credentialVmId] {string} the credential's own
353
+ * `keyAgreement` verification-method id, which tells a climb (the
354
+ * credential stands afterwards) from a spend (its posture goes in the same
355
+ * entry)
356
+ * @param [options.maxScan] {number} seeded pre-derivation bound; defaults to
357
+ * {@link LADDER_MAX_SCAN}
358
+ * @returns {Promise<LadderStandingPosture>} what currently stands; both
359
+ * arrays empty when the log carries nothing of the ladder any more
360
+ */
361
+ export async function attributeLadderPosture({ log, anchorKeyMultibase, ladderSeed, credentialVmId, maxScan = LADDER_MAX_SCAN }) {
362
+ const anchorHash = await deriveNextKeyHash(anchorKeyMultibase);
363
+ const ladderKeys = new Set([anchorKeyMultibase]);
364
+ // What the ladder knows a priori: the recorded key's hash and, with the
365
+ // seed in hand, every rung's. A claim outside this set is held on the
366
+ // evidence of the entry that committed it, and released again when a
367
+ // completion shows it was never the ladder's.
368
+ const derivedHashes = new Set([anchorHash]);
369
+ const ladderHashes = new Set([anchorHash]);
370
+ if (ladderSeed) {
371
+ for (let index = 0; index < maxScan; index++) {
372
+ const rung = await ladderRung({ ladderSeed, index });
373
+ ladderKeys.add(rung.keyMultibase);
374
+ const rungHash = await deriveNextKeyHash(rung.keyMultibase);
375
+ derivedHashes.add(rungHash);
376
+ ladderHashes.add(rungHash);
377
+ }
378
+ }
379
+ const params = effectiveParameters(log);
380
+ let pending;
381
+ let prevUpdateKeys = new Set();
382
+ let prevHashes = new Set();
383
+ for (const [index, entry] of params.entries()) {
384
+ const currentUpdateKeys = new Set(entry.updateKeys);
385
+ const addedKeys = entry.updateKeys.filter(key => !prevUpdateKeys.has(key));
386
+ // Order-preserving on purpose: the completion transfer below reads the
387
+ // claim committed immediately after the client's update-key hash as its
388
+ // staged hash (the reveal entry's append order, a ratified convention).
389
+ const addedHashes = entry.nextKeyHashes.filter(hash => !prevHashes.has(hash));
390
+ // Completion first: the pending revealed rung left `updateKeys`. When the
391
+ // same entry authorizes a key whose hash sits among the reveal's claims,
392
+ // the enrollment completed -- that hash and its successor (the client's
393
+ // staged hash) transfer to the client. A rung leaving any other way was
394
+ // struck, and its claims simply stop standing.
395
+ if (pending && !currentUpdateKeys.has(pending.key)) {
396
+ const transferred = new Set();
397
+ for (const key of addedKeys) {
398
+ const at = pending.claims.indexOf(await deriveNextKeyHash(key));
399
+ if (at === -1) {
400
+ continue;
401
+ }
402
+ transferred.add(pending.claims[at]);
403
+ const staged = pending.claims[at + 1];
404
+ if (staged !== undefined) {
405
+ transferred.add(staged);
406
+ }
407
+ break;
408
+ }
409
+ // What the reveal committed and the completion did not transfer is
410
+ // ladder-owned only on positive attribution -- a hash the ladder
411
+ // derives itself, or any residue of a ceremony the credential came out
412
+ // of still standing (a climb, whose residue really is its next rung's
413
+ // commitment). A spend's residue is its SUCCESSOR's commitment, and
414
+ // striking that is silent, unhealable damage: the replacement keeps its
415
+ // verification method and its roster wrap, and only fails when someone
416
+ // finally types it.
417
+ const stands = credentialSurvives({
418
+ entry: log[index],
419
+ vmId: credentialVmId
420
+ });
421
+ for (const hash of pending.claims) {
422
+ if (transferred.has(hash) || !(stands || derivedHashes.has(hash))) {
423
+ ladderHashes.delete(hash);
424
+ }
425
+ }
426
+ pending = undefined;
427
+ }
428
+ // A newly authorized key matching a known ladder commitment is a reveal.
429
+ const reveals = [];
430
+ for (const key of addedKeys) {
431
+ if (ladderKeys.has(key) ||
432
+ ladderHashes.has(await deriveNextKeyHash(key))) {
433
+ reveals.push(key);
434
+ }
435
+ }
436
+ if (reveals.length > 1 || (reveals.length === 1 && pending)) {
437
+ throw new LadderAttributionError('The published log reveals more than one rung of this ladder at ' +
438
+ 'once; refusing to attribute an ambiguous history.');
439
+ }
440
+ if (reveals.length === 1) {
441
+ const key = reveals[0];
442
+ ladderKeys.add(key);
443
+ pending = { key, claims: [...addedHashes] };
444
+ for (const hash of addedHashes) {
445
+ ladderHashes.add(hash);
446
+ }
447
+ }
448
+ else if (pending && ladderSigned({ entry: log[index], ladderKeys })) {
449
+ // The rung is still revealed AND signed this entry, so the hashes it
450
+ // commits were committed under the rung's authority (the
451
+ // ladder-anchored window's separate commit entry) and join its claims.
452
+ // Signature, not mere presence in `updateKeys`, is what attributes
453
+ // them: the rung's reveal outlives the ceremony that revealed it, so
454
+ // claiming everything committed afterwards would sweep up hashes of
455
+ // other credentials and of racing enrollments -- and striking those on
456
+ // retirement is silent, unhealable damage.
457
+ pending.claims.push(...addedHashes);
458
+ for (const hash of addedHashes) {
459
+ ladderHashes.add(hash);
460
+ }
461
+ }
462
+ prevUpdateKeys = currentUpdateKeys;
463
+ prevHashes = new Set(entry.nextKeyHashes);
464
+ }
465
+ const final = params[params.length - 1] ?? {
466
+ updateKeys: [],
467
+ nextKeyHashes: []
468
+ };
469
+ return {
470
+ revealedKeys: final.updateKeys.filter(key => ladderKeys.has(key)),
471
+ committedHashes: final.nextKeyHashes.filter(hash => ladderHashes.has(hash))
472
+ };
473
+ }
474
+ //# sourceMappingURL=ladder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ladder.js","sourceRoot":"","sources":["../../src/clientAnnex/ladder.ts"],"names":[],"mappings":"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"}