@interop/wallet-core 0.48.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 (163) 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/clientAnnex/gc.d.ts +255 -0
  15. package/dist/clientAnnex/gc.d.ts.map +1 -0
  16. package/dist/clientAnnex/gc.js +445 -0
  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 +99 -23
  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} +373 -152
  31. package/dist/clientAnnex/log.d.ts.map +1 -0
  32. package/dist/{webvh/companion.js → clientAnnex/log.js} +654 -261
  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 +38 -0
  107. package/dist/space/activity.d.ts.map +1 -1
  108. package/dist/space/activity.js +41 -1
  109. package/dist/space/activity.js.map +1 -1
  110. package/dist/space/index.d.ts +1 -1
  111. package/dist/space/index.d.ts.map +1 -1
  112. package/dist/space/index.js +1 -1
  113. package/dist/space/index.js.map +1 -1
  114. package/dist/unlock/index.d.ts +11 -23
  115. package/dist/unlock/index.d.ts.map +1 -1
  116. package/dist/unlock/index.js +10 -21
  117. package/dist/unlock/index.js.map +1 -1
  118. package/dist/unlock/retire.d.ts +47 -3
  119. package/dist/unlock/retire.d.ts.map +1 -1
  120. package/dist/unlock/retire.js +21 -5
  121. package/dist/unlock/retire.js.map +1 -1
  122. package/dist/unlock/standingWebvh.d.ts +37 -82
  123. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  124. package/dist/unlock/standingWebvh.js +64 -247
  125. package/dist/unlock/standingWebvh.js.map +1 -1
  126. package/dist/unlock/unlockRecord.d.ts +13 -6
  127. package/dist/unlock/unlockRecord.d.ts.map +1 -1
  128. package/dist/unlock/unlockRecord.js +14 -8
  129. package/dist/unlock/unlockRecord.js.map +1 -1
  130. package/dist/webvh/delegatedLogStore.d.ts +5 -5
  131. package/dist/webvh/delegatedLogStore.js +1 -1
  132. package/dist/webvh/didWebvh.d.ts +20 -10
  133. package/dist/webvh/didWebvh.d.ts.map +1 -1
  134. package/dist/webvh/didWebvh.js +17 -17
  135. package/dist/webvh/didWebvh.js.map +1 -1
  136. package/dist/webvh/index.d.ts +9 -23
  137. package/dist/webvh/index.d.ts.map +1 -1
  138. package/dist/webvh/index.js +9 -22
  139. package/dist/webvh/index.js.map +1 -1
  140. package/dist/webvh/revokeClient.d.ts +77 -5
  141. package/dist/webvh/revokeClient.d.ts.map +1 -1
  142. package/dist/webvh/revokeClient.js +154 -61
  143. package/dist/webvh/revokeClient.js.map +1 -1
  144. package/dist/webvh/standingZcap.d.ts +11 -1
  145. package/dist/webvh/standingZcap.d.ts.map +1 -1
  146. package/dist/webvh/standingZcap.js +13 -14
  147. package/dist/webvh/standingZcap.js.map +1 -1
  148. package/dist/webvh/wasIdStore.d.ts +13 -7
  149. package/dist/webvh/wasIdStore.d.ts.map +1 -1
  150. package/dist/webvh/wasIdStore.js +8 -4
  151. package/dist/webvh/wasIdStore.js.map +1 -1
  152. package/dist/webvh/zcap.d.ts +0 -24
  153. package/dist/webvh/zcap.d.ts.map +1 -1
  154. package/dist/webvh/zcap.js +0 -42
  155. package/dist/webvh/zcap.js.map +1 -1
  156. package/package.json +40 -34
  157. package/dist/unlock/ladder.d.ts.map +0 -1
  158. package/dist/unlock/ladder.js +0 -254
  159. package/dist/unlock/ladder.js.map +0 -1
  160. package/dist/unlock/selfEnroll.d.ts.map +0 -1
  161. package/dist/unlock/selfEnroll.js.map +0 -1
  162. package/dist/webvh/companion.d.ts.map +0 -1
  163. package/dist/webvh/companion.js.map +0 -1
