@ibgib/core-gib 0.1.59 → 0.1.61

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 (206) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/dist/common/other/graph-helper.d.mts.map +1 -1
  3. package/dist/common/other/graph-helper.mjs +7 -6
  4. package/dist/common/other/graph-helper.mjs.map +1 -1
  5. package/dist/keystone/keystone-config-builder.d.mts +1 -2
  6. package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
  7. package/dist/keystone/keystone-config-builder.mjs +4 -19
  8. package/dist/keystone/keystone-config-builder.mjs.map +1 -1
  9. package/dist/keystone/keystone-constants.d.mts +2 -0
  10. package/dist/keystone/keystone-constants.d.mts.map +1 -1
  11. package/dist/keystone/keystone-constants.mjs +2 -0
  12. package/dist/keystone/keystone-constants.mjs.map +1 -1
  13. package/dist/keystone/keystone-helpers.d.mts +5 -15
  14. package/dist/keystone/keystone-helpers.d.mts.map +1 -1
  15. package/dist/keystone/keystone-helpers.mjs +59 -73
  16. package/dist/keystone/keystone-helpers.mjs.map +1 -1
  17. package/dist/keystone/keystone-policy-types.d.mts +6 -4
  18. package/dist/keystone/keystone-policy-types.d.mts.map +1 -1
  19. package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
  20. package/dist/keystone/keystone-service-v1.mjs +4 -8
  21. package/dist/keystone/keystone-service-v1.mjs.map +1 -1
  22. package/dist/keystone/keystone-service-v1.respec.mjs +182 -33
  23. package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
  24. package/dist/keystone/keystone-types.d.mts +4 -11
  25. package/dist/keystone/keystone-types.d.mts.map +1 -1
  26. package/dist/keystone/policy/keystone-profile-builder.d.mts +25 -0
  27. package/dist/keystone/policy/keystone-profile-builder.d.mts.map +1 -0
  28. package/dist/keystone/policy/keystone-profile-builder.mjs +117 -0
  29. package/dist/keystone/policy/keystone-profile-builder.mjs.map +1 -0
  30. package/dist/keystone/policy/profiles/profile-high.json +84 -0
  31. package/dist/keystone/policy/profiles/profile-low.json +84 -0
  32. package/dist/keystone/policy/profiles/profile-medium.json +84 -0
  33. package/dist/keystone/policy/profiles/profile-session.json +84 -0
  34. package/dist/keystone/policy/profiles/profile-test.json +84 -0
  35. package/dist/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
  36. package/dist/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
  37. package/dist/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
  38. package/dist/keystone/policy/schemas/keystone.high.schema.json +26 -0
  39. package/dist/keystone/policy/schemas/keystone.low.schema.json +26 -0
  40. package/dist/keystone/policy/schemas/keystone.medium.schema.json +26 -0
  41. package/dist/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
  42. package/dist/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
  43. package/dist/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
  44. package/dist/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
  45. package/dist/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
  46. package/dist/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
  47. package/dist/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
  48. package/dist/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
  49. package/dist/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
  50. package/dist/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
  51. package/dist/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
  52. package/dist/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
  53. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts +8 -0
  54. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts.map +1 -0
  55. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs +582 -0
  56. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs.map +1 -0
  57. package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts +7 -0
  58. package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts.map +1 -0
  59. package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs +274 -0
  60. package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs.map +1 -0
  61. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts +8 -0
  62. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts.map +1 -0
  63. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs +322 -0
  64. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs.map +1 -0
  65. package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts +7 -0
  66. package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts.map +1 -0
  67. package/dist/sync/sync-conflict-text-merge.withid.respec.mjs +307 -0
  68. package/dist/sync/sync-conflict-text-merge.withid.respec.mjs.map +1 -0
  69. package/dist/sync/sync-innerspace-constants.withid.respec.d.mts +8 -0
  70. package/dist/sync/sync-innerspace-constants.withid.respec.d.mts.map +1 -0
  71. package/dist/sync/sync-innerspace-constants.withid.respec.mjs +233 -0
  72. package/dist/sync/sync-innerspace-constants.withid.respec.mjs.map +1 -0
  73. package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts +7 -0
  74. package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts.map +1 -0
  75. package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs +233 -0
  76. package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs.map +1 -0
  77. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts +7 -0
  78. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts.map +1 -0
  79. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs +225 -0
  80. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs.map +1 -0
  81. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
  82. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts +7 -0
  83. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts.map +1 -0
  84. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs +235 -0
  85. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs.map +1 -0
  86. package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts +7 -0
  87. package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts.map +1 -0
  88. package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs +211 -0
  89. package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs.map +1 -0
  90. package/dist/sync/sync-innerspace.withid.respec.d.mts +8 -0
  91. package/dist/sync/sync-innerspace.withid.respec.d.mts.map +1 -0
  92. package/dist/sync/sync-innerspace.withid.respec.mjs +260 -0
  93. package/dist/sync/sync-innerspace.withid.respec.mjs.map +1 -0
  94. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +1 -1
  95. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  96. package/dist/sync/sync-peer/sync-peer-types.d.mts +12 -1
  97. package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
  98. package/dist/sync/sync-peer/sync-peer-v1.d.mts +7 -0
  99. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  100. package/dist/sync/sync-peer/sync-peer-v1.mjs +43 -1
  101. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  102. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +2 -0
  103. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -1
  104. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +28 -9
  105. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -1
  106. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +1 -1
  107. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -1
  108. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +5 -3
  109. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -1
  110. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts +16 -0
  111. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -1
  112. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +223 -79
  113. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -1
  114. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
  115. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +41 -2
  116. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
  117. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +4 -0
  118. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
  119. package/dist/sync/sync-saga-coordinator.d.mts +6 -0
  120. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  121. package/dist/sync/sync-saga-coordinator.mjs +213 -137
  122. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  123. package/dist/sync/sync-withid.pingpong.respec.mjs +70 -2
  124. package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -1
  125. package/dist/timeline/timeline-api.d.mts.map +1 -1
  126. package/dist/timeline/timeline-api.mjs +1 -14
  127. package/dist/timeline/timeline-api.mjs.map +1 -1
  128. package/dist/witness/space/reconciliation-space/reconciliation-space-base.d.mts.map +1 -1
  129. package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs +0 -40
  130. package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs.map +1 -1
  131. package/dist/witness/space/reconciliation-space/reconciliation-space-helper.d.mts.map +1 -1
  132. package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs +6 -6
  133. package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs.map +1 -1
  134. package/ibgib-foundations.md +2 -1
  135. package/package.json +1 -1
  136. package/src/common/other/graph-helper.mts +7 -6
  137. package/src/keystone/README.md +19 -15
  138. package/src/keystone/docs/CRYPTANALYSIS.md +185 -0
  139. package/src/keystone/docs/architecture.md +24 -1
  140. package/src/keystone/docs/profiles.md +124 -0
  141. package/src/keystone/keystone-config-builder.mts +3 -21
  142. package/src/keystone/keystone-constants.mts +2 -0
  143. package/src/keystone/keystone-helpers.mts +74 -77
  144. package/src/keystone/keystone-policy-types.mts +6 -4
  145. package/src/keystone/keystone-service-v1.mts +4 -9
  146. package/src/keystone/keystone-service-v1.respec.mts +214 -32
  147. package/src/keystone/keystone-types.mts +5 -9
  148. package/src/keystone/policy/IMPLEMENTATION.md +60 -0
  149. package/src/keystone/policy/README.md +94 -0
  150. package/src/keystone/policy/keystone-profile-builder.mts +131 -0
  151. package/src/keystone/policy/profiles/profile-high.json +84 -0
  152. package/src/keystone/policy/profiles/profile-low.json +84 -0
  153. package/src/keystone/policy/profiles/profile-medium.json +84 -0
  154. package/src/keystone/policy/profiles/profile-session.json +84 -0
  155. package/src/keystone/policy/profiles/profile-test.json +84 -0
  156. package/src/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
  157. package/src/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
  158. package/src/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
  159. package/src/keystone/policy/schemas/keystone.high.schema.json +26 -0
  160. package/src/keystone/policy/schemas/keystone.low.schema.json +26 -0
  161. package/src/keystone/policy/schemas/keystone.medium.schema.json +26 -0
  162. package/src/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
  163. package/src/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
  164. package/src/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
  165. package/src/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
  166. package/src/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
  167. package/src/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
  168. package/src/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
  169. package/src/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
  170. package/src/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
  171. package/src/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
  172. package/src/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
  173. package/src/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
  174. package/src/sync/docs/security-3b.md +92 -0
  175. package/src/sync/docs/security.md +139 -38
  176. package/src/sync/sync-conflict-adv-multitimelines.withid.respec.mts +706 -0
  177. package/src/sync/sync-conflict-basic-divergence.withid.respec.mts +321 -0
  178. package/src/sync/sync-conflict-basic-multitimelines.withid.respec.mts +374 -0
  179. package/src/sync/sync-conflict-text-merge.withid.respec.mts +347 -0
  180. package/src/sync/sync-innerspace-constants.withid.respec.mts +264 -0
  181. package/src/sync/sync-innerspace-deep-updates.withid.respec.mts +272 -0
  182. package/src/sync/sync-innerspace-dest-ahead.withid.respec.mts +266 -0
  183. package/src/sync/sync-innerspace-multiple-timelines.respec.mts +0 -1
  184. package/src/sync/sync-innerspace-multiple-timelines.withid.respec.mts +273 -0
  185. package/src/sync/sync-innerspace-partial-update.withid.respec.mts +249 -0
  186. package/src/sync/sync-innerspace.withid.respec.mts +265 -0
  187. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +1 -1
  188. package/src/sync/sync-peer/sync-peer-types.mts +11 -1
  189. package/src/sync/sync-peer/sync-peer-v1.mts +47 -1
  190. package/src/sync/sync-peer/sync-peer-websocket/README.md +42 -0
  191. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +26 -9
  192. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +5 -3
  193. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +242 -78
  194. package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +46 -4
  195. package/src/sync/sync-saga-context/sync-saga-context-types.mts +5 -0
  196. package/src/sync/sync-saga-coordinator.mts +221 -137
  197. package/src/sync/sync-withid.pingpong.respec.mts +76 -3
  198. package/src/timeline/timeline-api.mts +1 -15
  199. package/src/timeline/timeline-api.respec.mts +3 -3
  200. package/src/witness/space/reconciliation-space/reconciliation-space-base.mts +0 -46
  201. package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts +6 -5
  202. package/tsconfig.json +6 -1
  203. package/src/keystone/keystone-policy.schema.json +0 -51
  204. package/src/sync/docs/ping_pong_plan.md +0 -147
  205. package/src/witness/space/reconciliation-space/reconciliation-space-base.mts.OLD.md +0 -884
  206. package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts.OLD.md +0 -125
