@interop/wallet-core 0.101.0 → 0.103.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 (123) hide show
  1. package/README.md +35 -19
  2. package/dist/audiences/audienceGrant.d.ts +49 -0
  3. package/dist/audiences/audienceGrant.d.ts.map +1 -0
  4. package/dist/audiences/audienceGrant.js +46 -0
  5. package/dist/audiences/audienceGrant.js.map +1 -0
  6. package/dist/audiences/index.d.ts +10 -0
  7. package/dist/audiences/index.d.ts.map +1 -0
  8. package/dist/audiences/index.js +10 -0
  9. package/dist/audiences/index.js.map +1 -0
  10. package/dist/clientAnnex/gc.d.ts +107 -25
  11. package/dist/clientAnnex/gc.d.ts.map +1 -1
  12. package/dist/clientAnnex/gc.js +258 -89
  13. package/dist/clientAnnex/gc.js.map +1 -1
  14. package/dist/clientAnnex/grantRevocation.d.ts +0 -10
  15. package/dist/clientAnnex/grantRevocation.d.ts.map +1 -1
  16. package/dist/clientAnnex/grantRevocation.js +1 -23
  17. package/dist/clientAnnex/grantRevocation.js.map +1 -1
  18. package/dist/clientAnnex/heal.d.ts +32 -0
  19. package/dist/clientAnnex/heal.d.ts.map +1 -1
  20. package/dist/clientAnnex/heal.js +52 -50
  21. package/dist/clientAnnex/heal.js.map +1 -1
  22. package/dist/clientAnnex/index.d.ts +2 -2
  23. package/dist/clientAnnex/index.d.ts.map +1 -1
  24. package/dist/clientAnnex/index.js +2 -2
  25. package/dist/clientAnnex/index.js.map +1 -1
  26. package/dist/clientAnnex/log.d.ts +20 -2
  27. package/dist/clientAnnex/log.d.ts.map +1 -1
  28. package/dist/clientAnnex/log.js +30 -4
  29. package/dist/clientAnnex/log.js.map +1 -1
  30. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  31. package/dist/clients/rosterPolicy.js +3 -1
  32. package/dist/clients/rosterPolicy.js.map +1 -1
  33. package/dist/connections/didKey.d.ts +27 -0
  34. package/dist/connections/didKey.d.ts.map +1 -1
  35. package/dist/connections/didKey.js +42 -6
  36. package/dist/connections/didKey.js.map +1 -1
  37. package/dist/connections/entry.d.ts +95 -13
  38. package/dist/connections/entry.d.ts.map +1 -1
  39. package/dist/connections/entry.js +102 -16
  40. package/dist/connections/entry.js.map +1 -1
  41. package/dist/connections/grants.d.ts +225 -3
  42. package/dist/connections/grants.d.ts.map +1 -1
  43. package/dist/connections/grants.js +293 -8
  44. package/dist/connections/grants.js.map +1 -1
  45. package/dist/connections/index.d.ts +15 -8
  46. package/dist/connections/index.d.ts.map +1 -1
  47. package/dist/connections/index.js +13 -6
  48. package/dist/connections/index.js.map +1 -1
  49. package/dist/connections/read.d.ts.map +1 -1
  50. package/dist/connections/read.js +2 -1
  51. package/dist/connections/read.js.map +1 -1
  52. package/dist/connections/resourceId.d.ts +33 -0
  53. package/dist/connections/resourceId.d.ts.map +1 -1
  54. package/dist/connections/resourceId.js +88 -8
  55. package/dist/connections/resourceId.js.map +1 -1
  56. package/dist/connections/upsert.d.ts +219 -7
  57. package/dist/connections/upsert.d.ts.map +1 -1
  58. package/dist/connections/upsert.js +628 -41
  59. package/dist/connections/upsert.js.map +1 -1
  60. package/dist/connections/writers.js +2 -1
  61. package/dist/connections/writers.js.map +1 -1
  62. package/dist/descriptors/index.d.ts +5 -0
  63. package/dist/descriptors/index.d.ts.map +1 -1
  64. package/dist/descriptors/index.js +5 -0
  65. package/dist/descriptors/index.js.map +1 -1
  66. package/dist/descriptors/logSource.d.ts +9 -4
  67. package/dist/descriptors/logSource.d.ts.map +1 -1
  68. package/dist/descriptors/logSource.js +13 -6
  69. package/dist/descriptors/logSource.js.map +1 -1
  70. package/dist/jsonObject.d.ts +16 -0
  71. package/dist/jsonObject.d.ts.map +1 -0
  72. package/dist/jsonObject.js +18 -0
  73. package/dist/jsonObject.js.map +1 -0
  74. package/dist/keys/index.d.ts +13 -9
  75. package/dist/keys/index.d.ts.map +1 -1
  76. package/dist/keys/index.js +11 -7
  77. package/dist/keys/index.js.map +1 -1
  78. package/dist/keys/userKeyCascade.d.ts +46 -0
  79. package/dist/keys/userKeyCascade.d.ts.map +1 -1
  80. package/dist/keys/userKeyCascade.js +153 -65
  81. package/dist/keys/userKeyCascade.js.map +1 -1
  82. package/dist/keys/userKeyRoster.d.ts +60 -7
  83. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  84. package/dist/keys/userKeyRoster.js +165 -47
  85. package/dist/keys/userKeyRoster.js.map +1 -1
  86. package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
  87. package/dist/keys/userKeyRosterCascade.js +1 -0
  88. package/dist/keys/userKeyRosterCascade.js.map +1 -1
  89. package/dist/menders/ids.d.ts +1 -1
  90. package/dist/menders/ids.d.ts.map +1 -1
  91. package/dist/menders/ids.js +20 -4
  92. package/dist/menders/ids.js.map +1 -1
  93. package/dist/space/collections.d.ts +26 -6
  94. package/dist/space/collections.d.ts.map +1 -1
  95. package/dist/space/collections.js +31 -7
  96. package/dist/space/collections.js.map +1 -1
  97. package/dist/space/inboxMessage.d.ts +47 -0
  98. package/dist/space/inboxMessage.d.ts.map +1 -0
  99. package/dist/space/inboxMessage.js +86 -0
  100. package/dist/space/inboxMessage.js.map +1 -0
  101. package/dist/space/index.d.ts +7 -2
  102. package/dist/space/index.d.ts.map +1 -1
  103. package/dist/space/index.js +6 -2
  104. package/dist/space/index.js.map +1 -1
  105. package/dist/sync/contactsConflict.d.ts +23 -10
  106. package/dist/sync/contactsConflict.d.ts.map +1 -1
  107. package/dist/sync/contactsConflict.js +40 -21
  108. package/dist/sync/contactsConflict.js.map +1 -1
  109. package/dist/sync/index.d.ts +2 -2
  110. package/dist/sync/index.js +2 -2
  111. package/dist/webvh/didWebProjection.d.ts +38 -5
  112. package/dist/webvh/didWebProjection.d.ts.map +1 -1
  113. package/dist/webvh/didWebProjection.js +35 -22
  114. package/dist/webvh/didWebProjection.js.map +1 -1
  115. package/dist/webvh/index.d.ts +4 -3
  116. package/dist/webvh/index.d.ts.map +1 -1
  117. package/dist/webvh/index.js +4 -3
  118. package/dist/webvh/index.js.map +1 -1
  119. package/dist/webvh/standingZcap.d.ts +19 -2
  120. package/dist/webvh/standingZcap.d.ts.map +1 -1
  121. package/dist/webvh/standingZcap.js +31 -3
  122. package/dist/webvh/standingZcap.js.map +1 -1
  123. package/package.json +12 -6
