@interop/wallet-core 0.68.0 → 0.69.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 (124) hide show
  1. package/README.md +14 -13
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +12 -1
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +9 -2
  5. package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
  6. package/dist/clientAnnex/establish.d.ts +10 -0
  7. package/dist/clientAnnex/establish.d.ts.map +1 -1
  8. package/dist/clientAnnex/establish.js +14 -2
  9. package/dist/clientAnnex/establish.js.map +1 -1
  10. package/dist/clientAnnex/mend.d.ts +19 -4
  11. package/dist/clientAnnex/mend.d.ts.map +1 -1
  12. package/dist/clientAnnex/mend.js +83 -35
  13. package/dist/clientAnnex/mend.js.map +1 -1
  14. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +13 -14
  15. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
  16. package/dist/clientAnnex/rosterDeliveredEpochs.js +12 -12
  17. package/dist/clientAnnex/rosterDeliveredEpochs.js.map +1 -1
  18. package/dist/descriptors/index.d.ts +21 -46
  19. package/dist/descriptors/index.d.ts.map +1 -1
  20. package/dist/descriptors/index.js +21 -45
  21. package/dist/descriptors/index.js.map +1 -1
  22. package/dist/descriptors/logSource.d.ts +45 -56
  23. package/dist/descriptors/logSource.d.ts.map +1 -1
  24. package/dist/descriptors/logSource.js +64 -74
  25. package/dist/descriptors/logSource.js.map +1 -1
  26. package/dist/genesis/accountGenesis.d.ts +13 -1
  27. package/dist/genesis/accountGenesis.d.ts.map +1 -1
  28. package/dist/genesis/accountGenesis.js +11 -2
  29. package/dist/genesis/accountGenesis.js.map +1 -1
  30. package/dist/keys/collectionLogStore.d.ts +73 -0
  31. package/dist/keys/collectionLogStore.d.ts.map +1 -0
  32. package/dist/keys/collectionLogStore.js +60 -0
  33. package/dist/keys/collectionLogStore.js.map +1 -0
  34. package/dist/keys/index.d.ts +18 -6
  35. package/dist/keys/index.d.ts.map +1 -1
  36. package/dist/keys/index.js +18 -6
  37. package/dist/keys/index.js.map +1 -1
  38. package/dist/keys/rosterLogStore.d.ts +44 -6
  39. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  40. package/dist/keys/rosterLogStore.js +51 -238
  41. package/dist/keys/rosterLogStore.js.map +1 -1
  42. package/dist/keys/rosterStore.d.ts.map +1 -1
  43. package/dist/keys/rosterStore.js +2 -1
  44. package/dist/keys/rosterStore.js.map +1 -1
  45. package/dist/keys/spaceEpochs.d.ts +67 -34
  46. package/dist/keys/spaceEpochs.d.ts.map +1 -1
  47. package/dist/keys/spaceEpochs.js +80 -30
  48. package/dist/keys/spaceEpochs.js.map +1 -1
  49. package/dist/keys/userKeyCascade.d.ts +26 -1
  50. package/dist/keys/userKeyCascade.d.ts.map +1 -1
  51. package/dist/keys/userKeyCascade.js +29 -2
  52. package/dist/keys/userKeyCascade.js.map +1 -1
  53. package/dist/keys/userKeyRoster.d.ts +5 -0
  54. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  55. package/dist/keys/userKeyRoster.js +5 -0
  56. package/dist/keys/userKeyRoster.js.map +1 -1
  57. package/dist/keys/userKeyRosterCascade.d.ts +54 -16
  58. package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
  59. package/dist/keys/userKeyRosterCascade.js +50 -22
  60. package/dist/keys/userKeyRosterCascade.js.map +1 -1
  61. package/dist/resourceLog/controller.d.ts +18 -6
  62. package/dist/resourceLog/controller.d.ts.map +1 -1
  63. package/dist/resourceLog/controller.js +5 -3
  64. package/dist/resourceLog/controller.js.map +1 -1
  65. package/dist/resourceLog/errors.d.ts +17 -43
  66. package/dist/resourceLog/errors.d.ts.map +1 -1
  67. package/dist/resourceLog/errors.js +17 -50
  68. package/dist/resourceLog/errors.js.map +1 -1
  69. package/dist/resourceLog/index.d.ts +4 -1
  70. package/dist/resourceLog/index.d.ts.map +1 -1
  71. package/dist/resourceLog/index.js +4 -1
  72. package/dist/resourceLog/index.js.map +1 -1
  73. package/dist/resourceLog/logClass.d.ts +69 -0
  74. package/dist/resourceLog/logClass.d.ts.map +1 -0
  75. package/dist/resourceLog/logClass.js +43 -0
  76. package/dist/resourceLog/logClass.js.map +1 -0
  77. package/dist/space/collections.d.ts +22 -2
  78. package/dist/space/collections.d.ts.map +1 -1
  79. package/dist/space/collections.js +18 -0
  80. package/dist/space/collections.js.map +1 -1
  81. package/dist/space/index.d.ts +4 -3
  82. package/dist/space/index.d.ts.map +1 -1
  83. package/dist/space/index.js +4 -3
  84. package/dist/space/index.js.map +1 -1
  85. package/dist/space/provisioning.d.ts +16 -6
  86. package/dist/space/provisioning.d.ts.map +1 -1
  87. package/dist/space/provisioning.js +11 -7
  88. package/dist/space/provisioning.js.map +1 -1
  89. package/dist/sync/engine.d.ts +4 -2
  90. package/dist/sync/engine.d.ts.map +1 -1
  91. package/dist/sync/engine.js.map +1 -1
  92. package/dist/sync/index.d.ts +9 -6
  93. package/dist/sync/index.d.ts.map +1 -1
  94. package/dist/sync/index.js +8 -5
  95. package/dist/sync/index.js.map +1 -1
  96. package/dist/sync/push.d.ts +0 -29
  97. package/dist/sync/push.d.ts.map +1 -1
  98. package/dist/sync/push.js +30 -28
  99. package/dist/sync/push.js.map +1 -1
  100. package/dist/sync/types.d.ts +39 -21
  101. package/dist/sync/types.d.ts.map +1 -1
  102. package/dist/sync/types.js +13 -7
  103. package/dist/sync/types.js.map +1 -1
  104. package/dist/unlock/retire.d.ts +8 -1
  105. package/dist/unlock/retire.d.ts.map +1 -1
  106. package/dist/unlock/retire.js +8 -1
  107. package/dist/unlock/retire.js.map +1 -1
  108. package/package.json +4 -4
  109. package/dist/descriptors/acquire.d.ts +0 -122
  110. package/dist/descriptors/acquire.d.ts.map +0 -1
  111. package/dist/descriptors/acquire.js +0 -100
  112. package/dist/descriptors/acquire.js.map +0 -1
  113. package/dist/descriptors/cipher.d.ts +0 -71
  114. package/dist/descriptors/cipher.d.ts.map +0 -1
  115. package/dist/descriptors/cipher.js +0 -109
  116. package/dist/descriptors/cipher.js.map +0 -1
  117. package/dist/descriptors/errors.d.ts +0 -44
  118. package/dist/descriptors/errors.d.ts.map +0 -1
  119. package/dist/descriptors/errors.js +0 -46
  120. package/dist/descriptors/errors.js.map +0 -1
  121. package/dist/descriptors/refresh.d.ts +0 -62
  122. package/dist/descriptors/refresh.d.ts.map +0 -1
  123. package/dist/descriptors/refresh.js +0 -69
  124. package/dist/descriptors/refresh.js.map +0 -1
