@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
@@ -11,6 +11,7 @@ import { KeystoneStrategyFactory } from '../../../../keystone/strategy/keystone-
11
11
  import { deriveSessionSecret } from '../../../sync-helpers.mjs';
12
12
  import { SyncPeer_V1 } from '../../sync-peer-v1.mjs';
13
13
  import { SyncSagaContextIbGib_V1 } from '../../../sync-saga-context/sync-saga-context-types.mjs';
14
+ import { validateContextAndSagaFrame } from '../../../sync-saga-context/sync-saga-context-helpers.mjs';
14
15
  import { GLOBAL_LOG_A_LOT } from '../../../../core-constants.mjs';
15
16
  import {
16
17
  ConnectSyncPeerWebSocketSenderOpts,
@@ -23,7 +24,17 @@ import {
23
24
  SESSION_KEYSTONE_POLICY,
24
25
  getConnectChallenge
25
26
  } from '../sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
26
- import { SyncWebSocketMsgType } from '../sync-peer-websocket-constants.mjs';
27
+ import { SyncWebSocketMsgType, isSyncWebSocketMsgType, SYNC_WEB_SOCKET_MSG_TYPE_VALID_VALUES } from '../sync-peer-websocket-constants.mjs';
28
+ import { toDto } from '../../../../common/other/ibgib-helper.mjs';
29
+ import { putInSpace, registerNewIbGib } from '../../../../witness/space/space-helper.mjs';
30
+
31
+ /**
32
+ * helper in creating compile-time safety that we're handling all message types.
33
+ */
34
+ function assertUnreachable(x: never): never {
35
+ throw new Error(`Unhandled message type: ${x} (E: e928a3f82cd7469a98ef1bc248a3f826)`);
36
+ }
37
+
27
38
 
28
39
  const logalot = GLOBAL_LOG_A_LOT || true;
29
40
 
@@ -51,6 +62,7 @@ export class SyncPeerWebSocketSender_V1
51
62
  protected activeResolve?: (value: SyncSagaContextIbGib_V1 | undefined) => void;
52
63
  protected activeReject?: (reason: any) => void;
53
64
  protected pendingPayloadsToSend: IbGib_V1[] = [];
65
+ protected handshakeMessageListener?: (event: MessageEvent) => Promise<void>;
54
66
 
55
67
  constructor(
56
68
  initialData: SyncPeerWebSocketSenderData_V1,
@@ -188,63 +200,64 @@ export class SyncPeerWebSocketSender_V1
188
200
  if (logalot) { console.log(`${lc} WebSocket opened. Awaiting challenge...`); }
189
201
  });
190
202
 
