@interop/wallet-core 0.78.1 → 0.79.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 (170) hide show
  1. package/README.md +16 -3
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +2 -2
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +1 -1
  5. package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
  6. package/dist/clientAnnex/establish.d.ts +2 -2
  7. package/dist/clientAnnex/establish.d.ts.map +1 -1
  8. package/dist/clientAnnex/forget.d.ts +1 -1
  9. package/dist/clientAnnex/forget.d.ts.map +1 -1
  10. package/dist/clientAnnex/heal.d.ts.map +1 -1
  11. package/dist/clientAnnex/heal.js +3 -1
  12. package/dist/clientAnnex/heal.js.map +1 -1
  13. package/dist/clientAnnex/ladder.d.ts +3 -98
  14. package/dist/clientAnnex/ladder.d.ts.map +1 -1
  15. package/dist/clientAnnex/ladder.js +4 -140
  16. package/dist/clientAnnex/ladder.js.map +1 -1
  17. package/dist/clientAnnex/log.d.ts +26 -10
  18. package/dist/clientAnnex/log.d.ts.map +1 -1
  19. package/dist/clientAnnex/log.js +39 -19
  20. package/dist/clientAnnex/log.js.map +1 -1
  21. package/dist/clientAnnex/mend.d.ts +2 -2
  22. package/dist/clientAnnex/mend.d.ts.map +1 -1
  23. package/dist/clientAnnex/mend.js +1 -1
  24. package/dist/clientAnnex/mend.js.map +1 -1
  25. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +1 -1
  26. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
  27. package/dist/clientAnnex/selfEnroll.d.ts +1 -1
  28. package/dist/clientAnnex/selfEnroll.d.ts.map +1 -1
  29. package/dist/clientAnnex/selfEnroll.js +2 -1
  30. package/dist/clientAnnex/selfEnroll.js.map +1 -1
  31. package/dist/clients/revocation.d.ts +1 -1
  32. package/dist/clients/revocation.d.ts.map +1 -1
  33. package/dist/clients/rosterPolicy.d.ts +1 -1
  34. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  35. package/dist/descriptors/logSource.d.ts +2 -1
  36. package/dist/descriptors/logSource.d.ts.map +1 -1
  37. package/dist/descriptors/logSource.js +1 -1
  38. package/dist/descriptors/logSource.js.map +1 -1
  39. package/dist/enrollment/enrollment.d.ts +2 -2
  40. package/dist/enrollment/enrollment.d.ts.map +1 -1
  41. package/dist/enrollment/enrollment.js +2 -1
  42. package/dist/enrollment/enrollment.js.map +1 -1
  43. package/dist/genesis/accountGenesis.d.ts +1 -1
  44. package/dist/genesis/accountGenesis.d.ts.map +1 -1
  45. package/dist/genesis/accountGenesis.js +11 -5
  46. package/dist/genesis/accountGenesis.js.map +1 -1
  47. package/dist/keyring/fetch.d.ts +1 -1
  48. package/dist/keyring/fetch.d.ts.map +1 -1
  49. package/dist/keyring/fetch.js +1 -1
  50. package/dist/keyring/fetch.js.map +1 -1
  51. package/dist/keyring/index.d.ts +15 -8
  52. package/dist/keyring/index.d.ts.map +1 -1
  53. package/dist/keyring/index.js +11 -6
  54. package/dist/keyring/index.js.map +1 -1
  55. package/dist/keyring/kdf.d.ts +0 -69
  56. package/dist/keyring/kdf.d.ts.map +1 -1
  57. package/dist/keyring/kdf.js +7 -86
  58. package/dist/keyring/kdf.js.map +1 -1
  59. package/dist/keyring/record.d.ts +1 -200
  60. package/dist/keyring/record.d.ts.map +1 -1
  61. package/dist/keyring/record.js +5 -251
  62. package/dist/keyring/record.js.map +1 -1
  63. package/dist/keyring/recordEnvelope.d.ts +270 -0
  64. package/dist/keyring/recordEnvelope.d.ts.map +1 -0
  65. package/dist/keyring/recordEnvelope.js +282 -0
  66. package/dist/keyring/recordEnvelope.js.map +1 -0
  67. package/dist/keyring/unlockIdentity.d.ts +71 -0
  68. package/dist/keyring/unlockIdentity.d.ts.map +1 -0
  69. package/dist/keyring/unlockIdentity.js +96 -0
  70. package/dist/keyring/unlockIdentity.js.map +1 -0
  71. package/dist/keyring/unlockSpace.d.ts +12 -1
  72. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  73. package/dist/keyring/unlockSpace.js +15 -2
  74. package/dist/keyring/unlockSpace.js.map +1 -1
  75. package/dist/keys/index.d.ts +6 -3
  76. package/dist/keys/index.d.ts.map +1 -1
  77. package/dist/keys/index.js +6 -3
  78. package/dist/keys/index.js.map +1 -1
  79. package/dist/keys/rosterLogStore.d.ts +1 -1
  80. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  81. package/dist/keys/rosterLogStore.js +1 -1
  82. package/dist/keys/rosterLogStore.js.map +1 -1
  83. package/dist/keys/rosterRecipientKid.d.ts +28 -0
  84. package/dist/keys/rosterRecipientKid.d.ts.map +1 -0
  85. package/dist/keys/rosterRecipientKid.js +27 -0
  86. package/dist/keys/rosterRecipientKid.js.map +1 -0
  87. package/dist/keys/spaceEpochs.d.ts +1 -1
  88. package/dist/keys/spaceEpochs.d.ts.map +1 -1
  89. package/dist/keys/spaceEpochs.js +2 -2
  90. package/dist/keys/spaceEpochs.js.map +1 -1
  91. package/dist/keys/userKey.d.ts +4 -46
  92. package/dist/keys/userKey.d.ts.map +1 -1
  93. package/dist/keys/userKey.js +8 -60
  94. package/dist/keys/userKey.js.map +1 -1
  95. package/dist/keys/userKeyCascade.d.ts +1 -33
  96. package/dist/keys/userKeyCascade.d.ts.map +1 -1
  97. package/dist/keys/userKeyCascade.js +2 -49
  98. package/dist/keys/userKeyCascade.js.map +1 -1
  99. package/dist/keys/userKeyGenerations.d.ts +47 -0
  100. package/dist/keys/userKeyGenerations.d.ts.map +1 -0
  101. package/dist/keys/userKeyGenerations.js +50 -0
  102. package/dist/keys/userKeyGenerations.js.map +1 -0
  103. package/dist/keys/userKeyRoster.d.ts +1 -19
  104. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  105. package/dist/keys/userKeyRoster.js +13 -19
  106. package/dist/keys/userKeyRoster.js.map +1 -1
  107. package/dist/keys/userKeyRosterCascade.d.ts +1 -1
  108. package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
  109. package/dist/keys/userKeySigning.d.ts +44 -0
  110. package/dist/keys/userKeySigning.d.ts.map +1 -0
  111. package/dist/keys/userKeySigning.js +65 -0
  112. package/dist/keys/userKeySigning.js.map +1 -0
  113. package/dist/recovery/recoveryCode.d.ts.map +1 -1
  114. package/dist/recovery/recoveryCode.js +3 -4
  115. package/dist/recovery/recoveryCode.js.map +1 -1
  116. package/dist/recovery/recoveryDelegation.d.ts +1 -1
  117. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  118. package/dist/space/collections.d.ts +1 -43
  119. package/dist/space/collections.d.ts.map +1 -1
  120. package/dist/space/collections.js +2 -34
  121. package/dist/space/collections.js.map +1 -1
  122. package/dist/space/systemCollections.d.ts +55 -0
  123. package/dist/space/systemCollections.d.ts.map +1 -0
  124. package/dist/space/systemCollections.js +46 -0
  125. package/dist/space/systemCollections.js.map +1 -0
  126. package/dist/sync/contactsConflict.d.ts +56 -10
  127. package/dist/sync/contactsConflict.d.ts.map +1 -1
  128. package/dist/sync/contactsConflict.js +82 -18
  129. package/dist/sync/contactsConflict.js.map +1 -1
  130. package/dist/sync/engine.d.ts +9 -3
  131. package/dist/sync/engine.d.ts.map +1 -1
  132. package/dist/sync/engine.js.map +1 -1
  133. package/dist/sync/pull.d.ts +25 -4
  134. package/dist/sync/pull.d.ts.map +1 -1
  135. package/dist/sync/pull.js +27 -3
  136. package/dist/sync/pull.js.map +1 -1
  137. package/dist/sync/remint.d.ts +10 -4
  138. package/dist/sync/remint.d.ts.map +1 -1
  139. package/dist/sync/remint.js +28 -6
  140. package/dist/sync/remint.js.map +1 -1
  141. package/dist/unlock/ladderDerivation.d.ts +98 -0
  142. package/dist/unlock/ladderDerivation.d.ts.map +1 -0
  143. package/dist/unlock/ladderDerivation.js +157 -0
  144. package/dist/unlock/ladderDerivation.js.map +1 -0
  145. package/dist/unlock/retire.d.ts +1 -1
  146. package/dist/unlock/retire.d.ts.map +1 -1
  147. package/dist/unlock/standingClient.js +1 -1
  148. package/dist/unlock/standingClient.js.map +1 -1
  149. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  150. package/dist/unlock/standingWebvh.js +3 -3
  151. package/dist/unlock/standingWebvh.js.map +1 -1
  152. package/dist/unlock/unlockRecord.d.ts +2 -1
  153. package/dist/unlock/unlockRecord.d.ts.map +1 -1
  154. package/dist/unlock/unlockRecord.js +11 -2
  155. package/dist/unlock/unlockRecord.js.map +1 -1
  156. package/dist/webvh/accountEntry.d.ts +2 -1
  157. package/dist/webvh/accountEntry.d.ts.map +1 -1
  158. package/dist/webvh/accountEntry.js.map +1 -1
  159. package/dist/webvh/didWebvh.d.ts +1 -11
  160. package/dist/webvh/didWebvh.d.ts.map +1 -1
  161. package/dist/webvh/didWebvh.js +5 -13
  162. package/dist/webvh/didWebvh.js.map +1 -1
  163. package/dist/webvh/updateKeyMultibase.d.ts +12 -0
  164. package/dist/webvh/updateKeyMultibase.d.ts.map +1 -0
  165. package/dist/webvh/updateKeyMultibase.js +23 -0
  166. package/dist/webvh/updateKeyMultibase.js.map +1 -0
  167. package/dist/webvh/wasIdStore.d.ts +5 -3
  168. package/dist/webvh/wasIdStore.d.ts.map +1 -1
  169. package/dist/webvh/wasIdStore.js.map +1 -1
  170. package/package.json +53 -11