package/README.md CHANGED
@@ -36,12 +36,14 @@ The subpaths:
36
36
 
37
37
  - **`@interop/wallet-core/space`** -- the wallet Space layout contract: the
38
38
  shared collection ids and descriptive specs (`private-credentials`,
39
- `public-credentials`, `wallet-activity`, `app-connections`), the
40
- `wallet-activity` wire shape with its pure `addHistory*` payload builders, the
39
+ `public-credentials`, `wallet-activity`, `app-keys`), the `wallet-activity`
40
+ wire shape with its pure `addHistory*` payload builders, the
41
41
  `publicCredentialUrl` derivation, and the `was-link` QR hand-off contract
42
42
  (`buildWasLinkPayload` / `parseWasLinkPayload` / `encodeWasLinkSecret`) with
43
- its structural recognizer, `isWasLinkPayload`. Contacts collection specs live
44
- in [`@interop/social-core`](https://npm.im/@interop/social-core).
43
+ its structural recognizer, `isWasLinkPayload`. It also carries the `inbox`
44
+ collection spec and the inbox message envelope (`inboxGrantMessage` /
45
+ `parseInboxGrantMessage`). Contacts collection specs live in
46
+ [`@interop/social-core`](https://npm.im/@interop/social-core).
45
47
 
46
48
  - **`@interop/wallet-core/webvh`** -- the account's did:webvh identity: the
47
49
  hosted DID log, its per-client update-key rotation, the client enrollment
@@ -85,16 +87,17 @@ The subpaths:
85
87
  the log-governed (and sealable) descriptor store those primitives drive, and
86
88
  the user key rotation cascade's per-collection op (re-epoch a collection onto
87
89
  the roster's current user key, staleness detected from durable state alone,
88
- history escrowed -- also the completion sweep's building block), plus the
89
- detector that converges a roster left wrapping the current key to a recipient
90
- the account document no longer keys. Also `ensureWalletSpaceEpochs`, the
91
- provision-time install of each encrypted wallet collection's key epoch[0] (a
92
- fresh random epoch key wrapped to the user key) -- the EDV-bearing second step
93
- of `provisionWalletSpace`. Also `walletSpaceProvisioner`, which builds the
94
- sync engine's `ensureProvisioned` closure over both steps, single-flight
95
- across concurrent callers. Also the client-key record codec: the contents and
96
- strict validation of the local record each wallet client keeps its own key
97
- material in (storage and wrapping stay app-side).
90
+ history escrowed -- also the completion sweep's building block). The decisions
91
+ behind that op and the roster convergence the login sweep runs are exported as
92
+ pure predicates, `userKeyRosterDrift` and `collectionEpochsCurrent`. Also
93
+ `ensureWalletSpaceEpochs`, the provision-time install of each encrypted wallet
94
+ collection's key epoch[0] (a fresh random epoch key wrapped to the user key)
95
+ -- the EDV-bearing second step of `provisionWalletSpace`. Also
96
+ `walletSpaceProvisioner`, which builds the sync engine's `ensureProvisioned`
97
+ closure over both steps, single-flight across concurrent callers. Also the
98
+ client-key record codec: the contents and strict validation of the local
99
+ record each wallet client keeps its own key material in (storage and wrapping
100
+ stay app-side).
98
101
 
99
102
  - **`@interop/wallet-core/clients`** -- the enrolled-client management surface:
100
103
  the listing over the locally verified did:webvh log with names joined from the
@@ -126,8 +129,21 @@ The subpaths:
126
129
  `removeGrants`, `retireConnection`, `unretireConnection`,
127
130
  `setConnectionLabel`); and the writer arm on a wallet client's entry (lazy