191
- ws.addEventListener('message', async (ev) => {
203
+ this.handshakeMessageListener = async (ev) => {
192
204
  try {
193
205
  const msg = JSON.parse(ev.data);
194
- if (logalot) { console.log(`${lc} received frame: ${msg.type}`); }
195
-
196
- if (msg.type === SyncWebSocketMsgType.auth_challenge_init) {
197
- ws.send(JSON.stringify({
198
- type: SyncWebSocketMsgType.auth_init,
199
- sAddr: targetSAddr
200
- }));
201
- } else if (msg.type === SyncWebSocketMsgType.auth_challenge) {
202
- const { challengeUuid, demandedIds } = msg;
203
- if (logalot) { console.log(`${lc} solving demanded challenges: ${demandedIds.join(', ')}`); }
204
-
205
- const keystoneService = new KeystoneService_V1();
206
- const proofFrame = await keystoneService.sign({
207
- latestKeystone: sessionS,
208
- masterSecret: sessionSecret,
209
- poolId: SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID,
210
- requiredChallengeIds: demandedIds,
211
- claim: {
212
- verb: SESSION_KEYSTONE_POLICY.CONNECT_POOL.VERB,
213
- target: challengeUuid
214
- },
215
- metaspace: localMetaspace,
216
- space: localSpace
217
- });
218
-
219
- ws.send(JSON.stringify({
220
- type: SyncWebSocketMsgType.auth_proof,
221
- proofFrame
222
- }));
223
- } else if (msg.type === SyncWebSocketMsgType.auth_ok) {
224
- if (logalot) { console.log(`${lc} WebSocket connect SUCCESS!`); }
225
- isResolved = true;
226
-
227
- // Setup persistent runtime listeners
228
- ws.removeEventListener('message', (() => { }) as any);
229
- ws.addEventListener('message', (event) => this.handleRuntimeMessage(event));
230
-
231
- resolve();
232
- } else if (msg.type === SyncWebSocketMsgType.auth_fail) {
233
- reject(new Error(`Connect failed: ${msg.message}`));
206
+ if (logalot) { console.log(`${lc} received handshake frame: ${msg.type}`); }
207
+
208
+ const msgType = msg.type;
209
+ if (!isSyncWebSocketMsgType(msgType)) {
210
+ const validTypes = SYNC_WEB_SOCKET_MSG_TYPE_VALID_VALUES.join(', ');
211
+ throw new Error(`Unknown message type '${msgType}' received during connection handshake. Valid types are: ${validTypes} (E: e983271bc84f46928e4695be2409826)`);
212
+ }
213
+
214
+ switch (msgType) {
215
+ case SyncWebSocketMsgType.auth_challenge_init:
216
+ await this.handleHandshakeAuthChallengeInit(ws, targetSAddr);
217
+ break;
218
+ case SyncWebSocketMsgType.auth_challenge:
219
+ await this.handleHandshakeAuthChallenge(ws, msg, sessionS, sessionSecret);
220
+ break;
221
+ case SyncWebSocketMsgType.auth_ok:
222
+ isResolved = true;
223
+ this.handleHandshakeAuthOk(ws, resolve);
224
+ break;
225
+ case SyncWebSocketMsgType.auth_fail:
226
+ this.handleHandshakeAuthFail(msg, reject);
227
+ break;
228
+ case SyncWebSocketMsgType.sync_error:
229
+ this.handleHandshakeSyncError(msg, reject);
230
+ break;
231
+ // Protocol violations / unexpected messages during connection handshake
232
+ case SyncWebSocketMsgType.auth_init:
233
+ case SyncWebSocketMsgType.auth_proof:
234
+ case SyncWebSocketMsgType.sync_frame:
235
+ case SyncWebSocketMsgType.sync_frame_response:
236
+ case SyncWebSocketMsgType.sync_frame_authenticated:
237
+ case SyncWebSocketMsgType.sync_frame_response_authenticated:
238
+ case SyncWebSocketMsgType.domain_payload:
239
+ throw new Error(`Unexpected message type '${msgType}' during connection handshake (E: e3f80c68ab2a46c2b1858c8a1e2f8926)`);
240
+ default:
241
+ assertUnreachable(msgType);
234
242
  }
235
243
  } catch (error) {
244
+ console.error(`${lc} ${extractErrorMsg(error)}`);
236
245
  reject(error);
237
246
  }
238
- });
247
+ };
248
+
249
+ ws.addEventListener('message', this.handshakeMessageListener);
239
250
 
240
251
  ws.addEventListener('close', (event) => {
241
252
  if (!isResolved) {
253
+ this.disconnect();
242
254
  reject(new Error(`WebSocket closed before connect completed (code: ${event.code})`));
243
255
  }
244
256
  });
245
257
 
246
258
  ws.addEventListener('error', (err) => {
247
259
  if (!isResolved) {
260
+ this.disconnect();
248
261
  reject(new Error(`WebSocket connection error`));
249
262
  }
250
263
  });
@@ -256,6 +269,36 @@ export class SyncPeerWebSocketSender_V1
256
269
  }
257
270
  }
258
271
 