@@ -17,14 +17,33 @@
17
17
  * with no duplicates and no round trips.
18
18
  *
19
19
  * **Fail-safe to remote.** Whenever the fields the rule needs are unreachable
20
- * -- a tombstone on either side, a missing cipher, an envelope that will not
21
- * decrypt, a body that is not a valid head payload -- the remote master wins.
22
- * That is the always-converging default, so a malformed side simply loses: a
23
- * valid local over a malformed remote re-pushes and repairs the server copy, a
24
- * valid remote over a malformed local is adopted, and two malformed sides adopt
25
- * the server version rather than re-fighting the conflict forever. A delete is
26
- * in the same class deliberately: a tombstone carries no fresher stamp (a
27
- * delete does not rewrite the head payload), so deletion wins.
20
+ * -- a tombstone on either side, a missing cipher, an envelope this replica
21
+ * holds no key for, a body that is not a valid head payload -- the remote
22
+ * master wins. That is the always-converging default, so a malformed side
23
+ * simply loses: a valid local over a malformed remote re-pushes and repairs the
24
+ * server copy, a valid remote over a malformed local is adopted, and two
25
+ * malformed sides adopt the server version rather than re-fighting the conflict
26
+ * forever. A delete is in the same class deliberately: a tombstone carries no
27
+ * fresher stamp (a delete does not rewrite the head payload), so deletion wins.
28
+ *
29
+ * **An integrity refusal is not an unreachable side.** A decrypt refused by the
30
+ * cipher's envelope-to-resource binding check (was-client's `IntegrityError`)
31
+ * says the stored body was written for a different resource than the one it was
32
+ * read under: the host altered the data or served it under another id. Scoring
33
+ * that as one more unreachable side would let the fail-safe default settle the
34
+ * conflict silently and discard the refusal, which is the binding check's whole
35
+ * point. It is rethrown instead, so it leaves the resolver and fails the
36
+ * replication cycle -- the rule `@interop/was-sync`'s own last-write-wins
37
+ * resolver follows on the same seam. A side this replica simply holds no key
38
+ * for (`UnknownEpochError`, `KeyUnwrapError`) is not that: it stays unreachable
39
+ * and stays on the fail-safe path above.
40
+ *
41
+ * Both directions fail the cycle, and no winner is returned: a misbound remote
42
+ * side and a misbound local side are refused alike. The caller learns WHICH
43
+ * side was refused through the optional `onIntegrityRefusal` callback, which
44
+ * fires once per refused side (both sides can be refused in one conflict)
45
+ * before the refusal is rethrown. The callback is a reporting seam alone, so it
46
+ * decides nothing.
28
47
  *