128
131
  registration, the throttled touch, the per-entry sweep, and the join a history
129
- view resolves a revision's `writerId` through). The wallet writes every entry;
130
- no party ever writes one.
132
+ view resolves a revision's `writerId` through). An agent's entry also carries
133
+ the wallet's side of the connection: the pairwise seed and its tag
134
+ (`connectionDidKey` derives the did:key), the grants the agent handed the
135
+ wallet, and the outbox of pending messages. Their readers (`receivedGrants`,
136
+ `liveInboxChannel`, `agentGrantDue`, ...) and writers (`recordReceivedGrants`,
137
+ `recordRenewedGrants`, `settleOutboxItem`, `pruneSupersededGrants`,
138
+ `clearReceivedGrants`, `markDeclined`) live here too. The wallet writes every
139
+ entry; no party ever writes one.
140
+
141
+ - **`@interop/wallet-core/audiences`** -- the audience collection: a plaintext
142
+ collection in the owner's Space whose posts are its Resources. It carries the
143
+ provisioning attributes every audience shares
144
+ (`AUDIENCE_PROVISION_ATTRIBUTES`) and the member grant
145
+ (`delegateAudienceGrant`, GET and HEAD on the container, with no key epoch to
146
+ escrow). Nothing marks an audience on the wire.
131
147
 