@@ -1,100 +0,0 @@
1
- import { isResourceLogRefusal } from '../resourceLog/errors.js';
2
- /**
3
- * The {@link EncryptionDescriptorSource} over a was-client handle: reads the
4
- * collection's Description in the given Space and returns its `encryption`
5
- * descriptor.
6
- *
7
- * @param options {object}
8
- * @param options.was {WasClient} a client whose signer can read the Space
9
- * @param options.spaceId {string}
10
- * @returns {EncryptionDescriptorSource}
11
- */
12
- export function wasDescriptorSource({ was, spaceId }) {
13
- return {
14
- async collectionEncryption({ collectionId }) {
15
- const description = await was
16
- .space(spaceId)
17
- .collection(collectionId)
18
- .describe();
19
- return description?.encryption ?? undefined;
20
- }
21
- };
22
- }
23
- /**
24
- * Acquires one collection's descriptor: fetches it from the source, caching a
25
- * success; falls back to the cached copy whenever the fetch yields no
26
- * descriptor (it threw, or it came back empty -- a masked 404 for an
27
- * unauthorized read looks exactly like an unencrypted collection); and with no
28
- * source at all (a purely local code path) reads the cache alone. Any cached
29
- * copy is deliberately left in place, never cleared by an empty fetch.
30
- * `undefined` means no descriptor exists anywhere for this collection.
31
- *
32
- * @param options {object}
33
- * @param [options.source] {EncryptionDescriptorSource} omit for cache-only
34
- * acquisition
35
- * @param options.cache {EncryptionDescriptorCache}
36
- * @param options.collectionId {string}
37
- * @param [options.onFetchError] {function} observes a swallowed fetch
38
- * failure (the thrown-fetch branch only; an empty description is not an
39
- * error). Errors from the cache itself throw through, as do a log-governed
40
- * source's refusal classes (a fabricated or discontinuous log is a security
41
- * signal, not an outage the cache should paper over) -- except a continuity
42
- * `rollback`, which falls back to the cache like any transport hiccup
43
- * @returns {Promise<CollectionEncryption | undefined>}
44
- */
45
- export async function acquireDescriptor({ source, cache, collectionId, onFetchError }) {
46
- if (!source) {
47
- return cache.readDescriptor({ collectionId });
48
- }
49
- try {
50
- const fetched = await source.collectionEncryption({ collectionId });
51
- if (fetched) {
52
- await cache.writeDescriptor({ collectionId, descriptor: fetched });
53
- return fetched;
54
- }
55
- // Empty description: not authoritative (an unauthorized read is masked as
56
- // an absent one), so a warm cache still serves the collection.
57
- return cache.readDescriptor({ collectionId });
58
- }
59
- catch (err) {
60
- // A resource-log refusal the cache must not paper over -- a fabricated
61
- // log, or one that is not the continuation of the pinned history. A
62
- // rollback is not one of them and falls through to the cache, as any
63
- // transport failure does.
64
- if (isResourceLogRefusal(err)) {
65
- throw err;
66
- }
67
- onFetchError?.(err, { collectionId });
68
- return cache.readDescriptor({ collectionId });
69
- }
70
- }
71
- /**
72
- * Acquires descriptors for a set of collections concurrently (each fetch is an
73
- * independent signed round trip, so a session start is not gated on a serial
74
- * chain of describes). Collections that resolve no descriptor are simply
75
- * absent from the result.
76
- *
77
- * @param options {object}
78
- * @param [options.source] {EncryptionDescriptorSource} omit for cache-only
79
- * acquisition
80
- * @param options.cache {EncryptionDescriptorCache}
81
- * @param options.collectionIds {string[]}
82
- * @param [options.onFetchError] {function} observes each swallowed fetch
83
- * failure
84
- * @returns {Promise<Record<string, CollectionEncryption>>} keyed by
85
- * collection id
86
- */
87
- export async function acquireDescriptors({ source, cache, collectionIds, onFetchError }) {
88
- const resolved = await Promise.all(collectionIds.map(async (collectionId) => [
89
- collectionId,
90
- await acquireDescriptor({ source, cache, collectionId, onFetchError })
91
- ]));
92
- const descriptors = {};
93
- for (const [collectionId, descriptor] of resolved) {
94
- if (descriptor) {
95
- descriptors[collectionId] = descriptor;
96
- }
97
- }
98
- return descriptors;
99
- }
100
- //# sourceMappingURL=acquire.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"acquire.js","sourceRoot":"","sources":["../../src/descriptors/acquire.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AA+B/D;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,GAAG,EACH,OAAO,EAIR;IACC,OAAO;QACL,KAAK,CAAC,oBAAoB,CAAC,EAAE,YAAY,EAAE;YACzC,MAAM,WAAW,GAAG,MAAM,GAAG;iBAC1B,KAAK,CAAC,OAAO,CAAC;iBACd,UAAU,CAAC,YAAY,CAAC;iBACxB,QAAQ,EAAE,CAAA;YACb,OAAO,WAAW,EAAE,UAAU,IAAI,SAAS,CAAA;QAC7C,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,MAAM,EACN,KAAK,EACL,YAAY,EACZ,YAAY,EAMb;IACC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;IAC/C,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;QACnE,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,KAAK,CAAC,eAAe,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAA;YAClE,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,0EAA0E;QAC1E,+DAA+D;QAC/D,OAAO,KAAK,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uEAAuE;QACvE,oEAAoE;QACpE,qEAAqE;QACrE,0BAA0B;QAC1B,IAAI,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,CAAA;QACX,CAAC;QACD,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,MAAM,EACN,KAAK,EACL,aAAa,EACb,YAAY,EAMb;IACC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,aAAa,CAAC,GAAG,CACf,KAAK,EAAC,YAAY,EAAC,EAAE,CACnB;QACE,YAAY;QACZ,MAAM,iBAAiB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;KAC9D,CACb,CACF,CAAA;IACD,MAAM,WAAW,GAAyC,EAAE,CAAA;IAC5D,KAAK,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,QAAQ,EAAE,CAAC;QAClD,IAAI,UAAU,EAAE,CAAC;YACf,WAAW,CAAC,YAAY,CAAC,GAAG,UAAU,CAAA;QACxC,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC"}
@@ -1,71 +0,0 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
- /**
5
- * A self-refreshing EDV document cipher: `createEdvDocCipher` bound to
6
- * descriptor acquisition and the once-per-session refresh rule, for a host
7
- * whose decrypt seam is the cipher itself (a sync engine's `decryptDoc`, a
8
- * conflict resolver) rather than a row-scanning store.
9
- *
10
- * Built, the cipher acquires the collection's descriptor (fetch, cache the
11
- * success, cached fallback whenever the fetch yields none -- see
12
- * `acquire.ts`) and constructs the
13
- * underlying EDV cipher from it; with no descriptor, or a descriptor with no
14
- * epochs, the build refuses fail-closed (every encrypted collection's
15
- * descriptor carries an epoch roster from provisioning, so the absence can
16
- * only mean the install has not landed or the host is lying). When a decrypt
17
- * throws
18
- * `UnknownEpochError`, the cipher re-acquires the descriptor, rebuilds itself,
19
- * and retries that decrypt exactly once -- and only once per cipher instance,
20
- * which the host scopes to one `(profile, collection)` session by dropping
21
- * its cipher cache when the session ends. A second failure (or any unknown
22
- * epoch after the one refresh is spent) propagates. A refresh that itself
23
- * fails does not count as spent -- the original `UnknownEpochError` is
24
- * rethrown and a later decrypt may try again.
25
- *
26
- * Only `UnknownEpochError` drives that refresh, and by design. The client
27
- * splits the two ways a decrypt can find no key: an epoch the descriptor does
28
- * not list at all raises `UnknownEpochError`, because a fresher descriptor may
29
- * well list it; an epoch the descriptor does list but this reader holds no key
30
- * for raises `KeyUnwrapError` (never a recipient, or removed and the epoch
31
- * rotated). The second is rethrown immediately, with the refresh left
32
- * untouched, since re-reading the same descriptor cannot produce a key the
33
- * reader was not given.
34
- */
35
- import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
36
- import { type DocCipher } from '@interop/was-client/edv';
37
- import { type EncryptionDescriptorCache, type EncryptionDescriptorSource } from './acquire.js';
38
- /**
39
- * Builds a {@link DocCipher} whose descriptor is acquired through the
40
- * source/cache seams and refreshed (once per instance) on an unknown-epoch
41
- * decrypt.
42
- *
43
- * With no `source` the descriptor is served from the cache alone and the
44
- * refresh path is inert (an unknown-epoch decrypt propagates immediately) --
45
- * the shape for a purely local code path that must never touch the network.
46
- *
47
- * @param options {object}
48
- * @param options.keyAgreementKey {IKeyAgreementKey} the vault key pair this
49
- * collection's envelopes are sealed to
50
- * @param options.keyResolver {IKeyResolver}
51
- * @param options.collectionId {string}
52
- * @param [options.idDerivation] {'content' | 'random'} defaults to
53
- * `'content'`
54
- * @param [options.source] {EncryptionDescriptorSource}
55
- * @param options.cache {EncryptionDescriptorCache}
56
- * @param [options.onFetchError] {function} observes swallowed
57
- * descriptor-fetch failures
58
- * @returns {Promise<DocCipher>}
59
- */
60
- export declare function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolver, collectionId, idDerivation, source, cache, onFetchError }: {
61
- keyAgreementKey: IKeyAgreementKey;
62
- keyResolver: IKeyResolver;
63
- collectionId: string;
64
- idDerivation?: 'content' | 'random';
65
- source?: EncryptionDescriptorSource;
66
- cache: EncryptionDescriptorCache;
67
- onFetchError?: (err: unknown, info: {
68
- collectionId: string;
69
- }) => void;
70
- }): Promise<DocCipher>;
71
- //# sourceMappingURL=cipher.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cipher.d.ts","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,cAAc,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EACb,EAAE;IACD,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACnC,MAAM,CAAC,EAAE,0BAA0B,CAAA;IACnC,KAAK,EAAE,yBAAyB,CAAA;IAChC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,GAAG,OAAO,CAAC,SAAS,CAAC,CAyFrB"}
@@ -1,109 +0,0 @@
1
- import { createEdvDocCipher, UnknownEpochError } from '@interop/was-client/edv';
2
- import { acquireDescriptor } from './acquire.js';
3
- /**
4
- * Builds a {@link DocCipher} whose descriptor is acquired through the
5
- * source/cache seams and refreshed (once per instance) on an unknown-epoch
6
- * decrypt.
7
- *
8
- * With no `source` the descriptor is served from the cache alone and the
9
- * refresh path is inert (an unknown-epoch decrypt propagates immediately) --
10
- * the shape for a purely local code path that must never touch the network.
11
- *
12
- * @param options {object}
13
- * @param options.keyAgreementKey {IKeyAgreementKey} the vault key pair this
14
- * collection's envelopes are sealed to
15
- * @param options.keyResolver {IKeyResolver}
16
- * @param options.collectionId {string}
17
- * @param [options.idDerivation] {'content' | 'random'} defaults to
18
- * `'content'`
19
- * @param [options.source] {EncryptionDescriptorSource}
20
- * @param options.cache {EncryptionDescriptorCache}
21
- * @param [options.onFetchError] {function} observes swallowed
22
- * descriptor-fetch failures
23
- * @returns {Promise<DocCipher>}
24
- */
25
- export async function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolver, collectionId, idDerivation, source, cache, onFetchError }) {
26
- const build = async () => {
27
- const encryption = await acquireDescriptor({
28
- source,
29
- cache,
30
- collectionId,
31
- onFetchError
32
- });
33
- if (!encryption) {
34
- throw new Error(`Collection "${collectionId}" has no encryption descriptor available ` +
35
- '(fetched or cached). Every encrypted collection carries its key ' +
36
- 'epochs from provisioning; refusing to build a cipher without them.');
37
- }
38
- return createEdvDocCipher({
39
- keyAgreementKey,
40
- keyResolver,
41
- collectionId,
42
- idDerivation,
43
- encryption
44
- });
45
- };
46
- let inner = await build();
47
- // The one descriptor refresh this cipher instance (= this collection this
48
- // session) may spend, shared so concurrent unknown-epoch decrypts ride a
49
- // single re-read instead of each spending one.
50
- let refreshed = null;
51
- return {
52
- encrypt: options => inner.encrypt(options),
53
- encryptUpdate: options => {
54
- if (!inner.encryptUpdate) {
55
- throw new Error(`Collection "${collectionId}" cipher has no in-place update.`);
56
- }
57
- return inner.encryptUpdate(options);
58
- },
59
- async decrypt({ envelope }) {
60
- try {
61
- return await inner.decrypt({ envelope });
62
- }
63
- catch (err) {
64
- // `instanceof` is safe here and only here: `inner` is built in this
65
- // file by `createEdvDocCipher`, from the same `@interop/was-client`
66
- // import this class comes from, so no injected seam is crossed. A
67
- // caller classifying what THIS cipher throws is crossing one, and uses
68
- // `isUnknownEpochError` / `isKeyUnwrapError` instead.
69
- if (!(err instanceof UnknownEpochError) || !source) {
70
- throw err;
71
- }
72
- if (!refreshed) {
73
- const attempt = build().then(cipher => {
74
- inner = cipher;
75
- });
76
- refreshed = attempt;
77
- // Only a COMPLETED refresh is spent. A rejected one (the description
78
- // could not be read and no cached copy answered either) un-arms the
79
- // guard so a later unknown-epoch decrypt may try again; a successful
80
- // refresh that still cannot route the envelope stays spent for the
81
- // session, which is what keeps a genuinely foreign envelope from
82
- // driving a refetch loop.
83
- attempt.catch(() => {
84
- if (refreshed === attempt) {
85
- refreshed = null;
86
- }
87
- });
88
- }
89
- try {
90
- await refreshed;
91
- }
92
- catch {
93
- // The refresh failed, so nothing was learned about this envelope's
94
- // epoch: surface the original UnknownEpochError rather than the
95
- // build failure, so callers classifying on it (the create-loss
96
- // re-mint) still see the row they exist to repair.
97
- throw err;
98
- }
99
- // One retry under the swapped cipher. If the refresh was already
100
- // spent before this decrypt began, this re-attempt is a local
101
- // no-network decrypt that fails the same way -- so a genuinely
102
- // foreign envelope still surfaces UnknownEpochError, and never a
103
- // second description read.
104
- return inner.decrypt({ envelope });
105
- }
106
- }
107
- };
108
- }
109
- //# sourceMappingURL=cipher.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../src/descriptors/cipher.ts"],"names":[],"mappings":"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"}
@@ -1,44 +0,0 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
- /**
5
- * The read-side classification of what an injected `DocCipher` throws when it
6
- * cannot open an envelope.
7
- *
8
- * A decrypt has two distinguishable no-key outcomes, and a host that scans
9
- * rows must tell them apart: an epoch the descriptor this reader holds does
10
- * not list at all (`UnknownEpochError` -- possibly fresh data behind a stale
11
- * descriptor, so a re-read may fix it), and an epoch the descriptor does list
12
- * but this reader holds no key for (`KeyUnwrapError` -- real data, and
13
- * permanently unreadable here, since re-reading the same descriptor cannot
14
- * produce a key the reader was not given). Neither is corruption, so neither
15
- * row may be treated as garbage.
16
- *
17
- * Both are matched on `err.name`, never `instanceof`: the cipher is an
18
- * injected seam, and in a wallet whose `@interop/was-client` resolves to a
19
- * second copy (a `link:` dev setup, a dedupe miss through a dependency tree)
20
- * the class the cipher throws is not the class the caller imported. The cost
21
- * of the miss lands on real data -- a scan that misses `KeyUnwrapError` drops
22
- * the row into its undecryptable bucket, which a host is entitled to purge.
23
- * Both classes assign their `name` explicitly, which is what makes the string
24
- * a contract.
25
- *
26
- * The unknown-epoch half of the pair ships from `@interop/was-client/sync`
27
- * as `isUnknownEpochError`, beside the class that assigns the name. This half
28
- * stays here on policy rather than on class adjacency: it classifies a
29
- * roster-membership failure the wallet layer owns, and no sync driver
30
- * dispatches on it. The file sits beside the cipher that raises the error and
31
- * stays import-free for the same reason `resourceLog/errors.ts` does.
32
- */
33
- /**
34
- * Whether an error is the cipher's not-a-recipient signal (`KeyUnwrapError`):
35
- * the envelope's epoch IS on the descriptor this reader holds, but the reader
36
- * has no key for it -- never a recipient of that epoch, or removed and the
37
- * epoch rotated since. Real data, unreadable by this wallet, and never
38
- * garbage: a caller skips such a row and leaves it in place.
39
- *
40
- * @param err {unknown}
41
- * @returns {boolean}
42
- */
43
- export declare function isKeyUnwrapError(err: unknown): boolean;
44
- //# sourceMappingURL=errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/descriptors/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEtD"}
@@ -1,46 +0,0 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
- /**
5
- * The read-side classification of what an injected `DocCipher` throws when it
6
- * cannot open an envelope.
7
- *
8
- * A decrypt has two distinguishable no-key outcomes, and a host that scans
9
- * rows must tell them apart: an epoch the descriptor this reader holds does
10
- * not list at all (`UnknownEpochError` -- possibly fresh data behind a stale
11
- * descriptor, so a re-read may fix it), and an epoch the descriptor does list
12
- * but this reader holds no key for (`KeyUnwrapError` -- real data, and
13
- * permanently unreadable here, since re-reading the same descriptor cannot
14
- * produce a key the reader was not given). Neither is corruption, so neither
15
- * row may be treated as garbage.
16
- *
17
- * Both are matched on `err.name`, never `instanceof`: the cipher is an
18
- * injected seam, and in a wallet whose `@interop/was-client` resolves to a
19
- * second copy (a `link:` dev setup, a dedupe miss through a dependency tree)
20
- * the class the cipher throws is not the class the caller imported. The cost
21
- * of the miss lands on real data -- a scan that misses `KeyUnwrapError` drops
22
- * the row into its undecryptable bucket, which a host is entitled to purge.
23
- * Both classes assign their `name` explicitly, which is what makes the string
24
- * a contract.
25
- *
26
- * The unknown-epoch half of the pair ships from `@interop/was-client/sync`
27
- * as `isUnknownEpochError`, beside the class that assigns the name. This half
28
- * stays here on policy rather than on class adjacency: it classifies a
29
- * roster-membership failure the wallet layer owns, and no sync driver
30
- * dispatches on it. The file sits beside the cipher that raises the error and
31
- * stays import-free for the same reason `resourceLog/errors.ts` does.
32
- */
33
- /**
34
- * Whether an error is the cipher's not-a-recipient signal (`KeyUnwrapError`):
35
- * the envelope's epoch IS on the descriptor this reader holds, but the reader
36
- * has no key for it -- never a recipient of that epoch, or removed and the
37
- * epoch rotated since. Real data, unreadable by this wallet, and never
38
- * garbage: a caller skips such a row and leaves it in place.
39
- *
40
- * @param err {unknown}
41
- * @returns {boolean}
42
- */
43
- export function isKeyUnwrapError(err) {
44
- return err?.name === 'KeyUnwrapError';
45
- }
46
- //# sourceMappingURL=errors.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/descriptors/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,OAAQ,GAAiC,EAAE,IAAI,KAAK,gBAAgB,CAAA;AACtE,CAAC"}
@@ -1,62 +0,0 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
- /**
5
- * The unknown-epoch refresh policy: an epoch rotation emits no change-feed
6
- * entry, so a cipher built from a cached descriptor can meet envelopes stamped
7
- * with an epoch it has never seen. The remedy is one re-read of the
8
- * Collection Description plus a cipher rebuild and a single retry -- and the
9
- * policy guards that remedy to ONCE per collection per session, so a
10
- * genuinely foreign envelope (one no descriptor will ever route) cannot drive
11
- * a refetch loop, let alone a refetch per resource.
12
- */
13
- /**
14
- * Tracks which collections have already spent their one refresh this session,
15
- * and runs reads under the refresh-and-retry-once rule. One instance per
16
- * session (it IS the session scope of the guard); the injected `refresh` does
17
- * the host's whole swap -- re-acquire the descriptor(s), rebuild the
18
- * cipher(s), and install them wherever the host keeps them.
19
- */
20
- export declare class DescriptorRefreshPolicy {
21
- #private;
22
- constructor({ refresh }: {
23
- refresh: (options: {
24
- collectionId: string;
25
- }) => Promise<void>;
26
- });
27
- /**
28
- * Whether a collection still has its one refresh this session.
29
- */
30
- shouldRefresh({ collectionId }: {
31
- collectionId: string;
32
- }): boolean;
33
- /**
34
- * Runs a read that reports whether it skipped unknown-epoch rows; on the
35
- * first such report for a collection this session, spends the collection's
36
- * refresh (descriptor re-read + cipher swap, via the injected `refresh`) and
37
- * re-reads once. A later unknown-epoch report for the same collection
38
- * returns the read's value as-is.
39
- *
40
- * @param options {object}
41
- * @param options.collectionId {string}
42
- * @param options.read {function} the read, reporting `unknownEpoch`
43
- * @returns {Promise<T>} the (possibly re-read) value
44
- */
45
- readWithRefresh<T>({ collectionId, read }: {
46
- collectionId: string;
47
- read: () => Promise<{
48
- value: T;
49
- unknownEpoch: boolean;
50
- }>;
51
- }): Promise<T>;
52
- /**
53
- * Re-arms the guard -- for one collection, or (with no argument) for all.
54
- * Call when a fresh descriptor is installed by some other path (a share,
55
- * unshare, or recipient rotation this session performed itself), since the
56
- * next unknown-epoch read is then evidence of a NEW rotation elsewhere.
57
- */
58
- reset(options?: {
59
- collectionId?: string;
60
- }): void;
61
- }
62
- //# sourceMappingURL=refresh.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/descriptors/refresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,qBAAa,uBAAuB;;gBAKtB,EACV,OAAO,EACR,EAAE;QACD,OAAO,EAAE,CAAC,OAAO,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAC9D;IAID;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;IAIlE;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,CAAC,EAAE,EACvB,YAAY,EACZ,IAAI,EACL,EAAE;QACD,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,OAAO,CAAC;YAAE,KAAK,EAAE,CAAC,CAAC;YAAC,YAAY,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KACzD,GAAG,OAAO,CAAC,CAAC,CAAC;IAUd;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAOjD"}
@@ -1,69 +0,0 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
- /**
5
- * The unknown-epoch refresh policy: an epoch rotation emits no change-feed
6
- * entry, so a cipher built from a cached descriptor can meet envelopes stamped
7
- * with an epoch it has never seen. The remedy is one re-read of the
8
- * Collection Description plus a cipher rebuild and a single retry -- and the
9
- * policy guards that remedy to ONCE per collection per session, so a
10
- * genuinely foreign envelope (one no descriptor will ever route) cannot drive
11
- * a refetch loop, let alone a refetch per resource.
12
- */
13
- /**
14
- * Tracks which collections have already spent their one refresh this session,
15
- * and runs reads under the refresh-and-retry-once rule. One instance per
16
- * session (it IS the session scope of the guard); the injected `refresh` does
17
- * the host's whole swap -- re-acquire the descriptor(s), rebuild the
18
- * cipher(s), and install them wherever the host keeps them.
19
- */
20
- export class DescriptorRefreshPolicy {
21
- #refresh;
22
- // Collection ids whose one refresh this session is already spent.
23
- #refreshed = new Set();
24
- constructor({ refresh }) {
25
- this.#refresh = refresh;
26
- }
27
- /**
28
- * Whether a collection still has its one refresh this session.
29
- */
30
- shouldRefresh({ collectionId }) {
31
- return !this.#refreshed.has(collectionId);
32
- }
33
- /**
34
- * Runs a read that reports whether it skipped unknown-epoch rows; on the
35
- * first such report for a collection this session, spends the collection's
36
- * refresh (descriptor re-read + cipher swap, via the injected `refresh`) and
37
- * re-reads once. A later unknown-epoch report for the same collection
38
- * returns the read's value as-is.
39
- *
40
- * @param options {object}
41
- * @param options.collectionId {string}
42
- * @param options.read {function} the read, reporting `unknownEpoch`
43
- * @returns {Promise<T>} the (possibly re-read) value
44
- */
45
- async readWithRefresh({ collectionId, read }) {
46
- const first = await read();
47
- if (first.unknownEpoch && this.shouldRefresh({ collectionId })) {
48
- this.#refreshed.add(collectionId);
49
- await this.#refresh({ collectionId });
50
- return (await read()).value;
51
- }
52
- return first.value;
53
- }
54
- /**
55
- * Re-arms the guard -- for one collection, or (with no argument) for all.
56
- * Call when a fresh descriptor is installed by some other path (a share,
57
- * unshare, or recipient rotation this session performed itself), since the
58
- * next unknown-epoch read is then evidence of a NEW rotation elsewhere.
59
- */
60
- reset(options) {
61
- if (options?.collectionId === undefined) {
62
- this.#refreshed.clear();
63
- }
64
- else {
65
- this.#refreshed.delete(options.collectionId);
66
- }
67
- }
68
- }
69
- //# sourceMappingURL=refresh.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/descriptors/refresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,MAAM,OAAO,uBAAuB;IACzB,QAAQ,CAAsD;IACvE,kEAAkE;IACzD,UAAU,GAAG,IAAI,GAAG,EAAU,CAAA;IAEvC,YAAY,EACV,OAAO,EAGR;QACC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACzB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,EAA4B;QACtD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,eAAe,CAAI,EACvB,YAAY,EACZ,IAAI,EAIL;QACC,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAA;QAC1B,IAAI,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;YACjC,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;YACrC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAA;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAA;IACpB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAmC;QACvC,IAAI,OAAO,EAAE,YAAY,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;CACF"}