29
48
  * Everything imported here is crypto-free: the envelope predicate and the
30
49
  * `DocCipher` seam come from was-client's plain `sync` module (the same one the
@@ -44,14 +63,30 @@ export type ContactConflictWinner = 'remote' | 'local';
44
63
  * envelope, passes plaintext through, and resolves `undefined` when the
45
64
  * payload (and so the fields the rule compares) cannot be reached.
46
65
  *
66
+ * A side this replica holds no key for is unreachable. What the fail-safe rule
67
+ * below then does with it depends on which side it was: an unreachable local
68
+ * side hands the conflict to the remote master, while an unreachable remote
69
+ * side leaves the reachable local body to win. Neither side is ever compared on
70
+ * a body it could not open.
71
+ *
72
+ * The decrypt is addressed with the row's own id, and an envelope sealed for
73
+ * another resource is refused with an `IntegrityError` rather than read as one
74
+ * more unreachable side. That refusal is rethrown, out of the resolver and into
75
+ * the replication cycle. See the module doc.
76
+ *
47
77
  * @param options {object}
78
+ * @param options.id {string} the contact head row's resource id, the id the
79
+ * stored envelope must be sealed for
48
80
  * @param options.data {Json} the stored body: an encrypted envelope or a
49
81
  * plaintext payload
50
82
  * @param [options.cipher] {DocCipher} the collection's document cipher;
51
83
  * absent for a plaintext store, in which case an envelope is unreachable
52
84
  * @returns {Promise<ContactHeadPayload | undefined>}
85
+ * @throws {Error} the cipher's `IntegrityError`: the stored envelope was
86
+ * sealed for a different resource than `id`
53
87
  */