272
+ /**
273
+ * Cleanly closes the socket and removes the handshake message listener.
274
+ *
275
+ * LOGS AND SWALLOWS ERRORS, DOES NOT THROW
276
+ */
277
+ public disconnect(): void {
278
+ const lc = `${this.lc}[${this.disconnect.name}]`;
279
+ try {
280
+ if (logalot) { console.log(`${lc} starting... (I: 35c4b85fca0c6e9d042f5ff87cde3826)`); }
281
+
282
+ if (this.ws) {
283
+ if (this.handshakeMessageListener) {
284
+ this.ws.removeEventListener('message', this.handshakeMessageListener);
285
+ this.handshakeMessageListener = undefined;
286
+ }
287
+ try {
288
+ this.ws.close();
289
+ } catch (error) {
290
+ console.error(`${lc} failed to close websocket: ${extractErrorMsg(error)}`);
291
+ }
292
+ this.ws = undefined;
293
+ }
294
+ } catch (error) {
295
+ console.error(`${lc} ${extractErrorMsg(error)}`);
296
+ // throw error; // disconnect does NOT rethrow
297
+ } finally {
298
+ if (logalot) { console.log(`${lc} complete.`); }
299
+ }
300
+ }
301
+
259
302
  /**
260
303
  * Handles synchronizing messages and evolved context frames during active transaction turns.
261
304
  */
@@ -265,49 +308,170 @@ export class SyncPeerWebSocketSender_V1
265
308
  const msg = JSON.parse(event.data);
266
309
  if (logalot) { console.log(`${lc} received runtime frame: ${msg.type}`); }
267
310
 
268
- if (msg.type === SyncWebSocketMsgType.sync_frame_response) {
269
- const responseContext = msg.context as SyncSagaContextIbGib_V1;
270
-
271
- // Validate and authenticate Bob's response context first
272
- await this.authenticateAndValidate({ context: responseContext });
273
-
274
- // If response has expected payloads, authorize Bob to stream them
275
- const expectedPayloadAddrs = responseContext.data?.['@payloadAddrsDomain'] || [];
276
- if (expectedPayloadAddrs.length > 0) {
277
- this.ws!.send(JSON.stringify({
278
- type: SyncWebSocketMsgType.sync_frame_response_authenticated,
279
- contextAddr: getIbGibAddr({ ibGib: responseContext })
280
- }));
281
- }
311
+ const msgType = msg.type;
312
+ if (!isSyncWebSocketMsgType(msgType)) {
313
+ const validTypes = SYNC_WEB_SOCKET_MSG_TYPE_VALID_VALUES.join(', ');
314
+ throw new Error(`Unknown message type '${msgType}' received during active sync saga loop. Valid types are: ${validTypes} (E: e23a8d10b74d47fb90518f8e3f4b826)`);
315
+ }
282
316
 
283
- if (this.activeResolve) {
284
- const resolve = this.activeResolve;
285
- this.activeResolve = undefined;
286
- this.activeReject = undefined;
287
- resolve(responseContext);
288
- }
289
- } else if (msg.type === SyncWebSocketMsgType.sync_frame_authenticated) {
290
- // Bob authenticated our context, stream buffered payloads
291
- const payloads = this.pendingPayloadsToSend || [];
292
- this.pendingPayloadsToSend = [];
293
- for (const ibGib of payloads) {
294
- this.ws!.send(JSON.stringify({
295
- type: SyncWebSocketMsgType.domain_payload,
296
- ibGib
297
- }));
298
- }
299
- } else if (msg.type === SyncWebSocketMsgType.domain_payload) {
300
- const payload = msg.ibGib as IbGib_V1;
301
- this.payloadIbGibsDomainReceived$.next(payload);
317
+ switch (msgType) {
318
+ case SyncWebSocketMsgType.sync_frame_response:
319
+ await this.handleRuntimeSyncFrameResponse(msg);
320
+ break;
321
+ case SyncWebSocketMsgType.sync_frame_authenticated:
322
+ this.handleRuntimeSyncFrameAuthenticated();
323
+ break;
324
+ case SyncWebSocketMsgType.domain_payload:
325
+ this.handleRuntimeDomainPayload(msg);
326
+ break;
327
+ case SyncWebSocketMsgType.sync_error:
328
+ this.handleRuntimeSyncError(msg);
329
+ break;
330
+ // Handshake messages / unexpected messages during active sync saga loop
331
+ case SyncWebSocketMsgType.auth_challenge_init:
332
+ case SyncWebSocketMsgType.auth_init:
333
+ case SyncWebSocketMsgType.auth_challenge:
334
+ case SyncWebSocketMsgType.auth_proof:
335
+ case SyncWebSocketMsgType.auth_ok:
336
+ case SyncWebSocketMsgType.auth_fail:
337
+ case SyncWebSocketMsgType.sync_frame:
338
+ case SyncWebSocketMsgType.sync_frame_response_authenticated:
339
+ throw new Error(`Unexpected message type '${msgType}' during active sync saga loop (E: e982b12cf92c448bbad0e84b7263c826)`);
340
+ default:
341
+ assertUnreachable(msgType);
302
342
  }
303
343
  } catch (error) {
304
- console.error(`${lc} failed parsing runtime frame: ${extractErrorMsg(error)}`);
344
+ console.error(`${lc} failed parsing/handling runtime frame: ${extractErrorMsg(error)}`);
345
+ this.disconnect();
305
346
  if (this.activeReject) {
306
- this.activeReject(error);
347
+ const reject = this.activeReject;
348
+ this.activeResolve = undefined;
349
+ this.activeReject = undefined;
350
+ reject(error);
307
351
  }
308
352
  }