132
148
  - **`@interop/wallet-core/enrollment`** -- the client enrollment ceremony
133
149
  (connect code, approval, completion) plus the onboarding-response envelope
@@ -228,9 +244,9 @@ import {
228
244
 
229
245
  The `sync` and `space` subpaths are re-exported from the package root as well.
230
246
  Every other subpath (`webvh`, `resourceLog`, `keys`, `clients`, `descriptors`,
231
- `keyring`, `connections`, `enrollment`, `genesis`, `unlock`, `recovery`,
232
- `clientAnnex`, `menders`) is import-directly-only, so consumers of the root
233
- never pull the signing / KMS / document-loader dependency graph.
247
+ `keyring`, `connections`, `audiences`, `enrollment`, `genesis`, `unlock`,
248
+ `recovery`, `clientAnnex`, `menders`) is import-directly-only, so consumers of
249
+ the root never pull the signing / KMS / document-loader dependency graph.
234
250
 
235
251
  Nine further exports are leaves of that same isolation, carved out to stay
236
252
  dependency-light, for an offline consumer such as `@interop/wallet-backup` that
@@ -0,0 +1,49 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The audience collection and its member grant. An audience is a plaintext
6
+ * collection in the owner's Space whose posts are its Resources. Nothing
7
+ * marks a collection as an audience on the wire.
8
+ */
9
+ import type { IDelegatedZcap, IZcap } from '@interop/data-integrity-core';
10
+ import type { ZcapClient } from '@interop/ezcap';
11
+ /**
12
+ * The provisioning attributes every audience collection carries: it is
13
+ * plaintext, since its members read posts without a key epoch. The rest of
14
+ * the spec is the caller's. `isPublic` is the caller's choice (a public
15
+ * audience is one under world read), and the collection id follows the
16
+ * existing collection name grammar and is chosen by the caller.
17
+ */
18
+ export declare const AUDIENCE_PROVISION_ATTRIBUTES: {
19
+ readonly encryption: "plaintext";
20
+ };
21
+ /**
22
+ * Delegates an audience member's read grant over the audience collection.
23
+ * The shape is the read-only share grant a wallet mints for a collection
24
+ * reader: GET and HEAD on the collection's container. No key epoch is
25
+ * escrowed, since the audience is plaintext.
26
+ *
27
+ * The authorization profile is adding an explicit subtree marker (`*`
28
+ * appended to the target), and this mint site will write it once the
29
+ * profile and the server ship it. Until then the target is the bare
30
+ * container URL, which the current server reads as covering the subtree.
31
+ *
32
+ * @param options {object}
33
+ * @param options.zcapClient {ZcapClient} the delegating signer
34
+ * @param options.parentCapability {string | IZcap} the parent: a root zcap
35
+ * id string, or the embedded generation delegation
36
+ * @param options.collectionUrl {string} the collection's canonical
37
+ * container URL (trailing slash)
38
+ * @param options.controller {string} the member's DID
39
+ * @param options.expires {Date} the grant's expiry
40
+ * @returns {Promise<IDelegatedZcap>}
41
+ */
42
+ export declare function delegateAudienceGrant({ zcapClient, parentCapability, collectionUrl, controller, expires }: {
43
+ zcapClient: ZcapClient;
44
+ parentCapability: string | IZcap;
45
+ collectionUrl: string;
46
+ controller: string;
47
+ expires: Date;
48
+ }): Promise<IDelegatedZcap>;
49
+ //# sourceMappingURL=audienceGrant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audienceGrant.d.ts","sourceRoot":"","sources":["../../src/audiences/audienceGrant.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B;;CAEiB,CAAA;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,OAAO,EACR,EAAE;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,GAAG,KAAK,CAAA;IAChC,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,IAAI,CAAA;CACd,GAAG,OAAO,CAAC,cAAc,CAAC,CAe1B"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The provisioning attributes every audience collection carries: it is
3
+ * plaintext, since its members read posts without a key epoch. The rest of
4
+ * the spec is the caller's. `isPublic` is the caller's choice (a public
5
+ * audience is one under world read), and the collection id follows the
6
+ * existing collection name grammar and is chosen by the caller.
7
+ */
8
+ export const AUDIENCE_PROVISION_ATTRIBUTES = {
9
+ encryption: 'plaintext'
10
+ };
11
+ /**
12
+ * Delegates an audience member's read grant over the audience collection.
13
+ * The shape is the read-only share grant a wallet mints for a collection
14
+ * reader: GET and HEAD on the collection's container. No key epoch is
15
+ * escrowed, since the audience is plaintext.
16
+ *
17
+ * The authorization profile is adding an explicit subtree marker (`*`
18
+ * appended to the target), and this mint site will write it once the
19
+ * profile and the server ship it. Until then the target is the bare
20
+ * container URL, which the current server reads as covering the subtree.
21
+ *
22
+ * @param options {object}
23
+ * @param options.zcapClient {ZcapClient} the delegating signer
24
+ * @param options.parentCapability {string | IZcap} the parent: a root zcap
25
+ * id string, or the embedded generation delegation
26
+ * @param options.collectionUrl {string} the collection's canonical
27
+ * container URL (trailing slash)
28
+ * @param options.controller {string} the member's DID
29
+ * @param options.expires {Date} the grant's expiry
30
+ * @returns {Promise<IDelegatedZcap>}
31
+ */
32
+ export async function delegateAudienceGrant({ zcapClient, parentCapability, collectionUrl, controller, expires }) {
33
+ if (!collectionUrl.endsWith('/')) {
34
+ throw new TypeError('audience grant: `collectionUrl` must be the canonical container URL ' +
35
+ '(with a trailing slash).');
36
+ }
37
+ return (await zcapClient.delegate({
38
+ capability: parentCapability,
39
+ // Subtree marker: pending the profile change; flip this target to `${collectionUrl}*` when it ships.
40
+ invocationTarget: collectionUrl,
41
+ controller,
42
+ allowedActions: ['GET', 'HEAD'],
43
+ expires
44
+ }));
45
+ }
46
+ //# sourceMappingURL=audienceGrant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audienceGrant.js","sourceRoot":"","sources":["../../src/audiences/audienceGrant.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,UAAU,EAAE,WAAW;CACkC,CAAA;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,OAAO,EAOR;IACC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CACjB,sEAAsE;YACpE,0BAA0B,CAC7B,CAAA;IACH,CAAC;IACD,OAAO,CAAC,MAAM,UAAU,CAAC,QAAQ,CAAC;QAChC,UAAU,EAAE,gBAAgB;QAC5B,qGAAqG;QACrG,gBAAgB,EAAE,aAAa;QAC/B,UAAU;QACV,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;QAC/B,OAAO;KACR,CAAC,CAAmB,CAAA;AACvB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/audiences` subpath: the audience collection's
6
+ * provisioning attributes and the member grant helper. The agent's own grants
7
+ * do not go through it. They arrive through a connection request.
8
+ */
9
+ export { AUDIENCE_PROVISION_ATTRIBUTES, delegateAudienceGrant } from './audienceGrant.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audiences/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,EACtB,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/audiences` subpath: the audience collection's
6
+ * provisioning attributes and the member grant helper. The agent's own grants
7
+ * do not go through it. They arrive through a connection request.
8
+ */
9
+ export { AUDIENCE_PROVISION_ATTRIBUTES, delegateAudienceGrant } from './audienceGrant.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audiences/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,EACtB,MAAM,oBAAoB,CAAA"}
@@ -29,8 +29,37 @@
29
29
  * delegation blind, reading was-client's genuine `AlreadyRevokedError` as