@@ -8,7 +8,7 @@ import { putInSpace, getLatestAddrs, getFromSpace, registerNewIbGib } from "../w
8
8
  import { SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN, SyncConflictStrategy, SYNC_CONFLICT_STRATEGY_VALID_VALUES, } from "./sync-constants.mjs";
9
9
  import { appendToTimeline, createTimeline, getHistory, getHistoryAddrs } from "../timeline/timeline-api.mjs";
10
10
  import { SyncMode, } from "./sync-types.mjs";
11
- import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory, getAllOrphanedAddresses, getFinalConflictsInfo } from "./sync-helpers.mjs";
11
+ import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory, getAllOrphanedAddresses, getFinalConflictsInfo, getSyncSagaFrameDependencyGraph } from "./sync-helpers.mjs";
12
12
  import { getDeltaDependencyGraph, getDependencyGraph } from "../common/other/graph-helper.mjs";
13
13
  import { getSyncSagaMessageIb } from "./sync-saga-message/sync-saga-message-helpers.mjs";
14
14
  import { SYNC_SAGA_MSG_ATOM } from "./sync-saga-message/sync-saga-message-constants.mjs";
@@ -324,141 +324,155 @@ export class SyncSagaCoordinator {
324
324
  },
325
325
  }));
326
326
  // #endregion set up peer observable for any domainPayloadsMap
