@ibgib/space-gib 0.0.3 → 0.0.4

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 (62) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/IMPLEMENTATION.md +9 -13
  3. package/dist/client/bootstrap.mjs +1 -1
  4. package/dist/client/bootstrap.mjs.map +1 -1
  5. package/dist/client/chunk-NCXKCVYS.mjs +42 -0
  6. package/dist/client/chunk-NCXKCVYS.mjs.map +7 -0
  7. package/dist/client/chunk-ZUEU37Z5.mjs +1920 -0
  8. package/dist/client/chunk-ZUEU37Z5.mjs.map +7 -0
  9. package/dist/client/index.html +103 -5
  10. package/dist/client/index.mjs +1 -1
  11. package/dist/client/script.mjs +1 -1
  12. package/dist/client/style.css +466 -61
  13. package/dist/respec-gib.node.mjs +5 -0
  14. package/dist/server/server.mjs +294 -225
  15. package/dist/server/server.mjs.map +2 -2
  16. package/package.json +6 -6
  17. package/src/client/AUTO-GENERATED-version.mts +1 -1
  18. package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
  19. package/src/client/components/identity-header/identity-header.css +74 -0
  20. package/src/client/components/identity-header/identity-header.html +10 -0
  21. package/src/client/components/identity-header/identity-header.mts +361 -0
  22. package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
  23. package/src/client/components/identity-manager/identity-manager.css +467 -0
  24. package/src/client/components/identity-manager/identity-manager.html +113 -0
  25. package/src/client/components/identity-manager/identity-manager.mts +767 -0
  26. package/src/client/components/keystone-creator/keystone-creator.css +2 -76
  27. package/src/client/components/keystone-creator/keystone-creator.html +41 -26
  28. package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
  29. package/src/client/dev-tools/base-tools.mts +252 -0
  30. package/src/client/dev-tools/common.mts +217 -0
  31. package/src/client/dev-tools/phase-1.mts +156 -0
  32. package/src/client/dev-tools/phase-2.mts +143 -0
  33. package/src/client/dev-tools/phase-3.mts +189 -0
  34. package/src/client/dev-tools/phase-4-1.mts +197 -0
  35. package/src/client/dev-tools/phase-4-10.mts +884 -0
  36. package/src/client/dev-tools/phase-4-2.mts +388 -0
  37. package/src/client/dev-tools/phase-4-3.mts +391 -0
  38. package/src/client/dev-tools/phase-4-4.mts +374 -0
  39. package/src/client/dev-tools/phase-4-5.mts +376 -0
  40. package/src/client/dev-tools/phase-4-6.mts +273 -0
  41. package/src/client/dev-tools/phase-4-7.mts +399 -0
  42. package/src/client/dev-tools/phase-4-8.mts +430 -0
  43. package/src/client/dev-tools/phase-4-9.mts +398 -0
  44. package/src/client/dev-tools/phase-4.mts +1302 -0
  45. package/src/client/dev-tools.mts +52 -1194
  46. package/src/client/index.html +103 -5
  47. package/src/client/style.css +466 -61
  48. package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
  49. package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
  50. package/src/common/common-constants.mts +0 -0
  51. package/src/common/keystone-policies.json +40 -43
  52. package/src/common/keystone-policies.mts +3 -5
  53. package/src/server/path-helper.respec.mts +99 -94
  54. package/src/server/serve-gib/README.md +9 -0
  55. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
  56. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +1 -1
  57. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +31 -3
  58. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  59. package/dist/client/chunk-2KJC5XKE.mjs +0 -31
  60. package/dist/client/chunk-2KJC5XKE.mjs.map +0 -7
  61. package/dist/client/chunk-QNIXTRFO.mjs +0 -235
  62. package/dist/client/chunk-QNIXTRFO.mjs.map +0 -7