30
30
  * success and an already-expired delegation as needing no POST at all;
31
31
  * write the digest; delete), so a GC torn anywhere resumes at the next
32
- * login instead of waiting a quarter. Failures are collected per generation
33
- * and never abort the fan-out: a partial pass is a resumable success.
32
+ * login instead of waiting a quarter. The pointer it compares against is
33
+ * re-read from the account log under this client's pin right before the
34
+ * fan-out, and a generation that log never pointed at is collected only
35
+ * once it is GC-quiet (the same quiet bound the swap defers on), so a
36
+ * sibling client's swap -- landed, or still between its mint and its
37
+ * re-point -- never loses the generation the account points at. A
38
+ * generation the log once pointed at is collected at once: it cannot be a
39
+ * sibling's unpointed fresh generation, and a retire swap's refused revoke
40
+ * is retried on it without waiting a day. Failures are collected per
41
+ * generation and never abort the fan-out: a partial pass is a resumable
42
+ * success. The re-read itself and the collection listing sit outside that
43
+ * isolation: either failing rejects the pass, since there is nothing safe
44
+ * to collect against.
45
+ *
46
+ * - The REPAIR is the swap off its cadence: when the pointed generation's
47
+ * log does not exist (the pointer names a generation a stale pass
48
+ * collected, or one never minted), every transient visit is shut out until
49
+ * the pointer moves, so the pass mints a fresh generation and re-points at
50
+ * once, with nothing to revoke. The pointed log is read on every pass for
51
+ * this reason. The repair covers a dead generation inside a live Space
52
+ * only: when the auxiliary Space itself is gone, or its metadata read
53
+ * answers anything but 2xx, it refuses (`failed`), and the transient
54
+ * readiness ensure, whose two-probe rule tells a gone Space from a masked
55
+ * read, is the one that replaces a Space.
56
+ *
57
+ * Both the swap and the repair decide on the account log re-read under this
58
+ * client's pin at the start of the pass, not on the caller's view, and
59
+ * their re-point lands only while the account still points at the
60
+ * generation they replace. A sibling client's swap that landed since the
61
+ * caller's read, or while this pass minted, stands, and the pass reports
62
+ * `not-due`.
34
63
  *
