@ibgib/core-gib 0.1.57 → 0.1.59

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 (162) hide show
  1. package/dist/keystone/keystone-config-builder.d.mts +12 -1
  2. package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
  3. package/dist/keystone/keystone-config-builder.mjs +58 -4
  4. package/dist/keystone/keystone-config-builder.mjs.map +1 -1
  5. package/dist/keystone/keystone-constants.d.mts +40 -5
  6. package/dist/keystone/keystone-constants.d.mts.map +1 -1
  7. package/dist/keystone/keystone-constants.mjs +39 -5
  8. package/dist/keystone/keystone-constants.mjs.map +1 -1
  9. package/dist/keystone/keystone-helpers.d.mts +11 -1
  10. package/dist/keystone/keystone-helpers.d.mts.map +1 -1
  11. package/dist/keystone/keystone-helpers.mjs +37 -1
  12. package/dist/keystone/keystone-helpers.mjs.map +1 -1
  13. package/dist/keystone/keystone-policy-types.d.mts +23 -0
  14. package/dist/keystone/keystone-policy-types.d.mts.map +1 -0
  15. package/dist/keystone/keystone-policy-types.mjs +2 -0
  16. package/dist/keystone/keystone-policy-types.mjs.map +1 -0
  17. package/dist/sync/graft-info/graft-info-helpers.respec.mjs +8 -8
  18. package/dist/sync/graft-info/graft-info-helpers.respec.mjs.map +1 -1
  19. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +22 -22
  20. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
  21. package/dist/sync/sync-conflict-basic-divergence.respec.mjs +3 -3
  22. package/dist/sync/sync-conflict-basic-divergence.respec.mjs.map +1 -1
  23. package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs +6 -6
  24. package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs.map +1 -1
  25. package/dist/sync/sync-conflict-text-merge.respec.mjs +26 -26
  26. package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
  27. package/dist/sync/sync-helpers.d.mts +19 -0
  28. package/dist/sync/sync-helpers.d.mts.map +1 -1
  29. package/dist/sync/sync-helpers.mjs +51 -1
  30. package/dist/sync/sync-helpers.mjs.map +1 -1
  31. package/dist/sync/sync-innerspace-constants.respec.mjs +2 -2
  32. package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
  33. package/dist/sync/sync-innerspace-deep-updates.respec.mjs +2 -2
  34. package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
  35. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +4 -4
  36. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
  37. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +2 -2
  38. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
  39. package/dist/sync/sync-innerspace-partial-update.respec.mjs +3 -3
  40. package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
  41. package/dist/sync/sync-innerspace.respec.mjs +4 -4
  42. package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
  43. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts +5 -0
  44. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts.map +1 -1
  45. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs +24 -2
  46. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs.map +1 -1
  47. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts +5 -0
  48. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts.map +1 -1
  49. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs +21 -3
  50. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs.map +1 -1
  51. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.d.mts +1 -1
  52. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +13 -1
  53. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  54. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +40 -10
  55. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  56. package/dist/sync/sync-peer/sync-peer-types.d.mts +81 -1
  57. package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
  58. package/dist/sync/sync-peer/sync-peer-v1.d.mts +37 -3
  59. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  60. package/dist/sync/sync-peer/sync-peer-v1.mjs +163 -23
  61. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  62. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.d.mts +46 -0
  63. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.d.mts.map +1 -0
  64. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mjs +45 -0
  65. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mjs.map +1 -0
  66. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts +30 -0
  67. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts.map +1 -0
  68. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs +2 -0
  69. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs.map +1 -0
  70. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +68 -0
  71. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -0
  72. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +324 -0
  73. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -0
  74. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +85 -0
  75. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -0
  76. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +332 -0
  77. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -0
  78. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts +29 -0
  79. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts.map +1 -0
  80. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs +2 -0
  81. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs.map +1 -0
  82. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts +44 -0
  83. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -0
  84. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +303 -0
  85. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -0
  86. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +22 -5
  87. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
  88. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +223 -27
  89. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
  90. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +9 -0
  91. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
  92. package/dist/sync/sync-saga-coordinator.d.mts +41 -2
  93. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  94. package/dist/sync/sync-saga-coordinator.mjs +110 -11
  95. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  96. package/dist/sync/sync-types.d.mts +24 -0
  97. package/dist/sync/sync-types.d.mts.map +1 -1
  98. package/dist/sync/sync-types.mjs +0 -1
  99. package/dist/sync/sync-types.mjs.map +1 -1
  100. package/dist/sync/sync-withid.connect.respec.d.mts +12 -0
  101. package/dist/sync/sync-withid.connect.respec.d.mts.map +1 -0
  102. package/dist/sync/sync-withid.connect.respec.mjs +205 -0
  103. package/dist/sync/sync-withid.connect.respec.mjs.map +1 -0
  104. package/dist/sync/sync-withid.establish.respec.d.mts +19 -0
  105. package/dist/sync/sync-withid.establish.respec.d.mts.map +1 -0
  106. package/dist/sync/sync-withid.establish.respec.mjs +322 -0
  107. package/dist/sync/sync-withid.establish.respec.mjs.map +1 -0
  108. package/dist/sync/sync-withid.pingpong.respec.d.mts +11 -0
  109. package/dist/sync/sync-withid.pingpong.respec.d.mts.map +1 -0
  110. package/dist/sync/sync-withid.pingpong.respec.mjs +131 -0
  111. package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -0
  112. package/dist/witness/space/inner-space/inner-space-v1.d.mts.map +1 -1
  113. package/dist/witness/space/inner-space/inner-space-v1.mjs +1 -1
  114. package/dist/witness/space/inner-space/inner-space-v1.mjs.map +1 -1
  115. package/package.json +4 -4
  116. package/src/keystone/keystone-config-builder.mts +73 -4
  117. package/src/keystone/keystone-constants.mts +42 -6
  118. package/src/keystone/keystone-helpers.mts +44 -2
  119. package/src/keystone/keystone-policy-types.mts +25 -0
  120. package/src/keystone/keystone-policy.schema.json +51 -0
  121. package/src/keystone/keystone-service-v1.mts +3 -3
  122. package/src/sync/docs/architecture.md +20 -0
  123. package/src/sync/docs/ping_pong_plan.md +147 -0
  124. package/src/sync/docs/security.md +207 -3
  125. package/src/sync/graft-info/graft-info-helpers.respec.mts +7 -7
  126. package/src/sync/sync-conflict-adv-multitimelines.respec.mts +21 -21
  127. package/src/sync/sync-conflict-basic-divergence.respec.mts +2 -2
  128. package/src/sync/sync-conflict-basic-multitimelines.respec.mts +5 -5
  129. package/src/sync/sync-conflict-text-merge.respec.mts +25 -25
  130. package/src/sync/sync-helpers.mts +51 -1
  131. package/src/sync/sync-innerspace-constants.respec.mts +1 -1
  132. package/src/sync/sync-innerspace-deep-updates.respec.mts +1 -1
  133. package/src/sync/sync-innerspace-dest-ahead.respec.mts +3 -3
  134. package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
  135. package/src/sync/sync-innerspace-partial-update.respec.mts +2 -2
  136. package/src/sync/sync-innerspace.respec.mts +3 -3
  137. package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mts +26 -2
  138. package/src/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mts +23 -3
  139. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.mts +1 -1
  140. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +47 -13
  141. package/src/sync/sync-peer/sync-peer-types.mts +87 -1
  142. package/src/sync/sync-peer/sync-peer-v1.mts +171 -32
  143. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mts +68 -0
  144. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mts +36 -0
  145. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +385 -0
  146. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +388 -0
  147. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mts +35 -0
  148. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +345 -0
  149. package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +223 -34
  150. package/src/sync/sync-saga-context/sync-saga-context-types.mts +9 -0
  151. package/src/sync/sync-saga-coordinator.mts +162 -6
  152. package/src/sync/sync-types.mts +28 -4
  153. package/src/sync/sync-withid.connect.respec.mts +243 -0
  154. package/src/sync/sync-withid.establish.respec.mts +361 -0
  155. package/src/sync/sync-withid.pingpong.respec.mts +161 -0
  156. package/src/sync/unused-identity-backup.mts.md +1 -1
  157. package/src/witness/space/inner-space/inner-space-v1.mts +4 -5
  158. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts +0 -2
  159. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts.map +0 -1
  160. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +0 -310
  161. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +0 -1
  162. package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +0 -364