@@ -0,0 +1,267 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The LAST durable client's forget: the two-entry transition ceremony that
6
+ * takes an account from one enrolled durable client to the client-less,
7
+ * ladder-anchored state -- the same state a credential-anchored signup and a
8
+ * transient recovery produce. Decision 0004's 2026-08-19 amendment fixes the
9
+ * entry order, and it is forced twice over: the server's revocation endpoint
10
+ * verifies a to-be-revoked capability's chain against the CURRENTLY resolved
11
+ * document (so a ladder-signed chain revokes only while the ladder VM is
12
+ * published), and the ladder VM carries no `capabilityInvocation` (so once
13
+ * the client's verification method is gone, nothing can sign the revocation
14
+ * POST at all). So:
15
+ *
16
+ * 1. **The install entry** ({@link installLadderVmWebvh}): the ladder VM
17
+ * joins the document while the client's whole footprint stays -- the
18
+ * both-present transitional state. This is the ceremony's
19
+ * posture-changing document version under the ceremony-tail license.
20
+ * 2. **The roster rotation**, ladder-signed, anchored at the install entry,
21
+ * HTTP-invoked under the still-standing client: the user key rotates off
22
+ * this client's wrap in ONE append (the license's one-shot shape), read
23
+ * back through the credential's standing wrap. Because the append's
24
+ * signer is the ladder VM -- a key the post-removal document still lists
25
+ * -- the roster log needs no seal completer afterwards, which matters on
26
+ * an account where no enrolled client's login sweep will ever run again.
27
+ * 3. **The collection fan-out**, still under this client's invocation
28
+ * authority: every encrypted collection re-epochs onto the fresh key.
29
+ * 4. **The generation-delegation replacement and revocations**: a fresh
30
+ * ladder-signed generation delegation replaces the embedded one
31
+ * unconditionally (the forced renewal), and then EVERY still-unexpired
32
+ * delegation the annex log's history ever embedded that this
33
+ * credential's ladder VM signed is revoked at the server (a renewal
34
+ * inside the 30-day window can leave two) -- closing the resurrection
35
+ * window a reinstalled derived-key VM would otherwise reopen. The
36
+ * replacement is what keeps the account transient-login-reachable after
37
+ * the transition; replace-before-revoke is what keeps a torn run from
38
+ * stranding the generation delegation-less.
39
+ * 5. **The other unlock methods' record re-mint** (`unlockMethods`): every
40
+ * other standing credential's and recovery code's bridge (and
41
+ * `delegatedClients` sibling, where the record carries one) is re-signed
42
+ * by the ladder VM and its record re-sealed through the entry's
43
+ * management zcap -- the revocation cascade's re-mint pass
44
+ * (`remintRecoveryDelegations`), run with the ladder VM as the delegating
45
+ * and record-signing key and the forgotten client named as retiring, so
46
+ * every delegation it signed counts as rotted ahead of the removal entry.
47
+ * Delegations the removed client had signed rot at that entry, and on a
48
+ * client-less account no durable login's refresh block will ever run
49
+ * again to heal them, so this is the one pass that reaches them. The
50
+ * HTTP side still invokes under the still-standing client (the
51
+ * management zcaps are granted to the account DID, which only an enrolled
52
+ * client can invoke) -- which is why the stage must run before the
53
+ * removal entry. Best-effort per entry, every entry's fate reported.
54
+ * 6. **The record re-bind seam** (`onBeforeRemoval`): the caller re-signs
55
+ * the LOGIN credential's bridge and `delegatedClients` sibling with the
56
+ * ladder VM and re-seals its unlock record with the credential in hand
57
+ * (a full re-wrap, proof verified rather than settled) -- the one record
58
+ * stage 5 need not reach.
59
+ * 7. **The removal entry** ({@link forgetLastWebvhClient}): the client's
60
+ * whole document footprint out while the installed ladder VM keeps the
61
+ * account anchored. The app's local wipe runs after this ceremony
62
+ * returns.
63
+ *
64
+ * Torn-state map: every stage detects completion from durable state, so a
65
+ * run torn anywhere before the removal entry reads as "not forgotten" and a
66
+ * re-run converges -- the install entry is idempotent, an already-rotated
67
+ * roster skips the append (no second ladder-signed append is ever
68
+ * attempted), the fan-out is staleness-driven, a re-POSTed revocation's 400
69
+ * already-revoked answer reads as success (decision 0006's resume contract),
70
+ * and the forced replacement re-mints (the prior run's fresh delegation is
71
+ * then revoked as history, so a re-run churns one delegation and strands
72
+ * nothing), and the record re-mint re-checks staleness per entry (a record
73
+ * already ladder-signed reads as current). Torn after the removal entry is
74
+ * the finish-the-wipe state the app's next login maps.
75
+ *
76
+ * The honest limitation is the cascade's, as everywhere: ciphertext this
77
+ * browser already fetched stays forensically recoverable from its storage,
78
+ * and old epochs stay open to keys it already held.
79
+ */
80
+ import type { DIDLog } from '@interop/did-method-webvh';
81
+ import type { IKeyAgreementKey, IZcap } from '@interop/data-integrity-core';
82
+ import type { ZcapClient } from '@interop/ezcap';
83
+ import type { CollectionEncryption, IDelegatedZcap } from '@interop/was-client';
84
+ import type { EncryptionDescriptorStore } from '@interop/was-client/edv';
85
+ import { type RevokedClientKeys } from '../webvh/revokeClient.js';
86
+ import type { ResourceLogPinStore } from '../resourceLog/index.js';
87
+ import { type CascadeCollections, type UserKey, type UserKeyCascadeResult } from '../keys/index.js';
88
+ import type { UnlockLogStore } from '../unlock/standingWebvh.js';
89
+ import type { AccountPointer } from '../keyring/record.js';
90
+ import { type RecordRemintOutcome, type RecoveryDelegationEntry } from '../recovery/recoveryDelegation.js';
91
+ import { type ClientAnnexWriteStore } from './log.js';
92
+ /**
93
+ * What the ceremony's generation stage did: the revoked delegation ids, and
94
+ * whether the forced replacement landed. A `skipped` reason names the stage
95
+ * that could not run -- `no-pointer` (the account points at no generation:
96
+ * nothing to revoke or replace), `log-unreadable` (the pointed generation's
97
+ * `did.jsonl` is gone; the delegation bytes are unrecoverable, decision
98
+ * 0006's honest limit), `rung-uncommitted` (this credential cannot write the
99
+ * generation's log; the account lands delegation-less until a
100
+ * fresh-generation heal), `already-removed` (the whole ceremony completed on
101
+ * an earlier run; nothing here can still invoke) -- and a skip never fails
102
+ * the ceremony.
103
+ */
104
+ export interface GenerationDelegationRetirement {
105
+ revoked: string[];
106
+ replaced: boolean;
107
+ skipped?: 'no-pointer' | 'log-unreadable' | 'rung-uncommitted' | 'already-removed';
108
+ }
109
+ /**
110
+ * The other unlock methods' reach for the record re-mint stage: the registry
111
+ * entries to walk (the OTHER methods' -- the login credential's own record is
112
+ * the `onBeforeRemoval` seam's, re-wrapped with the credential in hand; an
113
+ * entry for it here is harmless but redundant), the unlock Spaces' storage
114
+ * server, the management-zcap client factory (invoking as the still-standing
115
+ * client), and the registry record-back seam. The shape is the revocation
116
+ * cascade's re-mint seams verbatim, so an app binds both from one place.
117
+ */
118
+ export interface UnlockMethodsRemintReach<Entry extends RecoveryDelegationEntry = RecoveryDelegationEntry> {
119
+ entries: Entry[];
120
+ pointer: AccountPointer;
121
+ storageServerUrl: string;
122
+ managementZcapClient: (options: {
123
+ capability: IZcap;
124
+ }) => ZcapClient;
125
+ recordEntry: (options: {
126
+ entry: Entry;
127
+ }) => Promise<void>;
128
+ }
129
+ /**
130
+ * What a completed last-client forget reports: whether the install entry ran
131
+ * on this call (`false` on a resumed run), whether the roster's wrap for the
132
+ * forgotten client was retired on this run, the per-collection fan-out
133
+ * result, the generation stage's report, the other unlock methods' record
134
+ * re-mint report (present when the caller supplied the reach: the counts and
135
+ * every entry's fate, so a record the pass could not reach is named rather
136
+ * than silently left with a rotted bridge), the document as the removal entry
137
+ * left it, and -- when the account has a roster -- the rotated key with the
138
+ * roster descriptor it was read from.
139
+ */
140
+ export interface LastDurableClientForgetResult {
141
+ installed: boolean;
142
+ rotated: boolean;
143
+ collections: UserKeyCascadeResult;
144
+ generation: GenerationDelegationRetirement;
145
+ unlockMethods?: {
146
+ reminted: number;
147
+ skipped: number;
148
+ outcomes: RecordRemintOutcome[];
149
+ };
150
+ did: string;
151
+ document: object;
152
+ userKey?: UserKey;
153
+ rosterDescriptor?: CollectionEncryption;
154
+ }
155
+ /**
156
+ * Forgets the account's LAST enrolled durable client -- this browser's own
157
+ * -- transitioning the account to the client-less, ladder-anchored state.
158
+ * See the module doc for the stage order and the torn-state map. The caller
159
+ * runs the local wipe only after this resolves. An account with another
160
+ * enrolled durable client refuses: that forget is the ordinary ceremony
161
+ * (`forgetDurableClient`), reached first, whose `LastDurableClientForgetError`
162
+ * is what routes callers here.
163
+ *
164
+ * @param options {object}
165
+ * @param options.logStore {UnlockLogStore} the credential's delegated
166
+ * `did.jsonl` bridge store; also serves the ceremony's public reads. The
167
+ * caller is expected to have verified the account log under its own
168
+ * chain-head pins in the same session (the ceremony re-reads through the
169
+ * seam and checks `expectedDid`, but carries no account-log pin store
170
+ * itself)
171
+ * @param options.ladderSeed {Uint8Array} the login credential's ladder seed
172
+ * @param options.forgottenClient {RevokedClientKeys} this client's public
173
+ * halves; an `updateKeyMultibase` the log does not authorize (stale, or the
174
+ * staged key) is re-derived from the log
175
+ * @param options.forgottenKeyAgreementKeyMultibase {string} this client's
176
+ * identity key-agreement key (the X25519 twin), naming its roster wrap
177
+ * @param [options.knownLatentHashes] {string[]} standing latent commitments
178
+ * the caller vouches for (the recovery registry's update-key hashes),
179
+ * excluded from the staged-hash attribution
180
+ * @param options.expectedDid {string} the account DID from the caller's
181
+ * stored account pointer
182
+ * @param options.rosterStoreFor {Function} `({ did, log }) => store` --
183
+ * builds the `key-map/user-key.jsonl` roster store whose appends are
184
+ * SIGNED BY THE LADDER VM and whose controller view resolves from the
185
+ * supplied post-install log (the posture-changing anchor the ceremony-tail
186
+ * license admits), while its HTTP requests invoke under the still-standing
187
+ * client
188
+ * @param options.credentialKeyAgreementKey {IKeyAgreementKey} the standing
189
+ * credential's key-agreement key -- the recipient whose wrap survives the
190
+ * rotation, reading the fresh key back and unwrapping the generations for
191
+ * the fan-out
192
+ * @param [options.userKey] {UserKey} this client's cached user key
193
+ * @param [options.pinnedEpochId] {string} the locally pinned latest-seen
194
+ * roster epoch
195
+ * @param [options.onUserKeyAdopted] {Function} persists a rotated key:
196
+ * called with `{ userKey, latestEpochId, descriptor }` after the roster
197
+ * read and BEFORE the fan-out
198
+ * @param options.collections {CascadeCollections} the fan-out's work
199
+ * @param options.annex {object} the generation stage's reach:
200
+ * @param options.annex.storeFor {Function}
201
+ * `({ spaceId, generationId }) => ClientAnnexWriteStore` -- the pointed
202
+ * generation's log store, reading and writing under the still-standing
203
+ * client's authority
204
+ * @param options.annex.revoke {Function} `(delegation) => Promise<void>`
205
+ * -- POSTs a revocation (was-client's `WasClient#revoke`, bound by the
206
+ * caller; the invocation signs as the still-standing client)
207
+ * @param options.annex.wasServerUrl {string} the ACCOUNT Space's storage
208
+ * server (the fresh generation delegation's target host)
209
+ * @param options.annex.accountSpaceId {string} the ACCOUNT Space's id (the
210
+ * fresh delegation's target subtree)
211
+ * @param [options.annex.pinStore] {ResourceLogPinStore} chain-head pins
212
+ * for the pointed generation's read
213
+ * @param [options.unlockMethods] {UnlockMethodsRemintReach} the other
214
+ * unlock methods' record re-mint reach (stage 5): the registry entries
215
+ * whose bridge (and sibling) the ladder VM re-signs and whose records it
216
+ * re-seals through their management zcaps, invoked as the still-standing
217
+ * client. Omitted, the stage is skipped and the result carries no
218
+ * `unlockMethods` report -- the residue decision 0004's amendment stated
219
+ * @param [options.onBeforeRemoval] {Function}
220
+ * `({ did, doc, log }) => Promise<void>` -- the record re-bind seam: runs
221
+ * after the record re-mint stage, immediately before the removal entry,
222
+ * with the post-install published state. The caller re-signs the login
223
+ * credential's bridge and `delegatedClients` sibling with the ladder VM
224
+ * and re-seals its unlock record here. Must be idempotent (a resumed run
225
+ * invokes it again)
226
+ * @param [options.now] {number} epoch milliseconds, for tests
227
+ * @returns {Promise<LastDurableClientForgetResult>}
228
+ */
229
+ export declare function forgetLastDurableClient({ logStore, ladderSeed, forgottenClient, forgottenKeyAgreementKeyMultibase, knownLatentHashes, expectedDid, rosterStoreFor, credentialKeyAgreementKey, userKey, pinnedEpochId, onUserKeyAdopted, collections, annex, unlockMethods, onBeforeRemoval, now }: {
230
+ logStore: UnlockLogStore;
231
+ ladderSeed: Uint8Array;
232
+ forgottenClient: RevokedClientKeys;
233
+ forgottenKeyAgreementKeyMultibase: string;
234
+ knownLatentHashes?: string[];
235
+ expectedDid: string;
236
+ rosterStoreFor: (options: {
237
+ did: string;
238
+ log: DIDLog;
239
+ }) => EncryptionDescriptorStore;
240
+ credentialKeyAgreementKey: IKeyAgreementKey;
241
+ userKey?: UserKey;
242
+ pinnedEpochId?: string | null;
243
+ onUserKeyAdopted?: (adopted: {
244
+ userKey: UserKey;
245
+ latestEpochId: string;
246
+ descriptor: CollectionEncryption;
247
+ }) => Promise<void>;
248
+ collections: CascadeCollections;
249
+ annex: {
250
+ storeFor: (options: {
251
+ spaceId: string;
252
+ generationId: string;
253
+ }) => ClientAnnexWriteStore;
254
+ revoke: (delegation: IDelegatedZcap) => Promise<void>;
255
+ wasServerUrl: string;
256
+ accountSpaceId: string;
257
+ pinStore?: ResourceLogPinStore;
258
+ };
259
+ unlockMethods?: UnlockMethodsRemintReach;
260
+ onBeforeRemoval?: (published: {
261
+ did: string;
262
+ doc: object;
263
+ log: DIDLog;
264
+ }) => Promise<void>;
265
+ now?: number;
266
+ }): Promise<LastDurableClientForgetResult>;
267
+ //# sourceMappingURL=forgetLast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forgetLast.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/forgetLast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,374 @@
1
+ import { readPublishedLog, relationIds } from '../webvh/didWebvh.js';
2
+ import { clientRemovalTarget } from '../webvh/revokeClient.js';
3
+ import { delegationProofKeyId } from '../webvh/standingZcap.js';
4
+ import { vmFragmentOf } from '../resourceLog/index.js';
5
+ import { cascadeCollectionsToUserKey, readUserKeyRoster, rosterRecipientKid, rotateUserKeyRoster } from '../keys/index.js';
6
+ import { readLogOrThrow } from '../unlock/standingWebvh.js';
7
+ import { recordSignerFromAgent } from '../keyring/record.js';
8
+ import { remintRecoveryDelegations } from '../recovery/recoveryDelegation.js';
9
+ import { ladderVmKeyMultibase } from './ladder.js';
10
+ import { ladderVmAgent, ladderVmZcapClient } from './zcap.js';
11
+ import { forgetLastWebvhClient, installLadderVmWebvh } from './ladderAnchored.js';
12
+ import { clientAnnexDidParts, clientAnnexLogPinId, delegatedClientsDelegationMinter, delegatedClientsPointer, ensureGenerationDelegationCurrent, generationDelegationHistory, mintGenerationDelegation, revokeTreatingAlreadyRevokedAsSuccess } from './log.js';
13
+ /**
14
+ * Forgets the account's LAST enrolled durable client -- this browser's own
15
+ * -- transitioning the account to the client-less, ladder-anchored state.
16
+ * See the module doc for the stage order and the torn-state map. The caller
17
+ * runs the local wipe only after this resolves. An account with another
18
+ * enrolled durable client refuses: that forget is the ordinary ceremony
19
+ * (`forgetDurableClient`), reached first, whose `LastDurableClientForgetError`
20
+ * is what routes callers here.
21
+ *
22
+ * @param options {object}
23
+ * @param options.logStore {UnlockLogStore} the credential's delegated
24
+ * `did.jsonl` bridge store; also serves the ceremony's public reads. The
25
+ * caller is expected to have verified the account log under its own
26
+ * chain-head pins in the same session (the ceremony re-reads through the
27
+ * seam and checks `expectedDid`, but carries no account-log pin store
28
+ * itself)
29
+ * @param options.ladderSeed {Uint8Array} the login credential's ladder seed
30
+ * @param options.forgottenClient {RevokedClientKeys} this client's public
31
+ * halves; an `updateKeyMultibase` the log does not authorize (stale, or the
32
+ * staged key) is re-derived from the log
33
+ * @param options.forgottenKeyAgreementKeyMultibase {string} this client's
34
+ * identity key-agreement key (the X25519 twin), naming its roster wrap
35
+ * @param [options.knownLatentHashes] {string[]} standing latent commitments
36
+ * the caller vouches for (the recovery registry's update-key hashes),
37
+ * excluded from the staged-hash attribution
38
+ * @param options.expectedDid {string} the account DID from the caller's
39
+ * stored account pointer
40
+ * @param options.rosterStoreFor {Function} `({ did, log }) => store` --
41
+ * builds the `key-map/user-key.jsonl` roster store whose appends are
42
+ * SIGNED BY THE LADDER VM and whose controller view resolves from the
43
+ * supplied post-install log (the posture-changing anchor the ceremony-tail
44
+ * license admits), while its HTTP requests invoke under the still-standing
45
+ * client
46
+ * @param options.credentialKeyAgreementKey {IKeyAgreementKey} the standing
47
+ * credential's key-agreement key -- the recipient whose wrap survives the
48
+ * rotation, reading the fresh key back and unwrapping the generations for
49
+ * the fan-out
50
+ * @param [options.userKey] {UserKey} this client's cached user key
51
+ * @param [options.pinnedEpochId] {string} the locally pinned latest-seen
52
+ * roster epoch
53
+ * @param [options.onUserKeyAdopted] {Function} persists a rotated key:
54
+ * called with `{ userKey, latestEpochId, descriptor }` after the roster
55
+ * read and BEFORE the fan-out
56
+ * @param options.collections {CascadeCollections} the fan-out's work
57
+ * @param options.annex {object} the generation stage's reach:
58
+ * @param options.annex.storeFor {Function}
59
+ * `({ spaceId, generationId }) => ClientAnnexWriteStore` -- the pointed
60
+ * generation's log store, reading and writing under the still-standing
61
+ * client's authority
62
+ * @param options.annex.revoke {Function} `(delegation) => Promise<void>`
63
+ * -- POSTs a revocation (was-client's `WasClient#revoke`, bound by the
64
+ * caller; the invocation signs as the still-standing client)
65
+ * @param options.annex.wasServerUrl {string} the ACCOUNT Space's storage
66
+ * server (the fresh generation delegation's target host)
67
+ * @param options.annex.accountSpaceId {string} the ACCOUNT Space's id (the
68
+ * fresh delegation's target subtree)
69
+ * @param [options.annex.pinStore] {ResourceLogPinStore} chain-head pins
70
+ * for the pointed generation's read
71
+ * @param [options.unlockMethods] {UnlockMethodsRemintReach} the other
72
+ * unlock methods' record re-mint reach (stage 5): the registry entries
73
+ * whose bridge (and sibling) the ladder VM re-signs and whose records it
74
+ * re-seals through their management zcaps, invoked as the still-standing
75
+ * client. Omitted, the stage is skipped and the result carries no
76
+ * `unlockMethods` report -- the residue decision 0004's amendment stated
77
+ * @param [options.onBeforeRemoval] {Function}
78
+ * `({ did, doc, log }) => Promise<void>` -- the record re-bind seam: runs
79
+ * after the record re-mint stage, immediately before the removal entry,
80
+ * with the post-install published state. The caller re-signs the login
81
+ * credential's bridge and `delegatedClients` sibling with the ladder VM
82
+ * and re-seals its unlock record here. Must be idempotent (a resumed run
83
+ * invokes it again)
84
+ * @param [options.now] {number} epoch milliseconds, for tests
85
+ * @returns {Promise<LastDurableClientForgetResult>}
86
+ */
87
+ export async function forgetLastDurableClient({ logStore, ladderSeed, forgottenClient, forgottenKeyAgreementKeyMultibase, knownLatentHashes, expectedDid, rosterStoreFor, credentialKeyAgreementKey, userKey, pinnedEpochId, onUserKeyAdopted, collections, annex, unlockMethods, onBeforeRemoval, now = Date.now() }) {
88
+ // The pre-install read and the two guards: a client with no remaining
89
+ // presence means the removal entry already landed (the finish-the-wipe
90
+ // state the app's next login maps -- nothing here can still invoke), and
91
+ // an account with another enrolled durable client belongs to the ordinary
92
+ // forget ceremony.
93
+ const before = await readLogOrThrow({ store: logStore, expectedDid });
94
+ const preTarget = await clientRemovalTarget({
95
+ published: before,
96
+ client: forgottenClient
97
+ });
98
+ if (!preTarget.present) {
99
+ return {
100
+ installed: false,
101
+ rotated: false,
102
+ collections: { outcomes: {}, failed: [] },
103
+ generation: { revoked: [], replaced: false, skipped: 'already-removed' },
104
+ did: before.did,
105
+ document: before.doc
106
+ };
107
+ }
108
+ const signingVmId = `${before.did}#${forgottenClient.signingKeyMultibase}`;
109
+ const invocationIds = relationIds(before.doc.capabilityInvocation);
110
+ if (invocationIds.some(id => id !== signingVmId)) {
111
+ throw new Error('did:webvh: another enrolled durable client remains; the last-client ' +
112
+ 'transition ceremony does not apply -- run the ordinary forget.');
113
+ }
114
+ // Stage 1: the install entry -- the ladder VM in, the client untouched.
115
+ const install = await installLadderVmWebvh({
116
+ store: logStore,
117
+ ladderSeed,
118
+ expectedDid
119
+ });
120
+ // Stage 2: the roster rotation off this client's wrap, ladder-signed and
121
+ // anchored at the install entry, then stage 3, the collection fan-out --
122
+ // both HTTP-invoked under this client's still-standing authority. An
123
+ // already-rotated roster skips the append entirely, so the one-shot
124
+ // license is never asked for a second append at the same anchor.
125
+ let rotated = false;
126
+ let read;
127
+ let cascade = { outcomes: {}, failed: [] };
128
+ const rosterStore = rosterStoreFor({ did: install.did, log: install.log });
129
+ const current = await rosterStore.read();
130
+ if (current !== null) {
131
+ const forgottenKid = rosterRecipientKid({
132
+ signingKeyMultibase: forgottenClient.signingKeyMultibase,
133
+ keyAgreementKeyMultibase: forgottenKeyAgreementKeyMultibase
134
+ });
135
+ let descriptor = current.descriptor;
136
+ const currentEpoch = (descriptor.epochs ?? []).find(epoch => epoch.id === descriptor.currentEpoch);
137
+ const wrapped = currentEpoch?.recipients.some(entry => entry.header.kid === forgottenKid);
138
+ if (wrapped) {
139
+ descriptor = await rotateUserKeyRoster({
140
+ store: rosterStore,
141
+ document: install.doc,
142
+ retireRecipientId: forgottenKid
143
+ });
144
+ rotated = true;
145
+ }
146
+ // The fresh key comes back through the credential's standing wrap -- this
147
+ // client's own is gone from the current epoch -- with the continuity and
148
+ // possession checks still running on the threaded descriptor.
149
+ const adopted = await readUserKeyRoster({
150
+ store: rosterStore,
151
+ descriptor,
152
+ ...(userKey ? { userKey } : {}),
153
+ clientKeyAgreementKey: credentialKeyAgreementKey,
154
+ pinnedEpochId
155
+ });
156
+ if (adopted.rotated) {
157
+ await onUserKeyAdopted?.({
158
+ userKey: adopted.userKey,
159
+ latestEpochId: adopted.latestEpochId,
160
+ descriptor: adopted.descriptor
161
+ });
162
+ }
163
+ read = { userKey: adopted.userKey, descriptor: adopted.descriptor };
164
+ cascade = await cascadeCollectionsToUserKey({
165
+ collectionIds: typeof collections.collectionIds === 'function'
166
+ ? await collections.collectionIds()
167
+ : collections.collectionIds,
168
+ storeFor: collections.storeFor,
169
+ ...(collections.isEncrypted
170
+ ? { isEncrypted: collections.isEncrypted }
171
+ : {}),
172
+ rosterDescriptor: adopted.descriptor,
173
+ clientKeyAgreementKey: credentialKeyAgreementKey,
174
+ userKey: adopted.userKey
175
+ });
176
+ }
177
+ // Stage 4: the generation-delegation replacement and revocations.
178
+ const generation = await retireLadderGenerationDelegations({
179
+ doc: install.doc,
180
+ accountDid: install.did,
181
+ ladderSeed,
182
+ annex,
183
+ now
184
+ });
185
+ // Stage 5: the other unlock methods' record re-mint, ladder-signed, with
186
+ // the forgotten client named as retiring -- the post-install document
187
+ // still lists it, so without that axis every bridge it signed would read
188
+ // as standing and be left to rot at the removal entry.
189
+ let remint;
190
+ if (unlockMethods !== undefined) {
191
+ remint = await remintUnlockMethodRecordsAsLadder({
192
+ doc: install.doc,
193
+ accountDid: install.did,
194
+ ladderSeed,
195
+ retiringSigningKeyMultibase: forgottenClient.signingKeyMultibase,
196
+ reach: unlockMethods,
197
+ now
198
+ });
199
+ }
200
+ // Stage 6: the record re-bind seam, while the removal has not landed (a
201
+ // ladder-VM-signed bridge verifies from the install entry on, and the old
202
+ // client-signed one keeps verifying until the removal -- so a tear on
203
+ // either side of this callback leaves a working login).
204
+ await onBeforeRemoval?.({
205
+ did: install.did,
206
+ doc: install.doc,
207
+ log: install.log
208
+ });
209
+ // Stage 7: the removal entry -- the client's whole footprint out, the
210
+ // installed ladder VM keeping the account anchored.
211
+ const removed = await forgetLastWebvhClient({
212
+ store: logStore,
213
+ ladderSeed,
214
+ forgottenClient,
215
+ ...(knownLatentHashes ? { knownLatentHashes } : {}),
216
+ expectedDid
217
+ });
218
+ return {
219
+ installed: install.installed,
220
+ rotated,
221
+ collections: cascade,
222
+ generation,
223
+ ...(remint ? { unlockMethods: remint } : {}),
224
+ did: removed.did,
225
+ document: removed.doc,
226
+ ...(read
227
+ ? { userKey: read.userKey, rosterDescriptor: read.descriptor }
228
+ : {})
229
+ };
230
+ }
231
+ /**
232
+ * The generation stage: reads the pointed generation's log, force-replaces
233
+ * the embedded delegation with a fresh ladder-signed one (so the account
234
+ * stays transient-login-reachable), then revokes every still-unexpired
235
+ * delegation the log's history embedded that this credential's ladder VM
236
+ * signed. Replace-before-revoke is the tear-safety order: the fresh
237
+ * delegation is never in the pre-replacement history, so the revocation loop
238
+ * cannot touch it, and a run torn between the two leaves the generation with
239
+ * a live delegation either way.
240
+ *
241
+ * @param options {object}
242
+ * @param options.doc {DIDDoc} the post-install account document
243
+ * @param options.accountDid {string}
244
+ * @param options.ladderSeed {Uint8Array}
245
+ * @param options.annex {object} see {@link forgetLastDurableClient}
246
+ * @param options.now {number}
247
+ * @returns {Promise<GenerationDelegationRetirement>}
248
+ */
249
+ async function retireLadderGenerationDelegations({ doc, accountDid, ladderSeed, annex, now }) {
250
+ const pointedDid = delegatedClientsPointer({ doc });
251
+ if (pointedDid === undefined) {
252
+ return { revoked: [], replaced: false, skipped: 'no-pointer' };
253
+ }
254
+ const parts = clientAnnexDidParts({ did: pointedDid });
255
+ const store = annex.storeFor(parts);
256
+ const logId = clientAnnexLogPinId(parts);
257
+ // readPublishedLog only calls getIdResourceRaw, so the narrow seam is safe.
258
+ const published = await readPublishedLog({
259
+ idStore: store,
260
+ expectedDid: pointedDid,
261
+ ...(annex.pinStore !== undefined ? { pinStore: annex.pinStore, logId } : {})
262
+ });
263
+ if (published === undefined) {
264
+ return { revoked: [], replaced: false, skipped: 'log-unreadable' };
265
+ }
266
+ // The doomed set, collected BEFORE the replacement so the fresh delegation
267
+ // can never join it: every delegation the history embedded whose proof key
268
+ // is this credential's ladder VM and whose expiry has not passed. An
269
+ // unparseable or absent expiry counts as unexpired -- fail-safe, since an
270
+ // unbounded delegation is the worst resurrection credential.
271
+ const ladderVmKey = await ladderVmKeyMultibase({ ladderSeed });
272
+ const doomed = generationDelegationHistory({ log: published.log }).filter(delegation => {
273
+ const proofKeyId = delegationProofKeyId(delegation);
274
+ const fragment = proofKeyId === undefined ? null : vmFragmentOf(proofKeyId);
275
+ if (fragment !== ladderVmKey) {
276
+ return false;
277
+ }
278
+ const expires = Date.parse(delegation.expires ?? '');
279
+ return Number.isNaN(expires) || expires > now;
280
+ });
281
+ // The forced replacement first: a ladder-signed fresh delegation under the
282
+ // reinstalled VM, the annex entry signed by this credential's committed
283
+ // annex rung. A credential the generation does not commit cannot write the
284
+ // entry -- the honest skip, leaving the generation delegation-less once
285
+ // the doomed set is revoked below.
286
+ let replaced = false;
287
+ const ladderClient = await ladderVmZcapClient({ accountDid, ladderSeed });
288
+ try {
289
+ await ensureGenerationDelegationCurrent({
290
+ store,
291
+ ladderSeed,
292
+ generationId: parts.generationId,
293
+ mintGenerationDelegation: async ({ clientAnnexDid }) => mintGenerationDelegation({
294
+ zcapClient: ladderClient,
295
+ wasServerUrl: annex.wasServerUrl,
296
+ spaceId: annex.accountSpaceId,
297
+ clientAnnexDid,
298
+ now
299
+ }),
300
+ expectedDid: pointedDid,
301
+ force: true,
302
+ ...(annex.pinStore !== undefined
303
+ ? { pinStore: annex.pinStore, logId }
304
+ : {}),
305
+ now
306
+ });
307
+ replaced = true;
308
+ }
309
+ catch (err) {
310
+ if (err.name !== 'ClientAnnexRungUncommittedError') {
311
+ throw err;
312
+ }
313
+ }
314
+ // The revocations, blind and resumable (400 already-revoked as success).
315
+ const revoked = [];
316
+ for (const delegation of doomed) {
317
+ await revokeTreatingAlreadyRevokedAsSuccess({
318
+ revoke: annex.revoke,
319
+ delegation
320
+ });
321
+ const id = delegation.id;
322
+ if (typeof id === 'string') {
323
+ revoked.push(id);
324
+ }
325
+ }
326
+ return replaced
327
+ ? { revoked, replaced }
328
+ : { revoked, replaced, skipped: 'rung-uncommitted' };
329
+ }
330
+ /**
331
+ * The record re-mint stage: the revocation cascade's re-mint pass over the
332
+ * other unlock methods' registry entries, with the ladder VM as both the
333
+ * delegating key (the fresh bridge and sibling) and the record-frame signer
334
+ * (`ladderVmAgent`'s did:key form, whose multibase the post-install document
335
+ * lists, so a reader settling the mixed-signer proof against the account
336
+ * document accepts it after the removal too -- `currentAccountRecordSigners`
337
+ * is that allowlist), and the forgotten client named as retiring. The sibling
338
+ * minter reads the annex pointer off the post-install document. The HTTP
339
+ * side rides the caller's management-zcap clients, still invocable here.
340
+ *
341
+ * @param options {object}
342
+ * @param options.doc {DIDDoc} the post-install account document
343
+ * @param options.accountDid {string}
344
+ * @param options.ladderSeed {Uint8Array}
345
+ * @param options.retiringSigningKeyMultibase {string} the forgotten
346
+ * client's signing key
347
+ * @param options.reach {UnlockMethodsRemintReach}
348
+ * @param options.now {number}
349
+ * @returns {Promise<object>} the pass's counts and per-entry outcomes
350
+ */
351
+ async function remintUnlockMethodRecordsAsLadder({ doc, accountDid, ladderSeed, retiringSigningKeyMultibase, reach, now }) {
352
+ const ladderClient = await ladderVmZcapClient({ accountDid, ladderSeed });
353
+ const recordSigner = recordSignerFromAgent({
354
+ keyAgent: await ladderVmAgent({ ladderSeed })
355
+ });
356
+ return remintRecoveryDelegations({
357
+ doc,
358
+ entries: reach.entries,
359
+ pointer: reach.pointer,
360
+ storageServerUrl: reach.storageServerUrl,
361
+ zcapClient: ladderClient,
362
+ recordSigner,
363
+ managementZcapClient: reach.managementZcapClient,
364
+ recordEntry: reach.recordEntry,
365
+ mintDelegatedClientsDelegation: delegatedClientsDelegationMinter({
366
+ doc,
367
+ zcapClient: ladderClient,
368
+ wasServerUrl: reach.pointer.host
369
+ }),
370
+ retiringKeyMultibases: [retiringSigningKeyMultibase],
371
+ now
372
+ });
373
+ }
374
+ //# sourceMappingURL=forgetLast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forgetLast.js","sourceRoot":"","sources":["../../src/clientAnnex/forgetLast.ts"],"names":[],"mappings":"AAoFA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEpE,OAAO,EACL,mBAAmB,EAEpB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EAIpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EACL,yBAAyB,EAG1B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,uBAAuB,EACvB,iCAAiC,EACjC,2BAA2B,EAC3B,wBAAwB,EACxB,qCAAqC,EAEtC,MAAM,UAAU,CAAA;AAmEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAC5C,QAAQ,EACR,UAAU,EACV,eAAe,EACf,iCAAiC,EACjC,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,yBAAyB,EACzB,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,KAAK,EACL,aAAa,EACb,eAAe,EACf,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAsCjB;IACC,sEAAsE;IACtE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,mBAAmB;IACnB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;IACrE,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC;QAC1C,SAAS,EAAE,MAAM;QACjB,MAAM,EAAE,eAAe;KACxB,CAAC,CAAA;IACF,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACzC,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE;YACxE,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,QAAQ,EAAE,MAAM,CAAC,GAAG;SACrB,CAAA;IACH,CAAC;IACD,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,mBAAmB,EAAE,CAAA;IAC1E,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAClE,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,WAAW,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,gEAAgE,CACnE,CAAA;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC;QACzC,KAAK,EAAE,QAAQ;QACf,UAAU;QACV,WAAW;KACZ,CAAC,CAAA;IAEF,yEAAyE;IACzE,yEAAyE;IACzE,qEAAqE;IACrE,oEAAoE;IACpE,iEAAiE;IACjE,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,IAAwE,CAAA;IAC5E,IAAI,OAAO,GAAyB,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAChE,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAA;IACxC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,kBAAkB,CAAC;YACtC,mBAAmB,EAAE,eAAe,CAAC,mBAAmB;YACxD,wBAAwB,EAAE,iCAAiC;SAC5D,CAAC,CAAA;QACF,IAAI,UAAU,GAAG,OAAO,CAAC,UAAU,CAAA;QACnC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CACjD,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,UAAU,CAAC,YAAY,CAC9C,CAAA;QACD,MAAM,OAAO,GAAG,YAAY,EAAE,UAAU,CAAC,IAAI,CAC3C,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,YAAY,CAC3C,CAAA;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,UAAU,GAAG,MAAM,mBAAmB,CAAC;gBACrC,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,iBAAiB,EAAE,YAAY;aAChC,CAAC,CAAA;YACF,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;QACD,0EAA0E;QAC1E,yEAAyE;QACzE,8DAA8D;QAC9D,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC;YACtC,KAAK,EAAE,WAAW;YAClB,UAAU;YACV,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,qBAAqB,EAAE,yBAAyB;YAChD,aAAa;SACd,CAAC,CAAA;QACF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,gBAAgB,EAAE,CAAC;gBACvB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAA;QACnE,OAAO,GAAG,MAAM,2BAA2B,CAAC;YAC1C,aAAa,EACX,OAAO,WAAW,CAAC,aAAa,KAAK,UAAU;gBAC7C,CAAC,CAAC,MAAM,WAAW,CAAC,aAAa,EAAE;gBACnC,CAAC,CAAC,WAAW,CAAC,aAAa;YAC/B,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,GAAG,CAAC,WAAW,CAAC,WAAW;gBACzB,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE;gBAC1C,CAAC,CAAC,EAAE,CAAC;YACP,gBAAgB,EAAE,OAAO,CAAC,UAAU;YACpC,qBAAqB,EAAE,yBAAyB;YAChD,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,kEAAkE;IAClE,MAAM,UAAU,GAAG,MAAM,iCAAiC,CAAC;QACzD,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,UAAU,EAAE,OAAO,CAAC,GAAG;QACvB,UAAU;QACV,KAAK;QACL,GAAG;KACJ,CAAC,CAAA;IAEF,yEAAyE;IACzE,sEAAsE;IACtE,yEAAyE;IACzE,uDAAuD;IACvD,IAAI,MAAsD,CAAA;IAC1D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,GAAG,MAAM,iCAAiC,CAAC;YAC/C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,UAAU,EAAE,OAAO,CAAC,GAAG;YACvB,UAAU;YACV,2BAA2B,EAAE,eAAe,CAAC,mBAAmB;YAChE,KAAK,EAAE,aAAa;YACpB,GAAG;SACJ,CAAC,CAAA;IACJ,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,sEAAsE;IACtE,wDAAwD;IACxD,MAAM,eAAe,EAAE,CAAC;QACtB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAA;IAEF,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC;QAC1C,KAAK,EAAE,QAAQ;QACf,UAAU;QACV,eAAe;QACf,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,WAAW;KACZ,CAAC,CAAA;IAEF,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO;QACP,WAAW,EAAE,OAAO;QACpB,UAAU;QACV,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,GAAG;QACrB,GAAG,CAAC,IAAI;YACN,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,CAAC,UAAU,EAAE;YAC9D,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,KAAK,UAAU,iCAAiC,CAAC,EAC/C,GAAG,EACH,UAAU,EACV,UAAU,EACV,KAAK,EACL,GAAG,EAgBJ;IACC,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IACnD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA;IAChE,CAAC;IACD,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnC,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACxC,4EAA4E;IAC5E,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC;QACvC,OAAO,EAAE,KAAqB;QAC9B,WAAW,EAAE,UAAU;QACvB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7E,CAAC,CAAA;IACF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAA;IACpE,CAAC;IAED,2EAA2E;IAC3E,2EAA2E;IAC3E,qEAAqE;IACrE,0EAA0E;IAC1E,6DAA6D;IAC7D,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IAC9D,MAAM,MAAM,GAAG,2BAA2B,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CACvE,UAAU,CAAC,EAAE;QACX,MAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAA;QACnD,MAAM,QAAQ,GACZ,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;QAC5D,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACvB,UAAmC,CAAC,OAAO,IAAI,EAAE,CACnD,CAAA;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,GAAG,CAAA;IAC/C,CAAC,CACF,CAAA;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,wEAAwE;IACxE,mCAAmC;IACnC,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACzE,IAAI,CAAC;QACH,MAAM,iCAAiC,CAAC;YACtC,KAAK;YACL,UAAU;YACV,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,wBAAwB,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CACrD,wBAAwB,CAAC;gBACvB,UAAU,EAAE,YAAY;gBACxB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,OAAO,EAAE,KAAK,CAAC,cAAc;gBAC7B,cAAc;gBACd,GAAG;aACJ,CAAC;YACJ,WAAW,EAAE,UAAU;YACvB,KAAK,EAAE,IAAI;YACX,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;gBAC9B,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE;gBACrC,CAAC,CAAC,EAAE,CAAC;YACP,GAAG;SACJ,CAAC,CAAA;QACF,QAAQ,GAAG,IAAI,CAAA;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAAyB,CAAC,IAAI,KAAK,iCAAiC,EAAE,CAAC;YAC1E,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;QAChC,MAAM,qCAAqC,CAAC;YAC1C,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU;SACX,CAAC,CAAA;QACF,MAAM,EAAE,GAAI,UAA8B,CAAC,EAAE,CAAA;QAC7C,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ;QACb,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACvB,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAA;AACxD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,KAAK,UAAU,iCAAiC,CAAC,EAC/C,GAAG,EACH,UAAU,EACV,UAAU,EACV,2BAA2B,EAC3B,KAAK,EACL,GAAG,EAQJ;IACC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACzE,MAAM,YAAY,GAAG,qBAAqB,CAAC;QACzC,QAAQ,EAAE,MAAM,aAAa,CAAC,EAAE,UAAU,EAAE,CAAC;KAC9C,CAAC,CAAA;IACF,OAAO,yBAAyB,CAAC;QAC/B,GAAG;QACH,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,UAAU,EAAE,YAAY;QACxB,YAAY;QACZ,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,8BAA8B,EAAE,gCAAgC,CAAC;YAC/D,GAAG;YACH,UAAU,EAAE,YAAY;YACxB,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI;SACjC,CAAC;QACF,qBAAqB,EAAE,CAAC,2BAA2B,CAAC;QACpD,GAAG;KACJ,CAAC,CAAA;AACJ,CAAC"}