35
64
  * The completion predicate is durable state alone (exactly one `gen-`
36
65
  * collection exists in the auxiliary Space and it is the one the pointer
@@ -114,14 +143,17 @@ export declare function clientAnnexGcDue({ log, now }: {
114
143
  /**
115
144
  * The live-entry guard: whether a generation is GC-quiet -- its newest
116
145
  * entry's `versionTime` is older than the quiet bound plus the skew grace
117
- * margin. Applies to the POINTED generation only (an unpointed generation
118
- * authorizes nothing under pointer equality, so nothing inside it ever
119
- * defers deletion). An unparseable `versionTime` reads as not quiet: the
120
- * swap defers rather than abandoning a possibly-live visit.
146
+ * margin. On the POINTED generation it defers the swap, so a possibly-live
147
+ * visit is not abandoned. On an unpointed generation the account log NEVER
148
+ * pointed at it defers the collect: such a generation authorizes nothing
149
+ * under pointer equality, but one written moments ago may be a sibling
150
+ * client's fresh generation whose re-point has not landed yet, and collecting
151
+ * it would leave the account pointing at a deleted generation. An
152
+ * unparseable `versionTime` reads as not quiet, so both arms defer rather
153
+ * than act.
121
154
  *
122
155
  * @param options {object}
123
- * @param options.log {DIDLog} the pointed generation's VERIFIED annex
124
- * log
156
+ * @param options.log {DIDLog} the generation's VERIFIED annex log
125
157
  * @param [options.now] {number} epoch milliseconds, for tests
126
158
  * @returns {boolean}
127
159
  */
@@ -130,27 +162,38 @@ export declare function generationQuiet({ log, now }: {
130
162
  now?: number;
131
163
  }): boolean;
132
164
  /**
133
- * What the swap half of one GC pass did. `replaced` is the successful swap;
134
- * `not-due` and `deferred-live` are the two healthy skips (cadence and quiet
135
- * bound); `no-pointer` means the account has no annex inventory (the whole
136
- * pass no-ops -- without a pointer there is no auxiliary Space to list);
137
- * `no-ladder-seed` means the swap was due but the login held no ladder seed
138
- * to mint with (a non-standing record); `failed` means a swap stage threw --
139
- * reported in `failed` under the pointed generation's id, with the collect
140
- * fan-out still run.
165
+ * What the swap half of one GC pass did. `replaced` is the successful
166
+ * quarterly swap; `repaired` is the off-cadence swap the pass runs when the
167
+ * pointed generation's log does not exist (the account was left pointing at
168
+ * a collected or never-minted generation, and no transient visit could
169
+ * enroll), so the pointer names a live generation again; `not-due` and
170
+ * `deferred-live` are the two healthy skips (cadence and quiet bound), and
171
+ * `not-due` also covers a caller's dead pointer the account log has since
172
+ * moved off; `no-pointer` means the account has no annex inventory (the
173
+ * whole pass no-ops -- without a pointer there is no auxiliary Space to
174
+ * list), or that the re-read ahead of a repair found the pointer removed;
175
+ * `no-ladder-seed` means a swap was due, or a repair needed, but the login
176
+ * held no ladder seed to mint with (a non-standing record); `failed` means
177
+ * the pointed generation's read or a swap stage threw -- reported in
178
+ * `failed` under the pointed generation's id, with the collect fan-out
179
+ * still run.
141
180
  */
142
- export type ClientAnnexGcSwapOutcome = 'replaced' | 'not-due' | 'deferred-live' | 'no-pointer' | 'no-ladder-seed' | 'failed';
181
+ export type ClientAnnexGcSwapOutcome = 'replaced' | 'repaired' | 'not-due' | 'deferred-live' | 'no-pointer' | 'no-ladder-seed' | 'failed';
143
182
  /**
144
- * One GC pass's report: the swap outcome, the annex DID the account
145
- * points at after the pass, the generation ids collected (revoked, digested,
146
- * deleted), and the per-generation failures. A report with `failed` entries
147
- * is a resumable success -- the next remembered login's pass picks up exactly
148
- * the generations still listed.
183
+ * One GC pass's report: the swap outcome, the annex DID the account points
184
+ * at after the pass (read back from the account log under this client's
185
+ * pin, so it is what the host serves and not what this pass believes), the
186
+ * generation ids collected (revoked, digested, deleted), the ids deferred
187
+ * (unpointed but not yet GC-quiet, kept for a later pass), and the
188
+ * per-generation failures. A report with `failed` or `deferred` entries is a
189
+ * resumable success -- the next remembered login's pass picks up exactly the
190
+ * generations still listed.
149
191
  */
150
192
  export interface ClientAnnexGcReport {
151
193
  swap: ClientAnnexGcSwapOutcome;
152
194
  pointedDid?: string;
153
195
  collected: string[];
196
+ deferred: string[];
154
197
  failed: Array<{
155
198
  generationId: string;
156
199
  error: unknown;
@@ -202,7 +245,38 @@ export interface ClientAnnexGenerationSwap {
202
245
  * a chain whose signer has left the document is read as that), re-writes
203
246
  * the digest (the deterministic payload id collapses the second row at read
204
247
  * time), and re-runs the idempotent delete; a swap torn before its re-point
205
- * leaves an unpointed fresh generation the same fan-out collects.
248
+ * leaves an unpointed fresh generation the same fan-out collects once it is
249
+ * GC-quiet.
250
+ *
251
+ * Two guards keep the fan-out off the pointed generation. The pointer the
252
+ * fan-out compares against is re-read from the account log under this
253
+ * client's pin immediately before the fan-out, so a sibling client's swap,
254
+ * or this pass's own re-point whose response was lost, is seen rather than
255
+ * the caller's pre-pass view. And an unpointed generation the fresh log
256
+ * never pointed at is collected only when GC-quiet, so a sibling mid-swap
257
+ * (minted, not yet pointed) keeps its fresh generation; one the log once
258
+ * pointed at is collected at once. A generation whose log does not exist
259
+ * carries no timestamp and is deleted at once. A sibling whose genesis and
260
+ * install both land in the gap between that read and the delete goes on to
261
+ * re-point at the deleted generation; the next remembered login's repair,
262
+ * or the next transient visit's readiness ensure, mends that.
263
+ *
264
+ * The pointed generation's log is read on every pass: when the swap is due
265
+ * it is the quiet gate, and on every pass it is the detector of a dead
266
+ * pointed generation (a collected or never-minted one the pointer still
267
+ * names), which the pass repairs with an off-cadence swap so the next
268
+ * transient visit can enroll. Before the repair the account log is re-read
269
+ * under this client's pin: when the pointer has moved off the one the caller
270
+ * passed, a sibling client swapped since the caller's read, and the pass
271
+ * reports `not-due` and repairs nothing (`no-pointer` when the re-read
272
+ * document carries none). The repair's own re-point is conditional on the
273
+ * same pointer, so a sibling's re-point landing while the repair mints also
274
+ * stands, and the pass reports `not-due`. The repair then confirms the
275
+ * auxiliary Space
276
+ * itself still answers, and refuses when it does not: replacing a gone Space
277
+ * is the transient readiness ensure's, whose two-probe rule tells absence
278
+ * from a masked read, and a repair racing it across two Spaces would strand
279
+ * whichever Space lost the re-point.
206
280
  *
207
281
  * @param options {object}
208
282
  * @param options.was {WasClient} the storage client, signing as an
@@ -219,8 +293,8 @@ export interface ClientAnnexGenerationSwap {
219
293
  * @param options.zcapClient {ZcapClient} signs the fresh generation
220
294
  * delegation (the promoted account keyId)
221
295
  * @param [options.ladderSeed] {Uint8Array} the login credential's ladder
222
- * seed; absent, a due swap reports `no-ladder-seed` and only the collect
223
- * fan-out runs
296
+ * seed; absent, a due swap or a needed repair reports `no-ladder-seed` and
297
+ * only the collect fan-out runs
224
298
  * @param options.recordDigest {Function}
225
299
  * `({ generationId, firstEntry, lastEntry, entryCount }) => Promise<void>`
226
300
  * -- writes the GenerationCollect wallet-activity row; called before the
@@ -277,6 +351,12 @@ export declare function runClientAnnexGc({ was, wasServerUrl, accountSpaceId, ac
277
351
  * refuses that chain, and the revoke stage reads the refusal against the
278
352
  * caller's `account.doc` and reports `signer-gone`.
279
353
  *
354
+ * The re-point lands only while the account log, re-read under this
355
+ * client's pin before the mint, still points at the generation the caller's
356
+ * `account.doc` names. A sibling's re-point that lands first stands, and the
357
+ * swap throws rather than move the account off it; the caller re-runs its
358
+ * ceremony over a fresh read.
359
+ *
280
360
  * @param options {object} see {@link runClientAnnexGc} for the shared
281
361
  * members ({ was, wasServerUrl, accountSpaceId, account, idStore,
282
362
  * updateKeys, zcapClient }); `ladderSeed` here is the SURVIVING
@@ -284,6 +364,8 @@ export declare function runClientAnnexGc({ was, wasServerUrl, accountSpaceId, ac
284
364
  * @param [options.now] {number} epoch milliseconds, for tests
285
365
  * @returns {Promise<ClientAnnexGenerationSwap>} the fresh annex DID and
286
366
  * what the revoke stage did
367
+ * @throws {Error} `DelegatedClientsPointerMovedError` when the account log
368
+ * no longer points at the generation `account.doc` names
287
369
  */
288
370
  export declare function swapClientAnnexGeneration({ was, wasServerUrl, accountSpaceId, account, idStore, signer, zcapClient, ladderSeed, now }: {
289
371
  was: WasClient;
@@ -1 +1 @@
1
- {"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/gc.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAepD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACb,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAEvE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAA2B,CAAA;AAE/D;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,QAAsB,CAAA;AAE5D;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,QAAiB,CAAA;AAEvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oCAAoC,CAAC,EACnD,GAAG,EACJ,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,MAAM,GAAG,SAAS,CAgBrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,GAAgB,EACjB,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAUV;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,GAAgB,EACjB,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAUV;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GAChC,UAAU,GACV,SAAS,GACT,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,QAAQ,CAAA;AAEZ;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,wBAAwB,CAAA;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,4BAA4B,CAAA;IACpC,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,GAAG,EACH,YAAY,EACZ,cAAc,EACd,OAAO,EACP,OAAO,EACP,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,WAAW,EACX,GAAgB,EACjB,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAA;IACvD,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,qBAAqB,CAAA;IACjC,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,EAAE,CAAC,MAAM,EAAE;QACrB,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8G/B;AAuLD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,GAAG,EACH,YAAY,EACZ,cAAc,EACd,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,UAAU,EACV,GAAgB,EACjB,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,KAAK,CAAC,CAAA;IAC/C,OAAO,EAAE,YAAY,CAAA;IACrB,MAAM,EAAE,gBAAgB,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA6BrC"}
1
+ {"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/gc.ts"],"names":[],"mappings":"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"}