@@ -0,0 +1,385 @@
1
+ /**
2
+ * @module sync-peer-websocket-receiver-v1
3
+ */
4
+
5
+ import { extractErrorMsg, getUUID } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
+ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
7
+ import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
8
+ import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
9
+
10
+ import { GLOBAL_LOG_A_LOT } from '../../../../core-constants.mjs';
11
+ import { SyncPeer_V1 } from '../../sync-peer-v1.mjs';
12
+ import { SyncSagaContextIbGib_V1 } from '../../../sync-saga-context/sync-saga-context-types.mjs';
13
+ import { authenticateContextIntrinsically } from '../../../sync-saga-context/sync-saga-context-helpers.mjs';
14
+ import { IbGibSpaceAny } from '../../../../witness/space/space-base-v1.mjs';
15
+ import { putInSpace, registerNewIbGib } from '../../../../witness/space/space-helper.mjs';
16
+ import {
17
+ ConnectSyncPeerWebSocketReceiverOpts,
18
+ InitializeSyncPeerWebSocketReceiverOpts,
19
+ SyncPeerWebSocketReceiverData_V1, SyncPeerWebSocketReceiverRel8ns_V1,
20
+ SyncPeerWebSocketReceiverIbGib_V1
21
+ } from './sync-peer-websocket-receiver-types.mjs';
22
+ import { KeystoneIbGib_V1 } from '../../../../keystone/keystone-types.mjs';
23
+ import { SyncWebSocketMsgType } from '../sync-peer-websocket-constants.mjs';
24
+ import { SESSION_KEYSTONE_POLICY, verifyConnectProof } from './sync-websocket-peer-helpers.mjs';
25
+ import { getFullSyncSagaHistory } from '../../../sync-helpers.mjs';
26
+ import { toDto } from '../../../../common/other/ibgib-helper.mjs';
27
+
28
+ const logalot = GLOBAL_LOG_A_LOT || true;
29
+
30
+ /**
31
+ * A platform-agnostic interface wrapping runtime-specific WebSocket stream operations.
32
+ */
33
+ export interface IWebSocketWrapper {
34
+ send(data: string): void;
35
+ onMessage(callback: (data: string) => void): void;
36
+ onClose(callback: () => void): void;
37
+ }
38
+
39
+ /**
40
+ * Platform-agnostic WebSocket Receiver Peer.
41
+ *
42
+ * Fully encapsulates the multi-turn cryptographic challenge connect and runtime
43
+ * turn routing.
44
+ */
45
+ export class SyncPeerWebSocketReceiver_V1
46
+ extends SyncPeer_V1<ConnectSyncPeerWebSocketReceiverOpts, InitializeSyncPeerWebSocketReceiverOpts>
47
+ implements SyncPeerWebSocketReceiverIbGib_V1 {
48
+
49
+ protected override lc: string = `[${SyncPeerWebSocketReceiver_V1.name}]`;
50
+
51
+ override get classname(): string {
52
+ return SyncPeerWebSocketReceiver_V1.name;
53
+ }
54
+
55
+ declare data: SyncPeerWebSocketReceiverData_V1 | undefined;
56
+ declare rel8ns: SyncPeerWebSocketReceiverRel8ns_V1 | undefined;
57
+
58
+ protected socketWrapper?: IWebSocketWrapper;
59
+
60
+ // Connect State Machine variables
61
+ protected isAuthenticated = false;
62
+ protected challengeUuid?: string;
63
+ protected demandedIds?: string[];
64
+ protected sessionS_tjpAddr?: string;
65
+
66
+ // Runtime state variables for delayed payload streaming
67
+ protected pendingContext?: SyncSagaContextIbGib_V1;
68
+ protected pendingPayloadAddrs?: Set<string>;
69
+ protected pendingResponsePayloadsToSend: IbGib_V1[] = [];
70
+
71
+ constructor(
72
+ initialData: SyncPeerWebSocketReceiverData_V1,
73
+ initialRel8ns?: SyncPeerWebSocketReceiverRel8ns_V1,
74
+ ) {
75
+ super(initialData, initialRel8ns);
76
+ }
77
+
78
+ /**
79
+ * Wires the peer receiver to the platform-specific socket stream and
80
+ * triggers the connect.
81
+ */
82
+ public async bindSocket(socketWrapper: IWebSocketWrapper): Promise<void> {
83
+ const lc = `${this.lc}[${this.bindSocket.name}]`;
84
+ this.socketWrapper = socketWrapper;
85
+ socketWrapper.onMessage((data) => this.handleIncomingMessage(data));
86
+
87
+ // Immediately trigger multi-turn challenge connection
88
+ try {
89
+ this.challengeUuid = await getUUID();
90
+ socketWrapper.send(JSON.stringify({
91
+ type: SyncWebSocketMsgType.auth_challenge_init,
92
+ challengeUuid: this.challengeUuid
93
+ }));
94
+ } catch (error) {
95
+ console.error(`${lc} failed triggering challenge init: ${extractErrorMsg(error)}`);
96
+ socketWrapper.send(JSON.stringify({
97
+ type: SyncWebSocketMsgType.auth_fail,
98
+ message: 'Internal server connect error'
99
+ }));
100
+ }
101
+ }
102
+
103
+ protected override async preConnectCheck(opts: ConnectSyncPeerWebSocketReceiverOpts): Promise<void> {
104
+ // Handled dynamically on upgrade
105
+ }
106
+
107
+ protected override async connectImpl(opts: ConnectSyncPeerWebSocketReceiverOpts): Promise<void> {
108
+ // Handled dynamically on upgrade
109
+ }
110
+
111
+ protected override async postEstablishToReceiver(opts: {
112
+ newSenderIdentity: KeystoneIbGib_V1;
113
+ sessionIdentity: KeystoneIbGib_V1;
114
+ }): Promise<void> {
115
+ throw new Error(`postEstablishToReceiver is not supported on Receiver Peer (E: 309f3cf8e7c813d338394f28c576da26)`);
116
+ }
117
+
118
+ protected override async sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined> {
119
+ throw new Error(`sendContextRequest is not supported on Receiver Peer (E: e5327ed6c64883e12ef95984f1409926)`);
120
+ }
121
+
122
+ /** Helper to load a Session Keystone from storage */
123
+ protected async getSessionKeystone(sAddr: string): Promise<KeystoneIbGib_V1> {
124
+ const metaspace = this.opts!.localMetaspace;
125
+ const space = this.opts!.localSpace;
126
+ const resGet = await metaspace.get({ addrs: [sAddr], space });
127
+ if (resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1) {
128
+ return resGet.ibGibs[0] as KeystoneIbGib_V1;
129
+ }
130
+ throw new Error(`Session keystone not found in storage: ${sAddr} (E: 42315837e3b1deb5b81072f8601e6a26)`);
131
+ }
132
+
133
+ protected async ensureLocalTempSpace(): Promise<IbGibSpaceAny> {
134
+ const lc = `${this.lc}[${this.ensureLocalTempSpace.name}]`;
135
+ try {
136
+ if (!this.opts) { throw new Error(`opts not initialized. (E: c4929fb1596833a7186d119855bb7e26)`); }
137
+
138
+ if (!this.opts.localTempSpace) {
139
+ const { localMetaspace } = this.opts;
140
+
141
+ const uuid = crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36);
142
+ const tempSpaceName = `tmp_sync_recv_${uuid.substring(0, 8)}`;
143
+ const localTempSpace = await localMetaspace.createNewLocalSpace({
144
+ opts: {
145
+ allowCancel: false,
146
+ spaceName: tempSpaceName,
147
+ getFnPrompt: localMetaspace.getFnPrompt!,
148
+ logalot
149
+ }
150
+ });
151
+ if (!localTempSpace) { throw new Error(`couldn't create a temp space (E: d82461769b4bbb35df5d6a8a9c665426)`); }
152
+ await localTempSpace.initialized;
153
+ this.opts.localTempSpace = localTempSpace;
154
+ }
155
+
156
+ return this.opts.localTempSpace;
157
+ } catch (error) {
158
+ console.error(`${lc} ${extractErrorMsg(error)}`);
159
+ throw error;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Entry point for processing raw text frames received over the active WebSocket connection.
165
+ */
166
+ public async handleIncomingMessage(messageText: string): Promise<void> {
167
+ const lc = `${this.lc}[${this.handleIncomingMessage.name}]`;
168
+ try {
169
+ if (!this.socketWrapper) {
170
+ throw new Error(`WebSocket wrapper not bound to receiver peer (E: ad4c5838d1b87259586b21a89b2c7726)`);
171
+ }
172
+
173
+ const msg = JSON.parse(messageText);
174
+ if (logalot) { console.log(`${lc} received frame: ${msg.type}`); }
175
+
176
+ // 1. Connect Phase Route Guard
177
+ if (!this.isAuthenticated) {
178
+ await this.handleConnectFrame(msg);
179
+ return; /* <<<< returns early */
180
+ }
181
+
182
+ // 2. Authenticated Runtime Sync Route
183
+ if (msg.type === SyncWebSocketMsgType.domain_payload) {
184
+ const ibGib = msg.ibGib as IbGib_V1;
185
+ const validationErrors =
186
+ await validateIbGibIntrinsically({ ibGib }) ?? [];
187
+ if (validationErrors.length > 0) {
188
+ throw new Error(`controlIbGibs invalid intrinsically. validationErrors: ${validationErrors.join('|')} (E: 5ee1787d4cc53d3d2c55f3d4f2865226)`);
189
+ }
190
+
191
+ if (this.pendingContext && this.pendingPayloadAddrs) {
192
+ const addr = getIbGibAddr({ ibGib });
193
+ if (this.pendingPayloadAddrs.has(addr)) {
194
+ const tempSpace = await this.ensureLocalTempSpace();
195
+ await putInSpace({ space: tempSpace, ibGibs: [ibGib] });
196
+ this.pendingPayloadAddrs.delete(addr);
197
+
198
+ // If all expected payloads for the pending context are received
199
+ if (this.pendingPayloadAddrs.size === 0) {
200
+ const context = this.pendingContext;
201
+ this.pendingContext = undefined;
202
+ this.pendingPayloadAddrs = undefined;
203
+
204
+ await this.executeIncomingSyncRequestAndRespond({ context });
205
+ }
206
+ } else {
207
+ console.warn(`${lc} received payload not in expected list: ${addr}`);
208
+ }
209
+ }
210
+ } else if (msg.type === SyncWebSocketMsgType.sync_frame) {
211
+ const context = msg.context as SyncSagaContextIbGib_V1;
212
+
213
+ // First, validate and authenticate the context
214
+ const allControlIbGibs: IbGib_V1[] = [
215
+ toDto({ ibGib: context }),
216
+ context.sagaFrame
217
+ ];
218
+ if (context.signedSessionIdentity) {
219
+ allControlIbGibs.push(context.signedSessionIdentity);
220
+ }
221
+
222
+ for (const controlIbGib of allControlIbGibs) {
223
+ const validationErrors =
224
+ await validateIbGibIntrinsically({ ibGib: controlIbGib }) ?? [];
225
+ if (validationErrors.length > 0) {
226
+ throw new Error(`controlIbGibs invalid intrinsically. validationErrors: ${validationErrors.join('|')} (E: d40dfa87265a0b73c8ef784d1265ea26)`);
227
+ }
228
+ }
229
+
230
+ await this.authenticateAndValidate({ context });
231
+
232
+ // Put control ibgibs into durable space immediately for audit trail
233
+ for (const ibGib of allControlIbGibs) {
234
+ await putInSpace({ space: this.opts!.localSpace, ibGibs: [ibGib] });
235
+ await registerNewIbGib({ space: this.opts!.localSpace, ibGib });
236
+ }
237
+
238
+ // Check if payloads are expected
239
+ const expectedPayloadAddrs = context.data?.['@payloadAddrsDomain'] || [];
240
+ if (expectedPayloadAddrs.length > 0) {
241
+ // Set up wait state and request payloads
242
+ this.pendingContext = context;
243
+ this.pendingPayloadAddrs = new Set(expectedPayloadAddrs);
244
+ this.socketWrapper.send(JSON.stringify({
245
+ type: SyncWebSocketMsgType.sync_frame_authenticated,
246
+ contextAddr: getIbGibAddr({ ibGib: context })
247
+ }));
248
+ } else {
249
+ // No payloads expected, process immediately
250
+ await this.executeIncomingSyncRequestAndRespond({ context });
251
+ }
252
+ } else if (msg.type === SyncWebSocketMsgType.sync_frame_response_authenticated) {
253
+ // Alice authenticated our response context, stream our payloads now
254
+ const payloads = this.pendingResponsePayloadsToSend || [];
255
+ this.pendingResponsePayloadsToSend = [];
256
+ for (const ibGib of payloads) {
257
+ this.socketWrapper.send(JSON.stringify({
258
+ type: SyncWebSocketMsgType.domain_payload,
259
+ ibGib
260
+ }));
261
+ }
262
+ }
263
+ } catch (error) {
264
+ console.error(`${lc} message frame handling failed: ${extractErrorMsg(error)}`);
265
+ this.socketWrapper?.send(JSON.stringify({
266
+ type: this.isAuthenticated ? SyncWebSocketMsgType.sync_error : SyncWebSocketMsgType.auth_fail,
267
+ message: extractErrorMsg(error)
268
+ }));
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Handles the multi-turn cryptographic challenge connect messages.
274
+ */
275
+ protected async handleConnectFrame(msg: any): Promise<void> {
276
+ const lc = `${this.lc}[${this.handleConnectFrame.name}]`;
277
+ const metaspace = this.opts!.localMetaspace;
278
+ const space = this.opts!.localSpace;
279
+
280
+ if (msg.type === SyncWebSocketMsgType.auth_init) {
281
+ const { sAddr } = msg;
282
+ if (logalot) { console.log(`${lc} auth-init for ${sAddr}`); }
283
+
284
+ const authorizedS = await this.getSessionKeystone(sAddr);
285
+ const connectPool = (authorizedS.data?.challengePools ?? [])
286
+ .find(p => p.id === SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID);
287
+ if (!connectPool) {
288
+ throw new Error(`Session keystone missing "${SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID}" pool (E: 66b2a2e32db8f03168f6f2a8b746cb26)`);
289
+ }
290
+
291
+ // Demand random challenges
292
+ const challengeIds = Object.keys(connectPool.challenges);
293
+ this.demandedIds = challengeIds.sort(() => 0.5 - Math.random()).slice(0, SESSION_KEYSTONE_POLICY.CONNECT_POOL.SERVER_DEMAND_COUNT);
294
+
295
+ // Resolve secure S TJP
296
+ const past = authorizedS.rel8ns?.past;
297
+ this.sessionS_tjpAddr = (past && past.length > 0) ? past[0] : getIbGibAddr({ ibGib: authorizedS });
298
+
299
+ this.socketWrapper!.send(JSON.stringify({
300
+ type: SyncWebSocketMsgType.auth_challenge,
301
+ challengeUuid: this.challengeUuid,
302
+ demandedIds: this.demandedIds
303
+ }));
304
+
305
+ } else if (msg.type === SyncWebSocketMsgType.auth_proof) {
306
+ const { proofFrame } = msg;
307
+ if (logalot) { console.log(`${lc} verifying auth-proof...`); }
308
+
309
+ if (!this.sessionS_tjpAddr) {
310
+ throw new Error(`Missing active connect session TJP address (E: bf271853de61a04b6d05d6889263f826)`);
311
+ }
312
+
313
+ const sAddr_latest = await metaspace.getLatestAddr({ tjpAddr: this.sessionS_tjpAddr, space });
314
+ if (!sAddr_latest) {
315
+ throw new Error(`Authorized session keystone tip not found (E: b8cda5cdc058903318db536f59e8e826)`);
316
+ }
317
+
318
+ const sKeystone_latest = await this.getSessionKeystone(sAddr_latest);
319
+
320
+ // Crytographically verify proof evolution and demand solutions
321
+ await verifyConnectProof({
322
+ proofFrame,
323
+ sKeystone_latest,
324
+ challengeUuid: this.challengeUuid!,
325
+ demandedIds: this.demandedIds!
326
+ });
327
+
328
+ // Persist the newly validated evolved session keystone tip
329
+ await metaspace.put({ ibGibs: [proofFrame], space });
330
+
331
+ if (logalot) { console.log(`${lc} connect validation successful! Connection upgraded to active sync session.`); }
332
+ this.isAuthenticated = true;
333
+
334
+ this.socketWrapper!.send(JSON.stringify({
335
+ type: SyncWebSocketMsgType.auth_ok
336
+ }));
337
+ } else {
338
+ throw new Error(`Unexpected message type ${msg.type} during connect phase (E: f67a0f47f8426c2b01af5bc3d0146b26)`);
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Executes the incoming sync request through the local SyncSagaCoordinator and sends response.
344
+ */
345
+ protected async executeIncomingSyncRequestAndRespond({
346
+ context
347
+ }: {
348
+ context: SyncSagaContextIbGib_V1;
349
+ }): Promise<void> {
350
+ const lc = `${this.lc}[${this.executeIncomingSyncRequestAndRespond.name}]`;
351
+ try {
352
+ if (logalot) { console.log(`${lc} executing incoming sync turn...`); }
353
+
354
+ if (!this.opts) { throw new Error(`opts not initialized. (E: 0c98186714e85b9a08bb9d98daada826)`); }
355
+ const { localCoordinator, localMetaspace, localSpace } = this.opts;
356
+ const localTempSpace = await this.ensureLocalTempSpace();
357
+
358
+ const responseCtx = await localCoordinator.continueSync({
359
+ sagaContext: context,
360
+ metaspace: localMetaspace,
361
+ mySpace: localSpace,
362
+ myTempSpace: localTempSpace,
363
+ peer: this,
364
+ });
365
+
366
+ if (responseCtx) {
367
+ const responsePayloads = responseCtx.payloadIbGibsDomain ?? [];
368
+ delete responseCtx.payloadIbGibsDomain;
369
+
370
+ // Save payloads to stream once authenticated by Alice
371
+ this.pendingResponsePayloadsToSend = responsePayloads;
372
+
373
+ this.socketWrapper!.send(JSON.stringify({
374
+ type: SyncWebSocketMsgType.sync_frame_response,
375
+ context: responseCtx
376
+ }));
377
+ } else {
378
+ if (logalot) { console.log(`${lc} synchronization session completed successfully.`); }
379
+ }
380
+ } catch (error) {
381
+ console.error(`${lc} executeIncomingSyncRequestAndRespond failed: ${extractErrorMsg(error)}`);
382
+ throw error;
383
+ }
384
+ }
385
+ }