327
- // ...create/compose the Request Context itself...
328
- const requestCtx = await this.createSyncSagaContext({
329
- sagaFrame: currentFrame,
330
- /**
331
- * init frame: empty
332
- * ack frame: possible push offers
333
- * delta frame: requested ibgibs or commit offer
334
- * commit frame: empty
335
- */
336
- payloadIbGibsDomain: nextDomainIbGibs,
337
- localSpace,
338
- metaspace,
339
- sessionIdentityAddr: peer.currentSessionIdentityAddr,
340
- peer,
341
- });
342
- // #region Log what we're sending
343
- if (logalotControlDomain) {
344
- const domainAddrs = nextDomainIbGibs.map(p => getIbGibAddr({ ibGib: p }));
345
- console.log(`${lc}${lcControlDomain} SENDER TRANSMIT -> peer.witness (I: 5b0081803698770f0bf64992220b312)`);
346
- console.log(`${lc}${lcControlDomain} Context: ${getIbGibAddr({ ibGib: requestCtx })}`);
347
- console.log(`${lc}${lcControlDomain} Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
348
- console.log(`${lc}${lcControlDomain} DOMAIN Payloads (${domainAddrs.length}): ${domainAddrs.join(', ') || '(none)'}`);
349
- }
350
- // #endregion Log what we're sending
351
- // update our saga listeners...
352
- // if (logalot) { console.log(`${lc} transmitting... requestCtx: ${pretty(requestCtx)} (I: 8cf20817c66899abdb1e76df50356826)`); }
353
- updates$.next(requestCtx); // spins off for saga UI updates
354
- // ...And send the context.
355
- peer.setOptionalOpts({ localSpace, localTempSpace: tempSpace, });
356
- const responseCtx = await peer.witness(requestCtx);
357
- // the send returned, but a peer can return a falsy responseCtx, if
358
- // we just sent a commit to them and they're done. If so, there will
359
- // necessarily be no payload to wait to receive
360
- if (!responseCtx) {
361
- if (currentFrame) {
362
- // Check for Commit (Peer silence expected)
363
- const msg = await getSyncSagaMessageFromFrame({ frameIbGib: currentFrame, space: localSpace });
364
- if (msg?.data?.stage === SyncStage.commit) {
365
- if (logalot) {
366
- console.log(`${lc} Sender sent Commit. Peer returned no response. Saga Complete. (I: 26f9ee073858ca78b8284753368b5226)`);
327
+ try {
328
+ // ...create/compose the Request Context itself...
329
+ const requestCtx = await this.createSyncSagaContext({
330
+ sagaFrame: currentFrame,
331
+ /**
332
+ * init frame: empty
333
+ * ack frame: possible push offers
334
+ * delta frame: requested ibgibs or commit offer
335
+ * commit frame: empty
336
+ */
337
+ payloadIbGibsDomain: nextDomainIbGibs,
338
+ localSpace,
339
+ metaspace,
340
+ sessionIdentityAddr: peer.currentSessionIdentityAddr,
341
+ peer,
342
+ });
343
+ // #region Log what we're sending
344
+ if (logalotControlDomain) {
345
+ const domainAddrs = nextDomainIbGibs.map(p => getIbGibAddr({ ibGib: p }));
346
+ console.log(`${lc}${lcControlDomain} SENDER TRANSMIT -> peer.witness (I: 5b0081803698770f0bf64992220b312)`);
347
+ console.log(`${lc}${lcControlDomain} Context: ${getIbGibAddr({ ibGib: requestCtx })}`);
348
+ console.log(`${lc}${lcControlDomain} Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
349
+ console.log(`${lc}${lcControlDomain} DOMAIN Payloads (${domainAddrs.length}): ${domainAddrs.join(', ') || '(none)'}`);
350
+ }
351
+ // #endregion Log what we're sending
352
+ // update our saga listeners...
353
+ // if (logalot) { console.log(`${lc} transmitting... requestCtx: ${pretty(requestCtx)} (I: 8cf20817c66899abdb1e76df50356826)`); }
354
+ updates$.next(requestCtx); // spins off for saga UI updates
355
+ // ...And send the context.
356
+ peer.setOptionalOpts({ localSpace, localTempSpace: tempSpace, });
357
+ const responseCtx = await peer.witness(requestCtx);
358
+ // the send returned, but a peer can return a falsy responseCtx, if
359
+ // we just sent a commit to them and they're done. If so, there will
360
+ // necessarily be no payload to wait to receive
361
+ if (!responseCtx) {
362
+ if (currentFrame) {
363
+ // Check for Commit (Peer silence expected)
364
+ const msg = await getSyncSagaMessageFromFrame({ frameIbGib: currentFrame, space: localSpace });
365
+ if (msg?.data?.stage === SyncStage.commit) {
366
+ if (logalot) {
367
+ console.log(`${lc} Sender sent Commit. Peer returned no response. Saga Complete. (I: 26f9ee073858ca78b8284753368b5226)`);
368
+ }
369
+ currentFrame = null;
370
+ break;
371
+ }
372
+ else {
373
+ throw new Error(`(UNEXPECTED) responseCtx falsy and currentFrame truthy, but we're not in the commit stage? This may be expected ultimately, but atow I am not seeing this as being expected. (E: cc34498962bd370deeff351fac939f26)`);
367
374
  }
368
- currentFrame = null;
369
- break;
370
375
  }
371
376
  else {
372
- throw new Error(`(UNEXPECTED) responseCtx falsy and currentFrame truthy, but we're not in the commit stage? This may be expected ultimately, but atow I am not seeing this as being expected. (E: cc34498962bd370deeff351fac939f26)`);
377
+ throw new Error(`(UNEXPECTED) no response and currentFrame falsy? (E: 8d1085ea2f28cfc3f9c922649864a826)`);
373
378
  }
374
379
  }
375
- else {
376
- throw new Error(`(UNEXPECTED) no response and currentFrame falsy? (E: 8d1085ea2f28cfc3f9c922649864a826)`);
377
- }
378
- }
379
- // at this point, we did indeed receive a response to analyze. BUT!
380
- // we have only necessarily received the response context ibgib.
381
- // if there were payloads expected to be transferred, they may not
382
- // be done yet.
383
- if (!responseCtx.data) {
384
- throw new Error(`(UNEXPECTED) responseCtx.data falsy? (E: a969992bae53ab18a827ec58aec15826)`);
385
- }
386
- updates$.next(responseCtx); // spins off for saga UI updating
387
- // immediately validate context/saga frame (but not payloads because
388
- // we may not have those yet)
389
- const contextAndSagaFrameValidationErrors = await validateContextAndSagaFrame({ context: responseCtx });
390
- if (contextAndSagaFrameValidationErrors.length > 0) {
391
- throw new Error(`contextAndSagaFrameValidationErrors: ${contextAndSagaFrameValidationErrors} (E: 6eebe8e7fa437c00a8cde3ada3c66826)`);
392
- }
393
- // Extract expected domain addresses from response context
394
- const responsePayloadAddrsDomain = responseCtx.data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] || [];
395
- // Poll for them if needed. see above jsdocs for domainPayloadsMap
396
- if (responsePayloadAddrsDomain.length > 0) {
397
- responseCtx.payloadIbGibsDomain = await this.pollForDomainPayloads({
398
- expectedAddrs: responsePayloadAddrsDomain,
399
- pollIntervalMs: 20, // relatively arbitrary right now
400
- domainPayloadsMap,
401
- tempSpace,
380
+ // at this point, we did indeed receive a response to analyze. BUT!
381
+ // we have only necessarily received the response context ibgib.
382
+ // if there were payloads expected to be transferred, they may not
383
+ // be done yet.
384
+ if (!responseCtx.data) {
385
+ throw new Error(`(UNEXPECTED) responseCtx.data falsy? (E: a969992bae53ab18a827ec58aec15826)`);
386
+ }
387
+ updates$.next(responseCtx); // spins off for saga UI updating
388
+ // immediately validate context/saga frame (but not payloads because
389
+ // we may not have those yet)
390
+ const contextAndSagaFrameValidationErrors = await validateContextAndSagaFrame({ context: responseCtx });
391
+ if (contextAndSagaFrameValidationErrors.length > 0) {
392
+ throw new Error(`contextAndSagaFrameValidationErrors: ${contextAndSagaFrameValidationErrors} (E: 6eebe8e7fa437c00a8cde3ada3c66826)`);
393
+ }
394
+ // Turn-by-turn continuation & identity checks
395
+ const returnContextErrors = await this.validateReturnContext({
396
+ requestCtx,
397
+ responseCtx,
398
+ localSpace,
402
399
  });
403
- }
404
- // #region Log what we received back
405
- if (!responseCtx.sagaFrame) {
406
- throw new Error(`(UNEXPECTED) responseCtx.sagaFrame falsy? the Peer should have set this when it got the response back from the remote. (E: e650adadf9a2063ec6764a1e31d3d826)`);
407
- }
408
- if (logalotControlDomain) {
409
- const responseControlAddrs = responseCtx.data?.['@payloadAddrsControl'] || [];
410
- console.log(`${lc}${lcControlDomain} SENDER RECEIVED <- peer.witness (I: 3dc76a9744d89a4fc3e2f076c2be4826)`);
411
- console.log(`${lc}${lcControlDomain} Response Context: ${getIbGibAddr({ ibGib: responseCtx })}`);
412
- console.log(`${lc}${lcControlDomain} Response Saga Frame: ${getIbGibAddr({ ibGib: responseCtx.sagaFrame })}`);
413
- console.log(`${lc}${lcControlDomain} CONTROL Payloads (${responseControlAddrs.length}): ${responseControlAddrs.join(', ') || '(none)'}`);
414
- console.log(`${lc}${lcControlDomain} DOMAIN Payloads (${responsePayloadAddrsDomain.length}): ${responsePayloadAddrsDomain.join(', ') || '(none)'}`);
415
- }
416
- // #endregion Log what we received back
417
- // at this point, we have received the context AND **all** of the
418
- // domain payloads (if applicable), so we are ready to do the next
419
- // iteration in the saga loop
420
- // this is the part that drives the FSM forward, i.e., when we
421
- // evolve the sync saga ibgib itself to the next frame if we aren't
422
- // finished/errored out.
423
- const contextResult = await this.handleResponseSagaContext({
424
- sagaContext: responseCtx,
425
- initDomainGraph,
426
- mySpace: localSpace,
427
- myTempSpace: tempSpace,
428
- metaspace,
429
- });
430
- if (!contextResult) {
431
- // should this ever hit?
432
- console.error(`${lc} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
433
- break;
434
- }
435
- else if (contextResult.nextFrameInfo?.sagaComplete) {
436
- if (logalot) {
437
- console.log(`${lc} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
400
+ if (returnContextErrors.length > 0) {
401
+ throw new Error(`validateReturnContext errors: ${returnContextErrors.join(', ')} (E: cb8a023b9d0728cceb09fa3da0bb8226)`);
402
+ }
403
+ // Extract expected domain addresses from response context
404
+ const responsePayloadAddrsDomain = responseCtx.data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] || [];
405
+ // Poll for them if needed. see above jsdocs for domainPayloadsMap
406
+ if (responsePayloadAddrsDomain.length > 0) {
407
+ responseCtx.payloadIbGibsDomain = await this.pollForDomainPayloads({
408
+ expectedAddrs: responsePayloadAddrsDomain,
409
+ pollIntervalMs: 20, // relatively arbitrary right now
410
+ domainPayloadsMap,
411
+ tempSpace,
412
+ });
438
413
  }
439
- break;
440
- }
441
- // #region error conditions throw
442
- if (contextResult.errorMsg) {
443
- throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: c948e81d513b2a0eb8b8afa878edc626)`);
414
+ // #region Log what we received back
415
+ if (!responseCtx.sagaFrame) {
416
+ throw new Error(`(UNEXPECTED) responseCtx.sagaFrame falsy? the Peer should have set this when it got the response back from the remote. (E: e650adadf9a2063ec6764a1e31d3d826)`);
417
+ }
418
+ if (logalotControlDomain) {
419
+ const responseControlAddrs = responseCtx.data?.['@payloadAddrsControl'] || [];
420
+ console.log(`${lc}${lcControlDomain} SENDER RECEIVED <- peer.witness (I: 3dc76a9744d89a4fc3e2f076c2be4826)`);
421
+ console.log(`${lc}${lcControlDomain} Response Context: ${getIbGibAddr({ ibGib: responseCtx })}`);
422
+ console.log(`${lc}${lcControlDomain} Response Saga Frame: ${getIbGibAddr({ ibGib: responseCtx.sagaFrame })}`);
423
+ console.log(`${lc}${lcControlDomain} CONTROL Payloads (${responseControlAddrs.length}): ${responseControlAddrs.join(', ') || '(none)'}`);
424
+ console.log(`${lc}${lcControlDomain} DOMAIN Payloads (${responsePayloadAddrsDomain.length}): ${responsePayloadAddrsDomain.join(', ') || '(none)'}`);
425
+ }
426
+ // #endregion Log what we received back
427
+ // at this point, we have received the context AND **all** of the
428
+ // domain payloads (if applicable), so we are ready to do the next
429
+ // iteration in the saga loop
430
+ // this is the part that drives the FSM forward, i.e., when we
431
+ // evolve the sync saga ibgib itself to the next frame if we aren't
432
+ // finished/errored out.
433
+ const contextResult = await this.handleResponseSagaContext({
434
+ sagaContext: responseCtx,
435
+ initDomainGraph,
436
+ mySpace: localSpace,
437
+ myTempSpace: tempSpace,
438
+ metaspace,
439
+ });
440
+ if (!contextResult) {
441
+ // should this ever hit?
442
+ console.error(`${lc} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
443
+ break;
444
+ }
445
+ else if (contextResult.nextFrameInfo?.sagaComplete) {
446
+ if (logalot) {
447
+ console.log(`${lc} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
448
+ }
449
+ break;
450
+ }
451
+ // #region error conditions throw
452
+ if (contextResult.errorMsg) {
453
+ throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: c948e81d513b2a0eb8b8afa878edc626)`);
454
+ }
455
+ else if (!contextResult.nextFrameInfo) {
456
+ throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
457
+ }
458
+ // #endregion error conditions throw
459
+ // we have another frame to process and send out, with possibly
460
+ // payload domain ibgibs as well
461
+ const { frame, payloadIbGibsDomain, } = contextResult.nextFrameInfo;
462
+ currentFrame = frame;
463
+ nextDomainIbGibs = [...(payloadIbGibsDomain || [])];
464
+ // #region Log handler output for next iteration
465
+ if (logalotControlDomain) {
466
+ const handlerDomainAddrs = nextDomainIbGibs.map(p => getIbGibAddr({ ibGib: p }));
467
+ console.log(`${lc}${lcControlDomain} HANDLER RESULT -> next iteration (I: 6b0d88c4c28857ccd812381515bd7826)`);
468
+ console.log(`${lc}${lcControlDomain} Next Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
469
+ console.log(`${lc}${lcControlDomain} DOMAIN for next (${handlerDomainAddrs.length}): ${handlerDomainAddrs.join(', ') || '(none)'}`);
470
+ }
471
+ // #endregion Log handler output for next iteration
444
472
  }
445
- else if (!contextResult.nextFrameInfo) {
446
- throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
473
+ finally {
474
+ await subscription.unsubscribe();
447
475
  }
448
- // #endregion error conditions throw
449
- // we have another frame to process and send out, with possibly
450
- // payload domain ibgibs as well
451
- const { frame, payloadIbGibsDomain, } = contextResult.nextFrameInfo;
452
- currentFrame = frame;
453
- nextDomainIbGibs = [...(payloadIbGibsDomain || [])];
454
- // #region Log handler output for next iteration
455
- if (logalotControlDomain) {
456
- const handlerDomainAddrs = nextDomainIbGibs.map(p => getIbGibAddr({ ibGib: p }));
457
- console.log(`${lc}${lcControlDomain} HANDLER RESULT -> next iteration (I: 6b0d88c4c28857ccd812381515bd7826)`);
458
- console.log(`${lc}${lcControlDomain} Next Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
459
- console.log(`${lc}${lcControlDomain} DOMAIN for next (${handlerDomainAddrs.length}): ${handlerDomainAddrs.join(', ') || '(none)'}`);
460
- }
461
- // #endregion Log handler output for next iteration
462
476
  }
463
477
  }
464
478
  /**
@@ -544,6 +558,14 @@ export class SyncSagaCoordinator {
544
558
  });
545
559
  // Attach actual ibgibs for transport
546
560
  contextIbGib.sagaFrame = sagaFrame;
561
+ const { msgStones } = await getSyncSagaFrameDependencyGraph({
562
+ sagaIbGib: sagaFrame,
563
+ localSpace: localSpace,
564
+ });
565
+ if (msgStones.length !== 1) {
566
+ throw new Error(`(UNEXPECTED) msgStones.length !== 1 inside createSyncSagaContext? (E: a98165cf46ab4e82b7bd5e45a273b826)`);
567
+ }
568
+ contextIbGib.sagaFrameMsg = msgStones[0];
547
569
  if (payloadIbGibsDomain && payloadIbGibsDomain.length > 0) {
548
570
  contextIbGib.payloadIbGibsDomain = payloadIbGibsDomain;
549
571
  }
@@ -707,6 +729,45 @@ export class SyncSagaCoordinator {
707
729
  }
708
730
  }
709
731
  }
732
+ /**
733
+ * Validates that the return context received from a peer is a valid
734
+ * continuation of the outbound context and that the session identity
735
+ * is consistent.
736
+ */
737
+ async validateReturnContext({ requestCtx, responseCtx, localSpace, }) {
738
+ const lc = `${this.lc}[${this.validateReturnContext.name}]`;
739
+ const errors = [];
740
+ try {
741
+ // 1. Verify saga frame continuation
742
+ if (requestCtx.sagaFrame && responseCtx.sagaFrame) {
743
+ const requestFrameAddr = getIbGibAddr({ ibGib: requestCtx.sagaFrame });
744
+ const responseFrameAddr = getIbGibAddr({ ibGib: responseCtx.sagaFrame });
745
+ const isContinuation = await isPastFrame({
746
+ olderAddr: requestFrameAddr,
747
+ newerAddr: responseFrameAddr,
748
+ space: localSpace,
749
+ });
750
+ if (!isContinuation) {
751
+ errors.push(`Response saga frame (${responseFrameAddr}) is not a valid continuation of request saga frame (${requestFrameAddr}). (E: 2c85e8d97318ff24ac8a02bd3a068226)`);
752
+ }
753
+ }
754
+ else {
755
+ errors.push(`Missing sagaFrame on requestCtx or responseCtx. (E: b65c68ff891000ddca8d22384a088226)`);
756
+ }
757
+ // 2. Verify session identity has not changed
758
+ const expectedSessionIdAddr = requestCtx.signedSessionIdentity ?
759
+ getIbGibAddr({ ibGib: requestCtx.signedSessionIdentity }) :
760
+ requestCtx.rel8ns?.sessionIdentity?.[0];
761
+ const responseSessionIdAddr = responseCtx.rel8ns?.sessionIdentity?.[0];
762
+ if (expectedSessionIdAddr !== responseSessionIdAddr) {
763
+ errors.push(`Session identity mismatch. Expected ${expectedSessionIdAddr}, got ${responseSessionIdAddr}. (E: ab98716bca88d2243cc822187768226)`);
764
+ }
765
+ }
766
+ catch (error) {
767
+ errors.push(`Error during validateReturnContext: ${extractErrorMsg(error)} (E: da878e1239aa88ee27bdfca005c28226)`);
768
+ }
769
+ return errors;
770
+ }
710
771
  /**
711
772
  * Helper to poll for streaming domain payloads and put them in the
712
773
  * local {@link tempSpace}.
@@ -720,7 +781,8 @@ export class SyncSagaCoordinator {
720
781
  console.log(`${lc} starting... (I: 26dce86bfca572939885798802d6e926)`);
721
782
  }
722
783
  let resultDomainPayloads = [];
723
- let pending = [...expectedAddrs];
784
+ const uniqueExpectedAddrs = [...new Set(expectedAddrs)];
785
+ let pending = [...uniqueExpectedAddrs];
724
786
  const start = Date.now();
725
787
  /**
726
788
  * This needs
@@ -750,8 +812,8 @@ export class SyncSagaCoordinator {
750
812
  await delay(pollIntervalMs);
751
813
  }
752
814
  }
753
- if (expectedAddrs.length !== resultDomainPayloads.length) {
754
- throw new Error(`(UNEXPECTED) expectedAddrs.length !== resultDomainPayloads.length? at this point, we expect all of the payload ibgibs to have been received. (E: 03749a7478c4b8b28bfc86951887a826)`);
815
+ if (uniqueExpectedAddrs.length !== resultDomainPayloads.length) {
816
+ throw new Error(`(UNEXPECTED) uniqueExpectedAddrs.length !== resultDomainPayloads.length? at this point, we expect all of the payload ibgibs to have been received. (E: 03749a7478c4b8b28bfc86951887a826)`);
755
817
  }
756
818
  return resultDomainPayloads;
757
819
  }
@@ -1322,12 +1384,11 @@ export class SyncSagaCoordinator {
1322
1384
  * end will have to do the actual merging (assuming feasability).
1323
1385
  */
1324
1386
  const outgoingPayloadIbGibsDomain_conflicts = [];
1387
+ const activeConflicts = [];
1325
1388
  if (conflicts.length > 0) {
1326
1389
  if (logalot) {
1327
1390
  console.log(`${lc} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
1328
1391
  }
1329
- // we will need to resolve conflicts, so no commit yet
1330
- proposeCommit = false;
1331
1392
  for (const conflict of conflicts) {
1332
1393
  const { receiverTipAddr, reason, senderTipAddr,
1333
1394
  // latestCommonFrameAddr, // to be determined in this handler
@@ -1389,13 +1450,28 @@ export class SyncSagaCoordinator {
1389
1450
  const deltaPayloadIbGib = deltaGraph[deltaPayloadAddr];
1390
1451
  outgoingPayloadIbGibsDomain_conflicts.push(deltaPayloadIbGib);
1391
1452
  });
1392
- if (conflict.accretivePayloadAddrs) {
1393
- throw new Error(`(UNEXPECTED) conflict.accretivePayloadAddrs already truthy? This is expected to be falsy at this point in the sync. (E: 6b6b1846779867849cbde208f4374326)`);
1453
+ const isFastForward = latestCommonFrameAddr === receiverTipAddr;
1454
+ if (isFastForward) {
1455
+ if (logalot) {
1456
+ console.log(`${lc} [CONFLICT DEBUG] TJP ${tjpAddr}: Fast-forward detected (receiver behind sender). Excluding from active conflicts and sending delta payload.`);
1457
+ }
1458
+ }
1459
+ else {
1460
+ if (conflict.accretivePayloadAddrs) {
1461
+ throw new Error(`(UNEXPECTED) conflict.accretivePayloadAddrs already truthy? This is expected to be falsy at this point in the sync. (E: 6b6b1846779867849cbde208f4374326)`);
1462
+ }
1463
+ conflict.accretivePayloadAddrs = accretivePayloadAddrs;
1464
+ activeConflicts.push(conflict);
1394
1465
  }
1395
- conflict.accretivePayloadAddrs = accretivePayloadAddrs;
1466
+ }
1467
+ if (activeConflicts.length > 0) {
1468
+ proposeCommit = false;
1469
+ }
1470
+ else {
1471
+ proposeCommit = true;
1396
1472
  }
1397
1473
  if (logalot) {
1398
- console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingPayloadIbGibsDomain_conflicts.length (total outgoing payload ibgibs for ALL conflicts): ${outgoingPayloadIbGibsDomain_conflicts.length}`);
1474
+ console.log(`${lc} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. Active (divergent) conflicts: ${activeConflicts.length}. outgoingPayloadIbGibsDomain_conflicts.length (total outgoing payload ibgibs for ALL conflicts): ${outgoingPayloadIbGibsDomain_conflicts.length}`);
1399
1475
  }
1400
1476
  }
1401
1477
  else {
@@ -1434,7 +1510,7 @@ export class SyncSagaCoordinator {
1434
1510
  /**
1435
1511
  * these are the modified conflicts with additional information.
1436
1512
  */
1437
- conflicts,
1513
+ conflicts: activeConflicts,
1438
1514
  /**
1439
1515
  * we're sending these domain ibgibs as payload (they were
1440
1516
  * requested by receiver and/or they are being sent as delta