@@ -0,0 +1,376 @@
1
+ import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
+ import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
3
+ import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
4
+ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
5
+ import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
6
+ import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
7
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
+ import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
9
+ import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs';
10
+ import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
11
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
12
+ import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
13
+ import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
14
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
15
+
16
+ import { debugState, devLog, lc } from './common.mjs';
17
+
18
+ // Extend debugState to support our phase-specific storage
19
+ interface Phase45State {
20
+ domainI_latest?: KeystoneIbGib_V1;
21
+ targetV1?: any;
22
+ targetV2?: any;
23
+ }
24
+
25
+ const state: Phase45State = {};
26
+
27
+ export function init4_5bSetupButton(): void {
28
+ const btn = document.getElementById('btn-4-5b-setup') as HTMLButtonElement | null;
29
+ if (!btn) { return; }
30
+ btn.addEventListener('click', async () => {
31
+ try {
32
+ btn.disabled = true;
33
+ devLog('4.5B Setup: Generating Domain Keystone (I) and Target timeline V0 -> V1 in default local space...');
34
+
35
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
36
+ const space = await metaspace.getLocalUserSpace({});
37
+ if (!space) { throw new Error("No default space."); }
38
+
39
+ const keystoneService = new KeystoneService_V1();
40
+
41
+ // 1. Generate Domain Keystone (I) locally in default space
42
+ const domainI = await keystoneService.genesis({
43
+ masterSecret: 'test-sender-secret-phase4-5b',
44
+ configs: [
45
+ getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-5b'),
46
+ getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-5b'),
47
+ ],
48
+ metaspace,
49
+ space,
50
+ frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
51
+ });
52
+
53
+ debugState.domainI = domainI;
54
+ debugState.domainIMasterSecret = 'test-sender-secret-phase4-5b';
55
+
56
+ devLog(`4.5B Setup: ✓ Domain Keystone (I) created locally: ${getIbGibAddr({ ibGib: domainI })}`);
57
+
58
+ // 2. Post Genesis Domain Keystone to server
59
+ const apiBridge = new SpaceGibApiBridge();
60
+ const resGenesis = await apiBridge.postGenesisKeystone(domainI);
61
+ if (resGenesis.success) {
62
+ devLog(`4.5B Setup: ✓ Domain Keystone registered on server.`);
63
+ } else {
64
+ throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
65
+ }
66
+
67
+ // 3. Create target timeline root V0
68
+ const resV0 = await factory.firstGen({
69
+ parentIbGib: ROOT,
70
+ ib: 'timeline_root_partial_4_5b',
71
+ data: { type: 'root', label: 'Root4_5b', random: Math.random() },
72
+ dna: true,
73
+ nCounter: true,
74
+ tjp: { uuid: true, timestamp: true }
75
+ });
76
+ const r1_v0 = resV0.newIbGib;
77
+ await metaspace.persistTransformResult({ resTransform: resV0, space });
78
+ await metaspace.registerNewIbGib({ ibGib: r1_v0, space });
79
+
80
+ // 4. Mutate V0 -> V1 in default space
81
+ const r1_v1 = await mut8Timeline({
82
+ timeline: r1_v0,
83
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1_4_5b' } },
84
+ metaspace,
85
+ space,
86
+ });
87
+ state.targetV1 = r1_v1;
88
+
89
+ devLog(`4.5B Setup: ✓ Local timeline V0 -> V1 created. V1 Tip: ${getIbGibAddr({ ibGib: r1_v1 })}`);
90
+
91
+ // 5. Run Pass 1 Sync from default local space to server via WebSocket to seed V1 on the server
92
+ devLog('4.5B Setup: Seeding V1 to the server via WebSocket...');
93
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
94
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
95
+
96
+ const senderPeer1 = new SyncPeerWebSocketSender_V1({
97
+ classname: 'SyncPeerWebSocketSender_V1',
98
+ httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
99
+ wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
100
+ });
101
+
102
+ const coordinator1 = new SyncSagaCoordinator();
103
+ const sagaId1 = await getUUID();
104
+
105
+ await senderPeer1.initializeOpts({
106
+ localMetaspace: metaspace,
107
+ localSpace: space,
108
+ senderIdentity: domainI,
109
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
110
+ sagaId: sagaId1,
111
+ sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
112
+ sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
113
+ targetAddrs: [domainAddr]
114
+ });
115
+
116
+ const syncSaga1 = await coordinator1.sync({
117
+ domainIbGibs: [r1_v1],
118
+ senderIdentity: domainI,
119
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
120
+ peer: senderPeer1,
121
+ localSpace: space,
122
+ metaspace,
123
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
124
+ });
125
+ await syncSaga1.done;
126
+ devLog('4.5B Setup: ✓ Pass 1 Sync (V1 to server) complete.');
127
+
128
+ // 6. Retrieve evolved I tip from default space
129
+ const latestSenderAddr1 = await metaspace.getLatestAddr({
130
+ addr: domainAddr,
131
+ space,
132
+ });
133
+ if (!latestSenderAddr1) { throw new Error("Could not get latest sender address from default space."); }
134
+ const resGetLatestI1 = await metaspace.get({ addrs: [latestSenderAddr1], space });
135
+ const senderIdentityEvolved1 = resGetLatestI1.ibGibs![0] as KeystoneIbGib_V1;
136
+
137
+ // 7. Create remoteSpace (simulating a remote client)
138
+ devLog('4.5B Setup: Creating secondary local space simulating "remote" client...');
139
+ const remoteSpaceName = `remote-${await getUUID()}`;
140
+ const remoteSpace = await metaspace.createNewLocalSpace({
141
+ opts: {
142
+ allowCancel: false,
143
+ spaceName: remoteSpaceName,
144
+ getFnPrompt: metaspace.getFnPrompt!,
145
+ }
146
+ });
147
+ if (!remoteSpace) { throw new Error("Failed to create remote space"); }
148
+ await remoteSpace.initialized;
149
+
150
+ // 8. Copy V1 and its dependency graph from default space to remoteSpace
151
+ const graphV1 = await metaspace.getDependencyGraph({
152
+ ibGibAddr: getIbGibAddr({ ibGib: r1_v1 }),
153
+ space
154
+ });
155
+ await metaspace.put({ ibGibs: Object.values(graphV1), space: remoteSpace });
156
+ await metaspace.registerNewIbGib({ ibGib: r1_v1, space: remoteSpace });
157
+
158
+ // 9. Copy evolved I and its dependency graph from default space to remoteSpace
159
+ const graphI1 = await metaspace.getDependencyGraph({
160
+ ibGibAddr: latestSenderAddr1,
161
+ space
162
+ });
163
+ await metaspace.put({ ibGibs: Object.values(graphI1), space: remoteSpace });
164
+ await metaspace.registerNewIbGib({ ibGib: senderIdentityEvolved1, space: remoteSpace });
165
+
166
+ devLog('4.5B Setup: ✓ Copied V1 and identity I to remoteSpace.');
167
+
168
+ // 10. Mutate V1 -> V2 in remoteSpace ONLY
169
+ devLog('4.5B Setup: Mutating V1 -> V2 in remoteSpace...');
170
+ const r1_v2 = await mut8Timeline({
171
+ timeline: r1_v1,
172
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V2_4_5b' } },
173
+ metaspace,
174
+ space: remoteSpace,
175
+ });
176
+ state.targetV2 = r1_v2;
177
+ devLog(`4.5B Setup: ✓ Mutated to V2 in remoteSpace: ${getIbGibAddr({ ibGib: r1_v2 })}`);
178
+
179
+ // 11. Run Pass 2 Sync from remoteSpace to server via WebSocket to push V2
180
+ devLog('4.5B Setup: Syncing V2 from remoteSpace to the server...');
181
+ const senderPeer2 = new SyncPeerWebSocketSender_V1({
182
+ classname: 'SyncPeerWebSocketSender_V1',
183
+ httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
184
+ wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
185
+ });
186
+
187
+ const coordinator2 = new SyncSagaCoordinator();
188
+ const sagaId2 = await getUUID();
189
+
190
+ await senderPeer2.initializeOpts({
191
+ localMetaspace: metaspace,
192
+ localSpace: remoteSpace,
193
+ senderIdentity: senderIdentityEvolved1,
194
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
195
+ sagaId: sagaId2,
196
+ sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
197
+ sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
198
+ targetAddrs: [domainAddr]
199
+ });
200
+
201
+ const syncSaga2 = await coordinator2.sync({
202
+ domainIbGibs: [r1_v2],
203
+ senderIdentity: senderIdentityEvolved1,
204
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
205
+ peer: senderPeer2,
206
+ localSpace: remoteSpace,
207
+ metaspace,
208
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
209
+ });
210
+ await syncSaga2.done;
211
+ devLog('4.5B Setup: ✓ Pass 2 Sync (V2 to server) complete.');
212
+
213
+ // 12. Copy evolved I tip from remoteSpace back to default space so identity remains synchronized
214
+ const latestSenderAddr2 = await metaspace.getLatestAddr({
215
+ addr: domainAddr,
216
+ space: remoteSpace,
217
+ });
218
+ if (!latestSenderAddr2) { throw new Error("Could not get latest sender address from remoteSpace."); }
219
+ const resGetLatestI2 = await metaspace.get({ addrs: [latestSenderAddr2], space: remoteSpace });
220
+ const senderIdentityEvolved2 = resGetLatestI2.ibGibs![0] as KeystoneIbGib_V1;
221
+ state.domainI_latest = senderIdentityEvolved2;
222
+
223
+ const graphI2 = await metaspace.getDependencyGraph({
224
+ ibGibAddr: latestSenderAddr2,
225
+ space: remoteSpace
226
+ });
227
+ await metaspace.put({ ibGibs: Object.values(graphI2), space });
228
+ await metaspace.registerNewIbGib({ ibGib: senderIdentityEvolved2, space });
229
+
230
+ devLog('✓ 4.5B Setup Complete! Server has V2, default local space has V1. Ready for 4.5B Sync.');
231
+ btn.textContent = '✓ 4.5B Setup Complete';
232
+
233
+ const syncBtn = document.getElementById('btn-4-5b-sync') as HTMLButtonElement | null;
234
+ if (syncBtn) { syncBtn.disabled = false; }
235
+
236
+ } catch (error) {
237
+ devLog(`✗ 4.5B Setup FAILED: ${extractErrorMsg(error)}`);
238
+ console.error(error);
239
+ btn.disabled = false;
240
+ }
241
+ });
242
+ }
243
+
244
+ export function init4_5bSyncButton(): void {
245
+ const btn = document.getElementById('btn-4-5b-sync') as HTMLButtonElement | null;
246
+ if (!btn) { return; }
247
+ btn.addEventListener('click', async () => {
248
+ try {
249
+ btn.disabled = true;
250
+ devLog('4.5B Sync: Initiating WebSocket Sync from default local space (which has V1, server has V2)...');
251
+
252
+ const domainI = state.domainI_latest;
253
+ const targetV1 = state.targetV1;
254
+ if (!domainI || !targetV1) {
255
+ devLog('⚠ 4.5B Sync: Missing setup state. Please run Setup first.');
256
+ btn.disabled = false;
257
+ return;
258
+ }
259
+
260
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
261
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
262
+ const space = await metaspace.getLocalUserSpace({});
263
+ if (!space) { throw new Error("No default space."); }
264
+
265
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
266
+
267
+ const senderPeer = new SyncPeerWebSocketSender_V1({
268
+ classname: 'SyncPeerWebSocketSender_V1',
269
+ httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
270
+ wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
271
+ });
272
+
273
+ const coordinator = new SyncSagaCoordinator();
274
+ const sagaId = await getUUID();
275
+
276
+ await senderPeer.initializeOpts({
277
+ localMetaspace: metaspace,
278
+ localSpace: space,
279
+ senderIdentity: domainI,
280
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
281
+ sagaId,
282
+ sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
283
+ sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
284
+ targetAddrs: [domainAddr]
285
+ });
286
+
287
+ // Run Sync targeting our local tip V1.
288
+ // Since the server is ahead with V2, the coordinator should pull down V2.
289
+ const syncSaga = await coordinator.sync({
290
+ domainIbGibs: [targetV1],
291
+ senderIdentity: domainI,
292
+ fnSenderSecret: async () => 'test-sender-secret-phase4-5b',
293
+ peer: senderPeer,
294
+ localSpace: space,
295
+ metaspace,
296
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
297
+ });
298
+ await syncSaga.done;
299
+
300
+ devLog('✓ 4.5B Sync Execution Complete! Ready for 4.5B Check.');
301
+ btn.textContent = '✓ 4.5B Sync Run';
302
+
303
+ const checkBtn = document.getElementById('btn-4-5b-check') as HTMLButtonElement | null;
304
+ if (checkBtn) { checkBtn.disabled = false; }
305
+
306
+ } catch (error) {
307
+ devLog(`✗ 4.5B Sync FAILED: ${extractErrorMsg(error)}`);
308
+ console.error(error);
309
+ btn.disabled = false;
310
+ }
311
+ });
312
+ }
313
+
314
+ export function init4_5bCheckButton(): void {
315
+ const btn = document.getElementById('btn-4-5b-check') as HTMLButtonElement | null;
316
+ if (!btn) { return; }
317
+ btn.addEventListener('click', async () => {
318
+ try {
319
+ btn.disabled = true;
320
+ devLog('4.5B Check: Verifying that V2 was pulled down to default local space...');
321
+
322
+ const targetV2 = state.targetV2;
323
+ if (!targetV2) {
324
+ devLog('⚠ 4.5B Check: Missing target V2 in state. Did Setup run?');
325
+ btn.disabled = false;
326
+ return;
327
+ }
328
+
329
+ const targetV2Addr = getIbGibAddr({ ibGib: targetV2 });
330
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
331
+ const space = await metaspace.getLocalUserSpace({});
332
+ if (!space) { throw new Error("No default space."); }
333
+
334
+ // 1. Verify V2 now exists in default local space
335
+ const resGetV2 = await metaspace.get({ addr: targetV2Addr, space });
336
+ if (!resGetV2.success || resGetV2.ibGibs?.length !== 1) {
337
+ throw new Error(`V2 tip (${targetV2Addr}) is NOT present in local space!`);
338
+ }
339
+ const localV2 = resGetV2.ibGibs[0];
340
+ devLog(`4.5B Check: ✓ V2 Tip found locally. Label: "${localV2.data?.label}"`);
341
+
342
+ // 2. Fetch full dependency graph of V2 from local space
343
+ const localGraph = await metaspace.getDependencyGraph({
344
+ ibGibAddr: targetV2Addr,
345
+ space
346
+ });
347
+
348
+ // 3. Fetch full dependency graph of V2 from the server
349
+ devLog('4.5B Check: Fetching V2 dependency graph from server...');
350
+ const domainAddr = getIbGibAddr({ ibGib: state.domainI_latest! });
351
+ const apiBridge = new SpaceGibApiBridge();
352
+ const resServerGraph = await apiBridge.getIbGibGraph(domainAddr, targetV2Addr, true);
353
+ if (!resServerGraph.success || !resServerGraph.graph) {
354
+ throw new Error(`Failed to fetch V2 graph from server: ${resServerGraph.message}`);
355
+ }
356
+
357
+ // 4. Assert graphs are equivalent
358
+ const equal = graphsAreEquivalent({
359
+ graphA: localGraph,
360
+ graphB: resServerGraph.graph
361
+ });
362
+
363
+ if (equal) {
364
+ devLog('✓ 4.5B Check SUCCESS: V2 and all dependencies are fully equivalent on client and server!');
365
+ btn.textContent = '✓ 4.5B Check Success';
366
+ } else {
367
+ throw new Error("Dependency graphs on local space and server are NOT equivalent.");
368
+ }
369
+
370
+ } catch (error) {
371
+ devLog(`✗ 4.5B Check FAILED: ${extractErrorMsg(error)}`);
372
+ console.error(error);
373
+ btn.disabled = false;
374
+ }
375
+ });
376
+ }
@@ -0,0 +1,273 @@
1
+ import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
+ import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
3
+ import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
4
+ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
5
+ import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
6
+ import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
7
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
+ import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
9
+ import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs';
10
+ import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
11
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
12
+ import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
13
+ import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
14
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
15
+
16
+ import { debugState, devLog, lc } from './common.mjs';
17
+
18
+ // Extend debugState to support our phase-specific storage
19
+ interface Phase46State {
20
+ domainI_latest?: KeystoneIbGib_V1;
21
+ targetAlphaV1?: any;
22
+ targetBetaV2?: any;
23
+ }
24
+
25
+ const state: Phase46State = {};
26
+
27
+ export function init4_6bSetupButton(): void {
28
+ const btn = document.getElementById('btn-4-6b-setup') as HTMLButtonElement | null;
29
+ if (!btn) { return; }
30
+ btn.addEventListener('click', async () => {
31
+ try {
32
+ btn.disabled = true;
33
+ devLog('4.6B Setup: Generating Domain Keystone (I) and two independent target timelines (Alpha and Beta) in default local space...');
34
+
35
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
36
+ const space = await metaspace.getLocalUserSpace({});
37
+ if (!space) { throw new Error("No default space."); }
38
+
39
+ const keystoneService = new KeystoneService_V1();
40
+
41
+ // 1. Generate Domain Keystone (I) locally in default space
42
+ const domainI = await keystoneService.genesis({
43
+ masterSecret: 'test-sender-secret-phase4-6b',
44
+ configs: [
45
+ getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-6b'),
46
+ getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-6b'),
47
+ ],
48
+ metaspace,
49
+ space,
50
+ frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
51
+ });
52
+
53
+ state.domainI_latest = domainI;
54
+ debugState.domainI = domainI;
55
+ debugState.domainIMasterSecret = 'test-sender-secret-phase4-6b';
56
+
57
+ devLog(`4.6B Setup: ✓ Domain Keystone (I) created locally: ${getIbGibAddr({ ibGib: domainI })}`);
58
+
59
+ // 2. Post Genesis Domain Keystone to server
60
+ const apiBridge = new SpaceGibApiBridge();
61
+ const resGenesis = await apiBridge.postGenesisKeystone(domainI);
62
+ if (resGenesis.success) {
63
+ devLog(`4.6B Setup: ✓ Domain Keystone registered on server.`);
64
+ } else {
65
+ throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
66
+ }
67
+
68
+ // 3. Create Timeline A (root A -> mutant A1)
69
+ const resAlphaV0 = await factory.firstGen({
70
+ parentIbGib: ROOT,
71
+ ib: 'timeline_root_alpha_4_6b',
72
+ data: { type: 'root', label: 'Alpha4_6b', random: Math.random() },
73
+ dna: true,
74
+ nCounter: true,
75
+ tjp: { uuid: true, timestamp: true }
76
+ });
77
+ const r1_alpha_v0 = resAlphaV0.newIbGib;
78
+ await metaspace.persistTransformResult({ resTransform: resAlphaV0, space });
79
+ await metaspace.registerNewIbGib({ ibGib: r1_alpha_v0, space });
80
+
81
+ const r1_alpha_v1 = await mut8Timeline({
82
+ timeline: r1_alpha_v0,
83
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'A1_4_6b' } },
84
+ metaspace,
85
+ space,
86
+ });
87
+ state.targetAlphaV1 = r1_alpha_v1;
88
+ devLog(`4.6B Setup: ✓ Local Timeline A created. A1 Tip: ${getIbGibAddr({ ibGib: r1_alpha_v1 })}`);
89
+
90
+ // 4. Create Timeline B (root B -> mutant B1 -> mutant B2)
91
+ const resBetaV0 = await factory.firstGen({
92
+ parentIbGib: ROOT,
93
+ ib: 'timeline_root_beta_4_6b',
94
+ data: { type: 'root', label: 'Beta4_6b', random: Math.random() },
95
+ dna: true,
96
+ nCounter: true,
97
+ tjp: { uuid: true, timestamp: true }
98
+ });
99
+ const r1_beta_v0 = resBetaV0.newIbGib;
100
+ await metaspace.persistTransformResult({ resTransform: resBetaV0, space });
101
+ await metaspace.registerNewIbGib({ ibGib: r1_beta_v0, space });
102
+
103
+ const r1_beta_v1 = await mut8Timeline({
104
+ timeline: r1_beta_v0,
105
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'B1_4_6b' } },
106
+ metaspace,
107
+ space,
108
+ });
109
+
110
+ const r1_beta_v2 = await mut8Timeline({
111
+ timeline: r1_beta_v1,
112
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'B2_4_6b' } },
113
+ metaspace,
114
+ space,
115
+ });
116
+ state.targetBetaV2 = r1_beta_v2;
117
+ devLog(`4.6B Setup: ✓ Local Timeline B created. B2 Tip: ${getIbGibAddr({ ibGib: r1_beta_v2 })}`);
118
+
119
+ devLog('✓ 4.6B Setup Complete! Timelines created locally. Ready for 4.6B Sync.');
120
+ btn.textContent = '✓ 4.6B Setup Complete';
121
+
122
+ const syncBtn = document.getElementById('btn-4-6b-sync') as HTMLButtonElement | null;
123
+ if (syncBtn) { syncBtn.disabled = false; }
124
+
125
+ } catch (error) {
126
+ devLog(`✗ 4.6B Setup FAILED: ${extractErrorMsg(error)}`);
127
+ console.error(error);
128
+ btn.disabled = false;
129
+ }
130
+ });
131
+ }
132
+
133
+ export function init4_6bSyncButton(): void {
134
+ const btn = document.getElementById('btn-4-6b-sync') as HTMLButtonElement | null;
135
+ if (!btn) { return; }
136
+ btn.addEventListener('click', async () => {
137
+ try {
138
+ btn.disabled = true;
139
+ devLog('4.6B Sync: Initiating WebSocket Sync for both Timeline A and Timeline B in one call...');
140
+
141
+ const domainI = state.domainI_latest;
142
+ const targetAlphaV1 = state.targetAlphaV1;
143
+ const targetBetaV2 = state.targetBetaV2;
144
+ if (!domainI || !targetAlphaV1 || !targetBetaV2) {
145
+ devLog('⚠ 4.6B Sync: Missing setup state. Please run Setup first.');
146
+ btn.disabled = false;
147
+ return;
148
+ }
149
+
150
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
151
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
152
+ const space = await metaspace.getLocalUserSpace({});
153
+ if (!space) { throw new Error("No default space."); }
154
+
155
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
156
+
157
+ const senderPeer = new SyncPeerWebSocketSender_V1({
158
+ classname: 'SyncPeerWebSocketSender_V1',
159
+ httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
160
+ wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
161
+ });
162
+
163
+ const coordinator = new SyncSagaCoordinator();
164
+ const sagaId = await getUUID();
165
+
166
+ await senderPeer.initializeOpts({
167
+ localMetaspace: metaspace,
168
+ localSpace: space,
169
+ senderIdentity: domainI,
170
+ fnSenderSecret: async () => 'test-sender-secret-phase4-6b',
171
+ sagaId,
172
+ sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
173
+ sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
174
+ targetAddrs: [domainAddr]
175
+ });
176
+
177
+ // Run Sync targeting both Alpha A1 and Beta B2 tips
178
+ const syncSaga = await coordinator.sync({
179
+ domainIbGibs: [targetAlphaV1, targetBetaV2],
180
+ senderIdentity: domainI,
181
+ fnSenderSecret: async () => 'test-sender-secret-phase4-6b',
182
+ peer: senderPeer,
183
+ localSpace: space,
184
+ metaspace,
185
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
186
+ });
187
+ await syncSaga.done;
188
+
189
+ devLog('✓ 4.6B Sync Execution Complete! Ready for 4.6B Check.');
190
+ btn.textContent = '✓ 4.6B Sync Run';
191
+
192
+ const checkBtn = document.getElementById('btn-4-6b-check') as HTMLButtonElement | null;
193
+ if (checkBtn) { checkBtn.disabled = false; }
194
+
195
+ } catch (error) {
196
+ devLog(`✗ 4.6B Sync FAILED: ${extractErrorMsg(error)}`);
197
+ console.error(error);
198
+ btn.disabled = false;
199
+ }
200
+ });
201
+ }
202
+
203
+ export function init4_6bCheckButton(): void {
204
+ const btn = document.getElementById('btn-4-6b-check') as HTMLButtonElement | null;
205
+ if (!btn) { return; }
206
+ btn.addEventListener('click', async () => {
207
+ try {
208
+ btn.disabled = true;
209
+ devLog('4.6B Check: Verifying both Timeline A and Timeline B exist on the server with matching dependency graphs...');
210
+
211
+ const domainI = state.domainI_latest;
212
+ const targetAlphaV1 = state.targetAlphaV1;
213
+ const targetBetaV2 = state.targetBetaV2;
214
+ if (!domainI || !targetAlphaV1 || !targetBetaV2) {
215
+ devLog('⚠ 4.6B Check: Missing state. Did Setup and Sync run?');
216
+ btn.disabled = false;
217
+ return;
218
+ }
219
+
220
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
221
+ const alphaAddr = getIbGibAddr({ ibGib: targetAlphaV1 });
222
+ const betaAddr = getIbGibAddr({ ibGib: targetBetaV2 });
223
+
224
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
225
+ const space = await metaspace.getLocalUserSpace({});
226
+ if (!space) { throw new Error("No default space."); }
227
+
228
+ const apiBridge = new SpaceGibApiBridge();
229
+
230
+ // 1. Verify Timeline A (Alpha V1) on server
231
+ devLog('4.6B Check: Fetching Timeline A dependency graph from server...');
232
+ const resServerGraphAlpha = await apiBridge.getIbGibGraph(domainAddr, alphaAddr, true);
233
+ if (!resServerGraphAlpha.success || !resServerGraphAlpha.graph) {
234
+ throw new Error(`Failed to fetch Timeline A graph from server: ${resServerGraphAlpha.message}`);
235
+ }
236
+
237
+ const localGraphAlpha = await metaspace.getDependencyGraph({ ibGibAddr: alphaAddr, space });
238
+ const equalAlpha = graphsAreEquivalent({
239
+ graphA: localGraphAlpha,
240
+ graphB: resServerGraphAlpha.graph
241
+ });
242
+ if (!equalAlpha) {
243
+ throw new Error("Timeline A dependency graphs on local space and server are NOT equivalent.");
244
+ }
245
+ devLog('4.6B Check: ✓ Timeline A graphs are equivalent.');
246
+
247
+ // 2. Verify Timeline B (Beta V2) on server
248
+ devLog('4.6B Check: Fetching Timeline B dependency graph from server...');
249
+ const resServerGraphBeta = await apiBridge.getIbGibGraph(domainAddr, betaAddr, true);
250
+ if (!resServerGraphBeta.success || !resServerGraphBeta.graph) {
251
+ throw new Error(`Failed to fetch Timeline B graph from server: ${resServerGraphBeta.message}`);
252
+ }
253
+
254
+ const localGraphBeta = await metaspace.getDependencyGraph({ ibGibAddr: betaAddr, space });
255
+ const equalBeta = graphsAreEquivalent({
256
+ graphA: localGraphBeta,
257
+ graphB: resServerGraphBeta.graph
258
+ });
259
+ if (!equalBeta) {
260
+ throw new Error("Timeline B dependency graphs on local space and server are NOT equivalent.");
261
+ }
262
+ devLog('4.6B Check: ✓ Timeline B graphs are equivalent.');
263
+
264
+ devLog('✓ 4.6B Check SUCCESS: Both independent timelines are fully synced and identical on client and server!');
265
+ btn.textContent = '✓ 4.6B Check Success';
266
+
267
+ } catch (error) {
268
+ devLog(`✗ 4.6B Check FAILED: ${extractErrorMsg(error)}`);
269
+ console.error(error);
270
+ btn.disabled = false;
271
+ }
272
+ });
273
+ }