309
353
  }
310
354
 
355
+ protected async handleHandshakeAuthChallengeInit(ws: WebSocket, targetSAddr: string): Promise<void> {
356
+ ws.send(JSON.stringify({
357
+ type: SyncWebSocketMsgType.auth_init,
358
+ sAddr: targetSAddr
359
+ }));
360
+ }
361
+
362
+ protected async handleHandshakeAuthChallenge(
363
+ ws: WebSocket,
364
+ msg: any,
365
+ sessionS: KeystoneIbGib_V1,
366
+ sessionSecret: string
367
+ ): Promise<void> {
368
+ const { challengeUuid, demandedIds } = msg;
369
+ if (logalot) { console.log(`${this.lc} solving demanded challenges: ${demandedIds.join(', ')}`); }
370
+
371
+ const proofFrame = await this.signContextConnect({
372
+ challengeUuid,
373
+ demandedIds
374
+ });
375
+
376
+ if (!proofFrame) {
377
+ throw new Error(`Failed to sign connect challenge proof (E: e9807f28ae9248bbadd0a7f1a8e9826)`);
378
+ }
379
+
380
+ ws.send(JSON.stringify({
381
+ type: SyncWebSocketMsgType.auth_proof,
382
+ proofFrame
383
+ }));
384
+ }
385
+
386
+ protected handleHandshakeAuthOk(ws: WebSocket, resolve: () => void): void {
387
+ if (logalot) { console.log(`${this.lc} WebSocket connect SUCCESS!`); }
388
+ if (this.handshakeMessageListener) {
389
+ ws.removeEventListener('message', this.handshakeMessageListener);
390
+ this.handshakeMessageListener = undefined;
391
+ }
392
+ ws.addEventListener('message', (event) => this.handleRuntimeMessage(event));
393
+ resolve();
394
+ }
395
+
396
+ protected handleHandshakeAuthFail(msg: any, reject: (err: Error) => void): void {
397
+ this.disconnect();
398
+ reject(new Error(`Handshake auth failed: ${msg.message || 'Unknown fail reason'} (E: f380b271a2be498db257bc8209fa8926)`));
399
+ }
400
+
401
+ protected handleHandshakeSyncError(msg: any, reject: (err: Error) => void): void {
402
+ this.disconnect();
403
+ reject(new Error(`Handshake sync error: ${msg.message || msg.error || 'Unknown sync error'} (E: f9208a01fe434cbbad83f210ea8f3426)`));
404
+ }
405
+
406
+ protected async handleRuntimeSyncFrameResponse(msg: any): Promise<void> {
407
+ const responseContext = msg.context as SyncSagaContextIbGib_V1;
408
+
409
+ const validationErrors = await validateContextAndSagaFrame({ context: responseContext });
410
+ if (validationErrors.length > 0) {
411
+ throw new Error(`Invalid response context received: ${validationErrors.join(', ')} (E: d7b5a283cf4c43ba8659c803800cf826)`);
412
+ }
413
+
414
+ // Put response control ibgibs into durable space immediately
415
+ const allControlIbGibs: IbGib_V1[] = [
416
+ toDto({ ibGib: responseContext }),
417
+ responseContext.sagaFrame,
418
+ responseContext.sagaFrameMsg!
419
+ ];
420
+ if (responseContext.signedSessionIdentity) {
421
+ allControlIbGibs.push(responseContext.signedSessionIdentity);
422
+ }
423
+
424
+ const { localSpace } = this.opts!;
425
+ for (const ibGib of allControlIbGibs) {
426
+ await putInSpace({ space: localSpace, ibGibs: [ibGib] });
427
+ await registerNewIbGib({ space: localSpace, ibGib });
428
+ }
429
+
430
+ const expectedPayloadAddrs = responseContext.data?.['@payloadAddrsDomain'] || [];
431
+ if (expectedPayloadAddrs.length > 0) {
432
+ this.ws!.send(JSON.stringify({
433
+ type: SyncWebSocketMsgType.sync_frame_response_authenticated,
434
+ contextAddr: getIbGibAddr({ ibGib: responseContext })
435
+ }));
436
+ }
437
+
438
+ if (this.activeResolve) {
439
+ const resolve = this.activeResolve;
440
+ this.activeResolve = undefined;
441
+ this.activeReject = undefined;
442
+ resolve(responseContext);
443
+ }
444
+ }
445
+
446
+ protected handleRuntimeSyncFrameAuthenticated(): void {
447
+ const payloads = this.pendingPayloadsToSend || [];
448
+ this.pendingPayloadsToSend = [];
449
+ for (const ibGib of payloads) {
450
+ this.ws!.send(JSON.stringify({
451
+ type: SyncWebSocketMsgType.domain_payload,
452
+ ibGib
453
+ }));
454
+ }
455
+ }
456
+
457
+ protected handleRuntimeDomainPayload(msg: any): void {
458
+ const payload = msg.ibGib as IbGib_V1;
459
+ this.payloadIbGibsDomainReceived$.next(payload);
460
+ }
461
+
462
+ protected handleRuntimeSyncError(msg: any): void {
463
+ const errorDetail = msg.message || msg.error || 'Unknown sync runtime error';
464
+ const error = new Error(`Sync runtime error from receiver: ${errorDetail} (E: e983bc1c828d447fa0581da2b8004f26)`);
465
+ if (this.activeReject) {
466
+ const reject = this.activeReject;
467
+ this.activeResolve = undefined;
468
+ this.activeReject = undefined;
469
+ reject(error);
470
+ } else {
471
+ throw error;
472
+ }
473
+ }
474
+
311
475
  /**
312
476
  * Serializes the transaction context and payload down the active WebSocket connection.
313
477
  */