54
- export declare function contactHeadPayloadOf({ data, cipher }: {
88
+ export declare function contactHeadPayloadOf({ id, data, cipher }: {
89
+ id: string;
55
90
  data: Json | undefined;
56
91
  cipher?: DocCipher;
57
92
  }): Promise<ContactHeadPayload | undefined>;
@@ -59,18 +94,29 @@ export declare function contactHeadPayloadOf({ data, cipher }: {
59
94
  * Decides a contact-head conflict. See the module doc for the fail-safe rule.
60
95
  *
61
96
  * @param options {object}
97
+ * @param options.id {string} the contested row's resource id, which both
98
+ * sides' envelopes must be sealed for
62
99
  * @param options.remote {Json} the remote (master) row body
63
100
  * @param options.local {Json} the local row body
64
101
  * @param [options.cipher] {DocCipher} the collection's document cipher
65
102
  * @param [options.remoteDeleted] {boolean} the remote side is a tombstone
66
103
  * @param [options.localDeleted] {boolean} the local side is a tombstone
104
+ * @param [options.onIntegrityRefusal] {Function} reports each side the
105
+ * binding check refused, as `{ side, err }`, before the refusal is rethrown
67
106
  * @returns {Promise<ContactConflictWinner>}
107
+ * @throws {Error} the cipher's `IntegrityError` from either side: the
108
+ * conflict is left undecided and the replication cycle fails
68
109
  */
69
- export declare function resolveContactHeadConflict({ remote, local, cipher, remoteDeleted, localDeleted }: {
110
+ export declare function resolveContactHeadConflict({ id, remote, local, cipher, remoteDeleted, localDeleted, onIntegrityRefusal }: {
111
+ id: string;
70
112
  remote: Json | undefined;
71
113
  local: Json | undefined;
72
114
  cipher?: DocCipher;
73
115
  remoteDeleted?: boolean;
74
116
  localDeleted?: boolean;
117
+ onIntegrityRefusal?: (refusal: {
118
+ side: 'remote' | 'local';
119
+ err: unknown;
120
+ }) => void;
75
121
  }): Promise<ContactConflictWinner>;
76
122
  //# sourceMappingURL=contactsConflict.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contactsConflict.d.ts","sourceRoot":"","sources":["../../src/sync/contactsConflict.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,IAAI,EACV,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAA;AAE7B;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,IAAI,EACJ,MAAM,EACP,EAAE;IACD,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;IACtB,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAgB1C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,MAAM,EACN,KAAK,EACL,MAAM,EACN,aAAqB,EACrB,YAAoB,EACrB,EAAE;IACD,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;IACxB,KAAK,EAAE,IAAI,GAAG,SAAS,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAqBjC"}
1
+ {"version":3,"file":"contactsConflict.d.ts","sourceRoot":"","sources":["../../src/sync/contactsConflict.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,IAAI,EACV,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAA;AAE7B;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,EAAE,EACF,IAAI,EACJ,MAAM,EACP,EAAE;IACD,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;IACtB,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAmB1C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,EAAE,EACF,MAAM,EACN,KAAK,EACL,MAAM,EACN,aAAqB,EACrB,YAAoB,EACpB,kBAAkB,EACnB,EAAE;IACD,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;IACxB,KAAK,EAAE,IAAI,GAAG,SAAS,CAAA;IACvB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC7B,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAA;QACxB,GAAG,EAAE,OAAO,CAAA;KACb,KAAK,IAAI,CAAA;CACX,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA0CjC"}
@@ -17,14 +17,33 @@
17
17
  * with no duplicates and no round trips.
18
18
  *
19
19
  * **Fail-safe to remote.** Whenever the fields the rule needs are unreachable
20
- * -- a tombstone on either side, a missing cipher, an envelope that will not
21
- * decrypt, a body that is not a valid head payload -- the remote master wins.
22
- * That is the always-converging default, so a malformed side simply loses: a
23
- * valid local over a malformed remote re-pushes and repairs the server copy, a
24
- * valid remote over a malformed local is adopted, and two malformed sides adopt
25
- * the server version rather than re-fighting the conflict forever. A delete is
26
- * in the same class deliberately: a tombstone carries no fresher stamp (a
27
- * delete does not rewrite the head payload), so deletion wins.
20
+ * -- a tombstone on either side, a missing cipher, an envelope this replica
21
+ * holds no key for, a body that is not a valid head payload -- the remote
22
+ * master wins. That is the always-converging default, so a malformed side
23
+ * simply loses: a valid local over a malformed remote re-pushes and repairs the
24
+ * server copy, a valid remote over a malformed local is adopted, and two
25
+ * malformed sides adopt the server version rather than re-fighting the conflict
26
+ * forever. A delete is in the same class deliberately: a tombstone carries no
27
+ * fresher stamp (a delete does not rewrite the head payload), so deletion wins.
28
+ *
29
+ * **An integrity refusal is not an unreachable side.** A decrypt refused by the
30
+ * cipher's envelope-to-resource binding check (was-client's `IntegrityError`)
31
+ * says the stored body was written for a different resource than the one it was
32
+ * read under: the host altered the data or served it under another id. Scoring
33
+ * that as one more unreachable side would let the fail-safe default settle the
34
+ * conflict silently and discard the refusal, which is the binding check's whole
35
+ * point. It is rethrown instead, so it leaves the resolver and fails the
36
+ * replication cycle -- the rule `@interop/was-sync`'s own last-write-wins
37
+ * resolver follows on the same seam. A side this replica simply holds no key
38
+ * for (`UnknownEpochError`, `KeyUnwrapError`) is not that: it stays unreachable
39
+ * and stays on the fail-safe path above.
40
+ *
41
+ * Both directions fail the cycle, and no winner is returned: a misbound remote
42
+ * side and a misbound local side are refused alike. The caller learns WHICH
43
+ * side was refused through the optional `onIntegrityRefusal` callback, which
44
+ * fires once per refused side (both sides can be refused in one conflict)
45
+ * before the refusal is rethrown. The callback is a reporting seam alone, so it
46
+ * decides nothing.
28
47
  *
29
48
  * Everything imported here is crypto-free: the envelope predicate and the
30
49
  * `DocCipher` seam come from was-client's plain `sync` module (the same one the
@@ -33,21 +52,36 @@
33
52
  * in a plain test runner -- the EDV graph is the app's to pull in, at the point
34
53
  * where it builds the cipher it passes down.
35
54
  */
36
- import { isEncryptedEnvelope } from '@interop/was-client/sync';
55
+ import { isEncryptedEnvelope, isIntegrityError } from '@interop/was-client/sync';
37
56
  import { isContactHeadPayload, remotePayloadWins } from '@interop/social-core';
38
57
  /**
39
58
  * Recovers a validated head payload from a stored row body: decrypts an
40
59
  * envelope, passes plaintext through, and resolves `undefined` when the
41
60
  * payload (and so the fields the rule compares) cannot be reached.
42
61
  *
62
+ * A side this replica holds no key for is unreachable. What the fail-safe rule
63
+ * below then does with it depends on which side it was: an unreachable local
64
+ * side hands the conflict to the remote master, while an unreachable remote
65
+ * side leaves the reachable local body to win. Neither side is ever compared on
66
+ * a body it could not open.
67
+ *
68
+ * The decrypt is addressed with the row's own id, and an envelope sealed for
69
+ * another resource is refused with an `IntegrityError` rather than read as one
70
+ * more unreachable side. That refusal is rethrown, out of the resolver and into
71
+ * the replication cycle. See the module doc.
72
+ *
43
73
  * @param options {object}
74
+ * @param options.id {string} the contact head row's resource id, the id the
75
+ * stored envelope must be sealed for
44
76
  * @param options.data {Json} the stored body: an encrypted envelope or a
45
77
  * plaintext payload
46
78
  * @param [options.cipher] {DocCipher} the collection's document cipher;
47
79
  * absent for a plaintext store, in which case an envelope is unreachable
48
80
  * @returns {Promise<ContactHeadPayload | undefined>}
81
+ * @throws {Error} the cipher's `IntegrityError`: the stored envelope was
82
+ * sealed for a different resource than `id`
49
83
  */
50
- export async function contactHeadPayloadOf({ data, cipher }) {
84
+ export async function contactHeadPayloadOf({ id, data, cipher }) {
51
85
  if (data === null || data === undefined) {
52
86
  return undefined;
53
87
  }
@@ -57,9 +91,12 @@ export async function contactHeadPayloadOf({ data, cipher }) {
57
91
  return undefined;
58
92
  }
59
93
  try {
60
- body = await cipher.decrypt({ envelope: data });
94
+ body = await cipher.decrypt({ id, envelope: data });
61
95
  }
62
- catch {
96
+ catch (err) {
97
+ if (isIntegrityError(err)) {
98
+ throw err;
99
+ }
63
100
  return undefined;
64
101
  }
65
102
  }
@@ -69,25 +106,52 @@ export async function contactHeadPayloadOf({ data, cipher }) {
69
106
  * Decides a contact-head conflict. See the module doc for the fail-safe rule.
70
107
  *
71
108
  * @param options {object}
109
+ * @param options.id {string} the contested row's resource id, which both
110
+ * sides' envelopes must be sealed for
72
111
  * @param options.remote {Json} the remote (master) row body
73
112
  * @param options.local {Json} the local row body
74
113
  * @param [options.cipher] {DocCipher} the collection's document cipher
75
114
  * @param [options.remoteDeleted] {boolean} the remote side is a tombstone
76
115
  * @param [options.localDeleted] {boolean} the local side is a tombstone
116
+ * @param [options.onIntegrityRefusal] {Function} reports each side the
117
+ * binding check refused, as `{ side, err }`, before the refusal is rethrown
77
118
  * @returns {Promise<ContactConflictWinner>}
119
+ * @throws {Error} the cipher's `IntegrityError` from either side: the
120
+ * conflict is left undecided and the replication cycle fails
78
121
  */
79
- export async function resolveContactHeadConflict({ remote, local, cipher, remoteDeleted = false, localDeleted = false }) {
122
+ export async function resolveContactHeadConflict({ id, remote, local, cipher, remoteDeleted = false, localDeleted = false, onIntegrityRefusal }) {
80
123
  if (remoteDeleted || localDeleted) {
81
124
  return 'remote';
82
125
  }
83
126
  // Both sides decrypt independently, so they decrypt concurrently. Each
84
- // side's own unreachability (a failed decrypt, a malformed payload) is
127
+ // side's own unreachability (no key for the envelope, a malformed payload) is
85
128
  // already resolved as `undefined` inside the helper, so the join changes
86
- // nothing about the fail-safe rule below.
87
- const [remoteHead, localHead] = await Promise.all([
88
- contactHeadPayloadOf({ data: remote, cipher }),
89
- contactHeadPayloadOf({ data: local, cipher })
129
+ // nothing about the fail-safe rule below. An integrity refusal on either side
130
+ // rejects instead, and no winner is returned.
131
+ const [remoteResult, localResult] = await Promise.allSettled([
132
+ contactHeadPayloadOf({ id, data: remote, cipher }),
133
+ contactHeadPayloadOf({ id, data: local, cipher })
90
134
  ]);
135
+ // `allSettled` rather than `all`, so a conflict whose two sides are both
136
+ // misbound reports both before the first refusal leaves. The refusal itself
137
+ // is rethrown unchanged, so the caller still matches it on `name`.
138
+ const sides = [
139
+ { side: 'remote', result: remoteResult },
140
+ { side: 'local', result: localResult }
141
+ ];
142
+ for (const { side, result } of sides) {
143
+ if (result.status === 'rejected' && isIntegrityError(result.reason)) {
144
+ onIntegrityRefusal?.({ side, err: result.reason });
145
+ }
146
+ }
147
+ if (remoteResult.status === 'rejected') {
148
+ throw remoteResult.reason;
149
+ }
150
+ if (localResult.status === 'rejected') {
151
+ throw localResult.reason;
152
+ }
153
+ const remoteHead = remoteResult.value;
154
+ const localHead = localResult.value;
91
155
  if (remoteHead && localHead) {
92
156
  return remotePayloadWins(remoteHead, localHead) ? 'remote' : 'local';
93
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"contactsConflict.js","sourceRoot":"","sources":["../../src/sync/contactsConflict.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EACL,mBAAmB,EAGpB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EAElB,MAAM,sBAAsB,CAAA;AAO7B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,IAAI,EACJ,MAAM,EAIP;IACC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,IAAI,GAAY,IAAI,CAAA;IACxB,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IACD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AACtD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,EAC/C,MAAM,EACN,KAAK,EACL,MAAM,EACN,aAAa,GAAG,KAAK,EACrB,YAAY,GAAG,KAAK,EAOrB;IACC,IAAI,aAAa,IAAI,YAAY,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,uEAAuE;IACvE,uEAAuE;IACvE,yEAAyE;IACzE,0CAA0C;IAC1C,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChD,oBAAoB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC9C,oBAAoB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC,CAAA;IACF,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;QAC5B,OAAO,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IACtE,CAAC;IACD,4EAA4E;IAC5E,6BAA6B;IAC7B,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
1
+ {"version":3,"file":"contactsConflict.js","sourceRoot":"","sources":["../../src/sync/contactsConflict.ts"],"names":[],"mappings":"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"}
@@ -25,9 +25,15 @@ export interface SyncEngineDeps {
25
25
  port: WasSyncPort;
26
26
  store: SyncStore;
27
27
  /**
28
- * Decrypts a pulled body to its plaintext payload (DocCipher).
29
- */
30
- decryptDoc: (envelope: Json) => Promise<Json>;
28
+ * Decrypts a pulled body to its plaintext payload (DocCipher). `id` is the
29
+ * resource id the replica read the body under, and the cipher verifies the
30
+ * envelope was sealed for it -- an envelope addressed to some other
31
+ * resource is refused with was-client's `IntegrityError`.
32
+ */
33
+ decryptDoc: (options: {
34
+ id: string;
35
+ envelope: Json;
36
+ }) => Promise<Json>;
31
37
  /**
32
38
  * The collection's payload guard, when it has one: a pulled document that
33
39
  * decrypts but fails it is stored without being projected (see `pull.ts`).
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
@@ -15,12 +15,29 @@ import type { Json, ProjectionAction, SyncStore, WasSyncPort, WireDoc } from './
15
15
  * possibly a buggy or schema-incompatible writer) is skipped the same way:
16
16
  * stored, checkpoint advanced, never projected.
17
17
  *
18
+ * The decrypt is addressed: the feed row's own `id` goes to `decryptDoc`, and
19
+ * the cipher refuses an envelope sealed for some other resource with was-
20
+ * client's `IntegrityError`. That refusal has two causes and the reader
21
+ * cannot tell them apart: a host that moved one resource's stored envelope
22
+ * under another resource's id, and a row minted by a writer that predates
23
+ * addressed sealing (the legacy contacts rows
24
+ * `docs/cross-replica-sync-compatibility.md` records as a stated loss, which
25
+ * every fresh replica bootstrap re-reads). It is logged apart from the
26
+ * ordinary undecryptable skip so a caller can count it, but the benign cause
27
+ * is the common one and an alert on it needs a rate rather than a single
28
+ * event. The projection outcome is the same `none`: the row is not applied,
29
+ * the body is still stored, and the checkpoint advances past it.
30
+ *
18
31
  * @param doc {WireDoc}
19
- * @param decryptDoc {(envelope: Json) => Promise<Json>}
32
+ * @param decryptDoc {(options: { id: string, envelope: Json }) =>
33
+ * Promise<Json>}
20
34
  * @param [validatePayload] {(payload: Json) => boolean}
21
35
  * @returns {Promise<ProjectionAction>}
22
36
  */
23
- export declare function projectionForDoc(doc: WireDoc, decryptDoc: (envelope: Json) => Promise<Json>, validatePayload?: (payload: Json) => boolean): Promise<ProjectionAction>;
37
+ export declare function projectionForDoc(doc: WireDoc, decryptDoc: (options: {
38
+ id: string;
39
+ envelope: Json;
40
+ }) => Promise<Json>, validatePayload?: (payload: Json) => boolean): Promise<ProjectionAction>;
24
41
  /**
25
42
  * Runs the pull loop to exhaustion for one feed. Fetches a page from the current
26
43
  * checkpoint, decrypts it to projections, and applies it (upserts + projection +
@@ -36,7 +53,8 @@ export declare function projectionForDoc(doc: WireDoc, decryptDoc: (envelope: Js
36
53
  * @param options.port {WasSyncPort}
37
54
  * @param options.store {SyncStore}
38
55
  * @param options.batchSize {number} pull `limit` (server clamps at 1000)
39
- * @param options.decryptDoc {(envelope: Json) => Promise<Json>}
56
+ * @param options.decryptDoc {(options: { id: string, envelope: Json }) =>
57
+ * Promise<Json>}
40
58
  * @param [options.validatePayload] {(payload: Json) => boolean} collection
41
59
  * payload guard; a decrypted document failing it is stored but not projected
42
60
  * @param [options.signal] {AbortSignal}
@@ -46,7 +64,10 @@ export declare function runPull({ port, store, batchSize, decryptDoc, validatePa
46
64
  port: WasSyncPort;
47
65
  store: SyncStore;
48
66
  batchSize: number;
49
- decryptDoc: (envelope: Json) => Promise<Json>;
67
+ decryptDoc: (options: {
68
+ id: string;
69
+ envelope: Json;
70
+ }) => Promise<Json>;
50
71
  validatePayload?: (payload: Json) => boolean;
51
72
  signal?: AbortSignal;
52
73
  }): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,IAAI,EACJ,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,OAAO,EACR,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,EAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,eAAe,EACf,MAAM,EACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD/B"}
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,IAAI,EACJ,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,OAAO,EACR,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtE,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CAkC3B;AAqBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,eAAe,EACf,MAAM,EACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD/B"}
package/dist/sync/pull.js CHANGED
@@ -20,6 +20,7 @@
20
20
  * - A tombstone deletes the projected row; a live document decrypts its `data`
21
21
  * body to the payload to upsert.
22
22
  */
23
+ import { isIntegrityError } from '@interop/was-client/sync';
23
24
  import { log } from '../log.js';
24
25
  /**
25
26
  * Maps one pulled wire document to the projection action for the decrypted
@@ -37,8 +38,22 @@ import { log } from '../log.js';
37
38
  * possibly a buggy or schema-incompatible writer) is skipped the same way:
38
39
  * stored, checkpoint advanced, never projected.
39
40
  *
41
+ * The decrypt is addressed: the feed row's own `id` goes to `decryptDoc`, and
42
+ * the cipher refuses an envelope sealed for some other resource with was-
43
+ * client's `IntegrityError`. That refusal has two causes and the reader
44
+ * cannot tell them apart: a host that moved one resource's stored envelope
45
+ * under another resource's id, and a row minted by a writer that predates
46
+ * addressed sealing (the legacy contacts rows
47
+ * `docs/cross-replica-sync-compatibility.md` records as a stated loss, which
48
+ * every fresh replica bootstrap re-reads). It is logged apart from the
49
+ * ordinary undecryptable skip so a caller can count it, but the benign cause
50
+ * is the common one and an alert on it needs a rate rather than a single
51
+ * event. The projection outcome is the same `none`: the row is not applied,
52
+ * the body is still stored, and the checkpoint advances past it.
53
+ *
40
54
  * @param doc {WireDoc}
41
- * @param decryptDoc {(envelope: Json) => Promise<Json>}
55
+ * @param decryptDoc {(options: { id: string, envelope: Json }) =>
56
+ * Promise<Json>}
42
57
  * @param [validatePayload] {(payload: Json) => boolean}
43
58
  * @returns {Promise<ProjectionAction>}
44
59
  */
@@ -50,7 +65,7 @@ export async function projectionForDoc(doc, decryptDoc, validatePayload) {
50
65
  return { kind: 'none' };
51
66
  }
52
67
  try {
53
- const payload = await decryptDoc(doc.data);
68
+ const payload = await decryptDoc({ id: doc.id, envelope: doc.data });
54
69
  if (validatePayload !== undefined && !validatePayload(payload)) {
55
70
  log.warn('Skipping malformed synced document (no projection)', {
56
71
  id: doc.id
@@ -60,6 +75,14 @@ export async function projectionForDoc(doc, decryptDoc, validatePayload) {
60
75
  return { kind: 'upsert', payload };
61
76
  }
62
77
  catch (err) {
78
+ if (isIntegrityError(err)) {
79
+ log.warn('Skipping synced document sealed for another resource id (no ' +
80
+ 'projection)', {
81
+ id: doc.id,
82
+ err
83
+ });
84
+ return { kind: 'none' };
85
+ }
63
86
  log.warn('Skipping undecryptable synced document (no projection)', {
64
87
  id: doc.id,
65
88
  err
@@ -97,7 +120,8 @@ function sameCheckpoint(left, right) {
97
120
  * @param options.port {WasSyncPort}
98
121
  * @param options.store {SyncStore}
99
122
  * @param options.batchSize {number} pull `limit` (server clamps at 1000)
100
- * @param options.decryptDoc {(envelope: Json) => Promise<Json>}
123
+ * @param options.decryptDoc {(options: { id: string, envelope: Json }) =>
124
+ * Promise<Json>}
101
125
  * @param [options.validatePayload] {(payload: Json) => boolean} collection
102
126
  * payload guard; a decrypted document failing it is stored but not projected
103
127
  * @param [options.signal] {AbortSignal}
@@ -1 +1 @@
1
- {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"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"}
@@ -13,10 +13,16 @@ import type { DocCipher, Json, SyncStore } from './types.js';
13
13
  * and handed to {@link SyncStore.replacePending} -- which may re-key the row,
14
14
  * since the re-mint is a fresh encryption. Rows already readable under the
15
15
  * adopted descriptor, acked rows (`version > 0` -- they HAVE feed existence
16
- * and are never re-minted), and tombstones are left untouched. A decrypt
17
- * failure other than an unknown epoch propagates: an envelope that is
18
- * corrupt, rather than merely minted under a losing epoch, is not this
19
- * helper's to settle.
16
+ * and are never re-minted), and tombstones are left untouched.
17
+ *
18
+ * Two decrypt failures are told apart. An unknown epoch is the create-loss
19
+ * shape this helper exists for, and the row is re-minted. An addressing
20
+ * refusal (was-client's `IntegrityError`: the envelope is sealed for some
21
+ * other resource id, the shape a row minted by a pre-addressed writer has) is
22
+ * left where it is, logged once, and the pass moves to the next row -- the
23
+ * row is not this helper's to settle, and aborting the pass over it would
24
+ * strand every other pending row under the losing epoch and block the
25
+ * adoption from ever completing. Any other decrypt failure still propagates.
20
26
  *
21
27
  * A replace the store SKIPS (`{ applied: false }` -- a local write bumped the
22
28
  * row's revision between the snapshot and the replace, so the row now holds a
@@ -1 +1 @@
1
- {"version":3,"file":"remint.d.ts","sourceRoot":"","sources":["../../src/sync/remint.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAU5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,KAAK,EACL,MAAM,EACN,YAAY,EACZ,MAAM,EACP,EAAE;IACD,KAAK,EAAE,SAAS,GAAG;QACjB,cAAc,EAAE,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAA;KACzD,CAAA;IACD,MAAM,EAAE,SAAS,CAAA;IACjB,YAAY,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxE,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA4DjD"}
1
+ {"version":3,"file":"remint.d.ts","sourceRoot":"","sources":["../../src/sync/remint.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAU5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,KAAK,EACL,MAAM,EACN,YAAY,EACZ,MAAM,EACP,EAAE;IACD,KAAK,EAAE,SAAS,GAAG;QACjB,cAAc,EAAE,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAA;KACzD,CAAA;IACD,MAAM,EAAE,SAAS,CAAA;IACjB,YAAY,EAAE,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxE,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA2EjD"}
@@ -29,7 +29,8 @@
29
29
  * re-encryption may therefore re-key the row (a content-derived id hashes
30
30
  * the ciphertext, so a re-mint mints a new id).
31
31
  */
32
- import { isUnknownEpochError } from '@interop/was-client/sync';
32
+ import { isIntegrityError, isUnknownEpochError } from '@interop/was-client/sync';
33
+ import { log } from '../log.js';
33
34
  /**
34
35
  * How many full re-mint passes are attempted before giving up. A pass that
35
36
  * ends with skipped rows (a local write bumped a row's revision between the
@@ -51,10 +52,16 @@ const MAX_REMINT_ATTEMPTS = 5;
51
52
  * and handed to {@link SyncStore.replacePending} -- which may re-key the row,
52
53
  * since the re-mint is a fresh encryption. Rows already readable under the
53
54
  * adopted descriptor, acked rows (`version > 0` -- they HAVE feed existence
54
- * and are never re-minted), and tombstones are left untouched. A decrypt
55
- * failure other than an unknown epoch propagates: an envelope that is
56
- * corrupt, rather than merely minted under a losing epoch, is not this
57
- * helper's to settle.
55
+ * and are never re-minted), and tombstones are left untouched.
56
+ *
57
+ * Two decrypt failures are told apart. An unknown epoch is the create-loss
58
+ * shape this helper exists for, and the row is re-minted. An addressing
59
+ * refusal (was-client's `IntegrityError`: the envelope is sealed for some
60
+ * other resource id, the shape a row minted by a pre-addressed writer has) is
61
+ * left where it is, logged once, and the pass moves to the next row -- the
62
+ * row is not this helper's to settle, and aborting the pass over it would
63
+ * strand every other pending row under the losing epoch and block the
64
+ * adoption from ever completing. Any other decrypt failure still propagates.
58
65
  *
59
66
  * A replace the store SKIPS (`{ applied: false }` -- a local write bumped the
60
67
  * row's revision between the snapshot and the replace, so the row now holds a
@@ -88,6 +95,10 @@ export async function remintPendingEnvelopes({ store, cipher, decryptStale, sign
88
95
  let pending;
89
96
  let reminted = 0;
90
97
  let skipped = [];
98
+ // Rows the cipher refused as sealed for another resource id. The refusal is
99
+ // deterministic over the same envelope, so a later attempt's pass skips such
100
+ // a row instead of paying for the decrypt (and warning) again.
101
+ const misaddressed = new Set();
91
102
  for (let attempt = 0; attempt < MAX_REMINT_ATTEMPTS; attempt += 1) {
92
103
  if (signal?.aborted) {
93
104
  break;
@@ -100,12 +111,23 @@ export async function remintPendingEnvelopes({ store, cipher, decryptStale, sign
100
111
  if (signal?.aborted) {
101
112
  break;
102
113
  }
114
+ if (misaddressed.has(row.id)) {
115
+ continue;
116
+ }
103
117
  const envelope = row.data;
104
118
  try {
105
- await cipher.decrypt({ envelope });
119
+ await cipher.decrypt({ id: row.id, envelope });
106
120
  continue;
107
121
  }
108
122
  catch (err) {
123
+ if (isIntegrityError(err)) {
124
+ misaddressed.add(row.id);
125
+ log.warn('Leaving a pending row sealed for another resource id', {
126
+ id: row.id,
127
+ err
128
+ });
129
+ continue;
130
+ }
109
131
  if (!isUnknownEpochError(err)) {
110
132
  throw err;
111
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remint.js","sourceRoot":"","sources":["../../src/sync/remint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remint.js","sourceRoot":"","sources":["../../src/sync/remint.ts"],"names":[],"mappings":"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"}