@@ -2,14 +2,14 @@
2
2
  * @module sync saga context helpers
3
3
  */
4
4
 
5
- import { extractErrorMsg, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
5
+ import { extractErrorMsg, pretty, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
6
  import { getIbGibAddr, } from '@ibgib/ts-gib/dist/helper.mjs';
7
7
  import { Ib, } from '@ibgib/ts-gib/dist/types.mjs';
8
8
  import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
9
9
 
10
10
  import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
11
11
  import { SYNC_SAGA_CONTEXT_ATOM } from './sync-saga-context-constants.mjs';
12
- import { SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
12
+ import { SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN, SYNC_MSG_REL8N_NAME } from '../sync-constants.mjs';
13
13
  import {
14
14
  SyncSagaContextData_V1, SyncSagaContextIbGib_V1, SyncSagaContextIb_V1,
15
15
  } from './sync-saga-context-types.mjs';
@@ -17,9 +17,9 @@ import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
17
17
  import { getFromSpace, getLatestAddrs, getTjpIbGib } from '../../witness/space/space-helper.mjs';
18
18
  import { SessionGenesisFrameDetails, } from '../sync-types.mjs';
19
19
  import { validateSyncSagaFrame } from '../sync-helpers.mjs';
20
- import { isIbGibWithAtom } from '../../common/other/ibgib-helper.mjs';
20
+ import { isIbGibWithAtom, toDto } from '../../common/other/ibgib-helper.mjs';
21
21
  import { KeystoneService_V1 } from '../../keystone/keystone-service-v1.mjs';
22
- import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
22
+ import { KeystoneData_V1, KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
23
23
  import { KEYSTONE_VERB_SYNC } from '../../keystone/keystone-constants.mjs';
24
24
 
25
25
  const logalot = GLOBAL_LOG_A_LOT;
@@ -150,6 +150,26 @@ export async function validateContextAndSagaFrame({
150
150
  errors.push(`context.sagaFrame is falsy. (E: b4edd88f4963f493789f83b29ba2df26)`);
151
151
  }
152
152
 
153
+ if (context.sagaFrameMsg) {
154
+ const sagaFrameMsgErrors =
155
+ await validateIbGibIntrinsically({ ibGib: context.sagaFrameMsg }) ?? [];
156
+ sagaFrameMsgErrors.forEach(x => errors.push(x));
157
+
158
+ if (context.sagaFrame) {
159
+ const expectedMsgAddr = context.sagaFrame.rel8ns?.[SYNC_MSG_REL8N_NAME]?.[0];
160
+ if (expectedMsgAddr) {
161
+ const actualMsgAddr = getIbGibAddr({ ibGib: context.sagaFrameMsg });
162
+ if (actualMsgAddr !== expectedMsgAddr) {
163
+ errors.push(`context.sagaFrameMsg address (${actualMsgAddr}) does not match the stone address referenced in sagaFrame relations (${expectedMsgAddr}). (E: a983b271fcae46bbad7e82098bc24826)`);
164
+ }
165
+ } else {
166
+ errors.push(`context.sagaFrame is missing the message stone relation '${SYNC_MSG_REL8N_NAME}'. (E: da872cf3a8d46dbbad89d0a68d712826)`);
167
+ }
168
+ }
169
+ } else {
170
+ errors.push(`context.sagaFrameMsg is falsy. (E: ed405a72ab0d8bbdca7b9605d8f9a26)`);
171
+ }
172
+
153
173
  // if this is already invalid, we could have intrinsic validation
154
174
  // errors, which are a non-starter.
155
175
  if (errors.length > 0) { return errors; /* <<<< returns early */ }
@@ -301,6 +321,28 @@ export async function authenticateContextIntrinsically({
301
321
  } else {
302
322
  // debugger; // in sync saga context auth, want to know if this hits...so far this does NOT hit
303
323
  errors.push(`context.rel8ns.sessionIdentity does not point to the most recent in the space (${space.ib}). (E: 2f8288f53c87b6aa47bd2178d9df0c26)`)
324
+
325
+ // #region debug error keystone
326
+ console.log(`context: ${pretty(toDto({ ibGib: context }))}`)
327
+ console.log(`prevSessionIdentityAddr (context.rel8ns.sessionIdentity): ${prevSessionIdentityAddr}`)
328
+ console.log(`prevSessionIdentityAddr_latest: ${prevSessionIdentityAddr_latest}`)
329
+ console.log(`currSessionIdentity (context.signedSessionIdentity): ${pretty(toDto({
330
+ ibGib: {
331
+ ib: currSessionIdentity.ib,
332
+ gib: currSessionIdentity.gib,
333
+ rel8ns: currSessionIdentity.rel8ns,
334
+ data: {
335
+ ...currSessionIdentity.data,
336
+ challengePools: currSessionIdentity.data.challengePools.map(p => {
337
+ return { ...p, challenges: {} }
338
+ }),
339
+ } satisfies Partial<KeystoneData_V1>,
340
+
341
+ }
342
+ }))}`)
343
+ console.log(`currSessionIdentityAddr: ${currSessionIdentityAddr}`)
344
+
345
+ // #endregion debug error keystone
304
346
  return errors; /* <<<< returns early */
305
347
  }
306
348
  }
@@ -79,4 +79,9 @@ export interface SyncSagaContextIbGib_V1 extends IbGib_V1<SyncSagaContextData_V1
79
79
  * Evolved session identity frame signed by Alice targeting this context.
80
80
  */
81
81
  signedSessionIdentity?: KeystoneIbGib_V1;
82
+
83
+ /**
84
+ * The actual message stone (the sync saga message containing state/stage).
85
+ */
86
+ sagaFrameMsg: IbGib_V1;
82
87
  }