@ibgib/space-gib 0.0.2 → 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 (67) 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 +108 -8
  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 +815 -316
  15. package/dist/server/server.mjs.map +4 -4
  16. package/package.json +6 -6
  17. package/src/client/AUTO-GENERATED-version.mts +1 -1
  18. package/src/client/api/space-gib-api-bridge.mts +35 -0
  19. package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
  20. package/src/client/components/identity-header/identity-header.css +74 -0
  21. package/src/client/components/identity-header/identity-header.html +10 -0
  22. package/src/client/components/identity-header/identity-header.mts +361 -0
  23. package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
  24. package/src/client/components/identity-manager/identity-manager.css +467 -0
  25. package/src/client/components/identity-manager/identity-manager.html +113 -0
  26. package/src/client/components/identity-manager/identity-manager.mts +767 -0
  27. package/src/client/components/keystone-creator/keystone-creator.css +2 -76
  28. package/src/client/components/keystone-creator/keystone-creator.html +41 -26
  29. package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
  30. package/src/client/dev-tools/base-tools.mts +252 -0
  31. package/src/client/dev-tools/common.mts +217 -0
  32. package/src/client/dev-tools/phase-1.mts +156 -0
  33. package/src/client/dev-tools/phase-2.mts +143 -0
  34. package/src/client/dev-tools/phase-3.mts +189 -0
  35. package/src/client/dev-tools/phase-4-1.mts +197 -0
  36. package/src/client/dev-tools/phase-4-10.mts +884 -0
  37. package/src/client/dev-tools/phase-4-2.mts +388 -0
  38. package/src/client/dev-tools/phase-4-3.mts +391 -0
  39. package/src/client/dev-tools/phase-4-4.mts +374 -0
  40. package/src/client/dev-tools/phase-4-5.mts +376 -0
  41. package/src/client/dev-tools/phase-4-6.mts +273 -0
  42. package/src/client/dev-tools/phase-4-7.mts +399 -0
  43. package/src/client/dev-tools/phase-4-8.mts +430 -0
  44. package/src/client/dev-tools/phase-4-9.mts +398 -0
  45. package/src/client/dev-tools/phase-4.mts +1302 -0
  46. package/src/client/dev-tools.mts +55 -1096
  47. package/src/client/index.html +108 -8
  48. package/src/client/style.css +466 -61
  49. package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
  50. package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
  51. package/src/common/common-constants.mts +0 -0
  52. package/src/common/keystone-policies.json +40 -43
  53. package/src/common/keystone-policies.mts +4 -6
  54. package/src/server/path-helper.respec.mts +99 -94
  55. package/src/server/serve-gib/README.md +9 -0
  56. package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +1 -1
  57. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
  58. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +4 -4
  59. package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +1 -1
  60. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +37 -5
  61. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  62. package/dist/client/chunk-BL2SGXS4.mjs +0 -18994
  63. package/dist/client/chunk-RDTAT5G4.mjs +0 -235
  64. package/dist/client/chunk-RDTAT5G4.mjs.map +0 -7
  65. package/dist/client/chunk-RE7XSMHH.mjs +0 -31
  66. package/dist/client/chunk-RE7XSMHH.mjs.map +0 -7
  67. package/dist/client/chunk-YUSGN3J4.mjs +0 -23119
@@ -1,1103 +1,32 @@
1
1
  /**
2
2
  * @module client/dev-tools
3
3
  *
4
- * Wires up the Dev Tools panel button handlers for manual testing during
5
- * development. Import this from index.mts inside the DOMContentLoaded handler.
6
- *
7
- * ## intent
8
- *
9
- * Remove or gate this module once the real sync WebSocket endpoint is confirmed
10
- * working end-to-end.
4
+ * Facade entry point for Dev Tools panel button handlers.
5
+ * Imports and wires up all modular sub-file handlers under dev-tools/.
11
6
  */
12
7
 
13
- import { extractErrorMsg, getTimestamp, getUUID, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
14
- import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
15
- import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
16
- import { getIbGibAddr, } from '@ibgib/ts-gib/dist/helper.mjs';
17
- import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
18
- import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
19
- import { KeystoneIbGib_V1, KeystoneReplenishStrategy } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
20
- import { createManagePoolConfig } from '@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs';
21
- import { KeystoneStrategyFactory } from '@ibgib/core-gib/dist/keystone/strategy/keystone-strategy-factory.mjs';
22
- import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
23
- import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
24
- import { KEYSTONE_VERB_CONNECT, POOL_ID_CONNECT, POOL_ID_SYNC } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
25
- import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
26
9
 
27
- import { GLOBAL_LOG_A_LOT } from './constants.mjs';
10
+ import { devLog, debugState, lc } from './dev-tools/common.mjs';
28
11
  import {
29
- SESSION_KEYSTONE_POLICY, getConnectChallenge, getSpaceGibPoolConfig
30
- } from "../common/keystone-policies.mjs";
31
- import { SpaceGibApiBridge } from './api/space-gib-api-bridge.mjs';
32
-
33
- const logalot = GLOBAL_LOG_A_LOT
34
- const lc = '[dev-tools]';
35
-
36
- interface DebugState {
37
- domainI?: KeystoneIbGib_V1;
38
- domainIMasterSecret?: string;
39
- targetX?: IbGib_V1;
40
- sessionS?: KeystoneIbGib_V1;
41
- sessionSecret?: string;
42
- senderPeer?: SyncPeerWebSocketSender_V1;
43
- sagaId?: string;
44
- }
45
-
46
- export const debugState: DebugState = {};
47
- (window as any).ibgibDebugState = debugState;
48
-
49
- // ---------------------------------------------------------------------------
50
- // Dev panel log helper
51
- // ---------------------------------------------------------------------------
52
-
53
- export function devLog(msg: string): void {
54
- const logEl = document.getElementById('dev-panel-log') as HTMLPreElement | null;
55
- if (!logEl) { return; }
56
- const timestamp = new Date().toISOString().slice(11, 23); // HH:MM:SS.mmm
57
- logEl.textContent = `[${timestamp}] ${msg}\n` + logEl.textContent;
58
- }
59
-
60
- // ---------------------------------------------------------------------------
61
- // Test WebSocket button
62
- // ---------------------------------------------------------------------------
63
-
64
- let _ws: WebSocket | null = null;
65
-
66
- function initWsTestButton(): void {
67
- const lc_fn = `${lc}[initWsTestButton]`;
68
- const btn = document.getElementById('btn-test-ws') as HTMLButtonElement | null;
69
- if (!btn) {
70
- console.warn(`${lc_fn} btn-test-ws not found — skipping`);
71
- return;
72
- }
73
-
74
- btn.addEventListener('click', () => {
75
- try {
76
- if (_ws && _ws.readyState === WebSocket.OPEN) {
77
- // Already connected — send a test ping instead
78
- _ws.send(JSON.stringify({ ping: 'hello from client', ts: Date.now() }));
79
- devLog('→ sent ping on existing connection');
80
- return;
81
- }
82
-
83
- // Build the WebSocket URL from the current origin (wss:// if https://)
84
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
85
- const wsUrl = `${protocol}//${location.host}/api/debug/ws-echo`;
86
- devLog(`→ connecting to ${wsUrl}`);
87
-
88
- _ws = new WebSocket(wsUrl);
89
-
90
- _ws.addEventListener('open', () => {
91
- devLog('✓ WebSocket connected');
92
- btn.textContent = 'Send WS Ping';
93
- });
94
-
95
- _ws.addEventListener('message', (ev) => {
96
- devLog(`← ${ev.data}`);
97
- });
98
-
99
- _ws.addEventListener('close', (ev) => {
100
- devLog(`✗ WebSocket closed (code ${ev.code})`);
101
- btn.textContent = 'Test WebSocket';
102
- _ws = null;
103
- });
104
-
105
- _ws.addEventListener('error', (ev) => {
106
- devLog(`✗ WebSocket error — check console`);
107
- console.error(`${lc_fn} WebSocket error`, ev);
108
- });
109
-
110
- } catch (error) {
111
- devLog(`✗ ${extractErrorMsg(error)}`);
112
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
113
- }
114
- });
115
- }
116
-
117
- // ---------------------------------------------------------------------------
118
- // Print Dev State button
119
- // ---------------------------------------------------------------------------
120
-
121
- function initPrintStateButton(): void {
122
- const btn = document.getElementById('btn-print-dev-state') as HTMLButtonElement | null;
123
- if (!btn) return;
124
- btn.addEventListener('click', () => {
125
- devLog(`Printing debug state to console...`);
126
- console.dir(debugState);
127
- });
128
- }
129
-
130
- // ---------------------------------------------------------------------------
131
- // Create Domain Keystone (I) button
132
- // ---------------------------------------------------------------------------
133
-
134
- function initCreateDomainKeystoneButton(): void {
135
- const lc_fn = `${lc}[initCreateDomainKeystoneButton]`;
136
- const btn = document.getElementById('btn-create-domain-keystone') as HTMLButtonElement | null;
137
- if (!btn) return;
138
-
139
- btn.addEventListener('click', async () => {
140
- try {
141
- btn.disabled = true;
142
- devLog('Generating dummy Domain Keystone (I)...');
143
-
144
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
145
- const space = await metaspace.getLocalUserSpace({});
146
- if (!space) { throw new Error("No default space found in metaspace."); }
147
-
148
- const masterSecret = 'password'; // Hardcoded for debug as requested
149
- const keystoneService = new KeystoneService_V1();
150
-
151
- const domainI = await keystoneService.genesis({
152
- masterSecret,
153
- configs: [
154
- createManagePoolConfig({
155
- id: 'default',
156
- salt: await getUUID(),
157
- replenishStrategy: KeystoneReplenishStrategy.topUp,
158
- }),
159
- ],
160
- metaspace,
161
- space,
162
- frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
163
- });
164
-
165
- const iAddr = getIbGibAddr({ ibGib: domainI });
166
- devLog(`✓ Local genesis complete: ${iAddr}`);
167
-
168
- debugState.domainI = domainI;
169
- debugState.domainIMasterSecret = masterSecret;
170
-
171
- // Post to server
172
- devLog(`Posting genesis keystone to server...`);
173
- const apiBridge = new SpaceGibApiBridge();
174
- const resSync = await apiBridge.postGenesisKeystone(domainI);
175
- if (!resSync.success) {
176
- devLog(`✗ Server rejected genesis keystone: ${resSync.message}`);
177
- btn.disabled = false;
178
- return;
179
- }
180
-
181
- devLog(`✓ Server accepted Domain Keystone (I)`);
182
- btn.textContent = '✓ Domain Keystone Created';
183
-
184
- // Enable next step
185
- const nextBtn = document.getElementById('btn-create-test-ibgib') as HTMLButtonElement;
186
- if (nextBtn) nextBtn.disabled = false;
187
-
188
- } catch (error) {
189
- devLog(`✗ ${extractErrorMsg(error)}`);
190
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
191
- btn.disabled = false;
192
- }
193
- });
194
- }
195
-
196
- // ---------------------------------------------------------------------------
197
- // Create Test IbGib button
198
- // ---------------------------------------------------------------------------
199
-
200
- function initCreateTestIbGibButton(): void {
201
- const lc_fn = `${lc}[initCreateTestIbGibButton]`;
202
- const btn = document.getElementById('btn-create-test-ibgib') as HTMLButtonElement | null;
203
- if (!btn) {
204
- console.warn(`${lc_fn} btn-create-test-ibgib not found — skipping`);
205
- return;
206
- }
207
-
208
- btn.addEventListener('click', async () => {
209
- try {
210
- devLog('Generating dummy X^Xtjp ibgib...');
211
- const resX = await factory.firstGen({
212
- parentIbGib: ROOT,
213
- ib: 'test data',
214
- data: { hello: 'world', random: Math.random() },
215
- dna: true,
216
- nCounter: true,
217
- tjp: { uuid: true, timestamp: true }
218
- });
219
- const xIbGib = resX.newIbGib;
220
- const xAddr = getIbGibAddr({ ibGib: xIbGib });
221
-
222
- debugState.targetX = xIbGib;
223
- devLog(`✓ Created X: ${xAddr}`);
224
- btn.textContent = '✓ Test IbGib (X) Created';
225
-
226
- // Enable next step
227
- const nextBtn = document.getElementById('btn-create-session-keystone') as HTMLButtonElement;
228
- if (nextBtn) nextBtn.disabled = false;
229
- } catch (error) {
230
- devLog(`✗ ${extractErrorMsg(error)}`);
231
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
232
- }
233
- });
234
- }
235
-
236
- // ---------------------------------------------------------------------------
237
- // Create Session Keystone (S^Stjp) button
238
- // ---------------------------------------------------------------------------
239
-
240
- function initCreateSessionKeystoneButton(): void {
241
- const lc_fn = `${lc}[initCreateSessionKeystoneButton]`;
242
- const btn = document.getElementById('btn-create-session-keystone') as HTMLButtonElement | null;
243
- if (!btn) {
244
- console.warn(`${lc_fn} btn-create-session-keystone not found — skipping`);
245
- return;
246
- }
247
-
248
- btn.addEventListener('click', async () => {
249
- try {
250
- devLog('Generating Session Keystone (S^Stjp)...');
251
-
252
- const domainI = debugState.domainI;
253
- const targetX = debugState.targetX;
254
-
255
- if (!domainI) { devLog('⚠ No domain keystone (I) found in state. Please Create Domain Keystone first.'); return; }
256
- if (!targetX) { devLog('⚠ No target ibgib (X) found in state. Please Create Test IbGib first.'); return; }
257
-
258
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
259
- const space = await metaspace.getLocalUserSpace({});
260
- if (!space) { throw new Error("No default space found in metaspace."); }
261
-
262
- const sessionSecret = 'ephemeral-' + Math.random().toString();
263
- const keystoneService = new KeystoneService_V1();
264
-
265
- console.warn(`${lc}[NAG] placeholder genesis keystone config right now (W: 69b108687cf8bec0f9a8e148bcca8d26)`);
266
- const sIbGib = await keystoneService.genesis({
267
- masterSecret: sessionSecret,
268
- configs: [
269
- {
270
- id: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.ID,
271
- salt: await getUUID(),
272
- type: SESSION_KEYSTONE_POLICY.COMMON.TYPE,
273
- algo: SESSION_KEYSTONE_POLICY.COMMON.ALGO,
274
- rounds: SESSION_KEYSTONE_POLICY.COMMON.ROUNDS,
275
- behavior: {
276
- size: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SIZE,
277
- replenish: SESSION_KEYSTONE_POLICY.COMMON.REPLENISH,
278
- selectSequentially: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SELECT_SEQUENTIALLY,
279
- selectRandomly: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SELECT_RANDOMLY,
280
- targetBindingChars: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.TARGET_BINDING_CHARS,
281
- },
282
- allowedVerbs: [],
283
- },
284
- {
285
- id: SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID,
286
- salt: await getUUID(),
287
- type: SESSION_KEYSTONE_POLICY.COMMON.TYPE,
288
- algo: SESSION_KEYSTONE_POLICY.COMMON.ALGO,
289
- rounds: SESSION_KEYSTONE_POLICY.COMMON.ROUNDS,
290
- behavior: {
291
- size: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SIZE,
292
- replenish: SESSION_KEYSTONE_POLICY.COMMON.REPLENISH,
293
- selectSequentially: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SELECT_SEQUENTIALLY,
294
- selectRandomly: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SELECT_RANDOMLY,
295
- targetBindingChars: SESSION_KEYSTONE_POLICY.CONNECT_POOL.TARGET_BINDING_CHARS,
296
- },
297
- allowedVerbs: [SESSION_KEYSTONE_POLICY.CONNECT_POOL.VERB],
298
- }
299
- ],
300
- metaspace,
301
- space,
302
- frameDetails: {
303
- client: 'space-gib-web-session',
304
- target_I: domainI ? getIbGibAddr({ ibGib: domainI }) : undefined,
305
- target_X: targetX ? getIbGibAddr({ ibGib: targetX }) : undefined,
306
- }
307
- });
308
-
309
- const sAddr = getIbGibAddr({ ibGib: sIbGib });
310
- debugState.sessionS = sIbGib;
311
- debugState.sessionSecret = sessionSecret;
312
-
313
- devLog(`✓ Created Session Keystone: ${sAddr}`);
314
- btn.textContent = '✓ Session Keystone Created';
315
-
316
- // Enable next step
317
- const nextBtn = document.getElementById('btn-evolve-domain-keystone') as HTMLButtonElement;
318
- if (nextBtn) nextBtn.disabled = false;
319
- } catch (error) {
320
- devLog(`✗ ${extractErrorMsg(error)}`);
321
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
322
- }
323
- });
324
- }
325
-
326
- // ---------------------------------------------------------------------------
327
- // Evolve Domain Keystone (I^I1) button
328
- // ---------------------------------------------------------------------------
329
-
330
- function initEvolveDomainKeystoneButton(): void {
331
- const lc_fn = `${lc}[initEvolveDomainKeystoneButton]`;
332
- const btn = document.getElementById('btn-evolve-domain-keystone') as HTMLButtonElement | null;
333
- if (!btn) {
334
- console.warn(`${lc_fn} btn-evolve-domain-keystone not found — skipping`);
335
- return;
336
- }
337
-
338
- btn.addEventListener('click', async () => {
339
- try {
340
- btn.disabled = true;
341
- devLog('Evolving Domain Keystone (I^I1) with sync claim...');
342
-
343
- const domainI = debugState.domainI;
344
- const masterSecret = debugState.domainIMasterSecret;
345
- const sessionS = debugState.sessionS;
346
-
347
- if (!domainI || !masterSecret) { devLog('⚠ No domain keystone (I) found. Please Create Domain Keystone first.'); return; }
348
- if (!sessionS) { devLog('⚠ No session keystone (S) found. Please Create Session Keystone first.'); return; }
349
-
350
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
351
- const space = await metaspace.getLocalUserSpace({});
352
- if (!space) { throw new Error("No default space found in metaspace."); }
353
-
354
- const keystoneService = new KeystoneService_V1();
355
- const sAddr = getIbGibAddr({ ibGib: sessionS });
356
-
357
- devLog('Solving challenges to authorize sync...');
358
- const evolvedI = await keystoneService.sign({
359
- latestKeystone: domainI,
360
- masterSecret,
361
- claim: {
362
- target: sAddr,
363
- verb: 'sync'
364
- },
365
- metaspace,
366
- space
367
- });
368
-
369
- const evolvedAddr = getIbGibAddr({ ibGib: evolvedI });
370
- devLog(`✓ Local evolution complete: ${evolvedAddr}`);
371
-
372
- // Update state with new tip
373
- debugState.domainI = evolvedI;
374
-
375
- devLog('Posting evolution to server...');
376
- const apiBridge = new SpaceGibApiBridge();
377
- // We pass the domain address (from the original TJP) and the session keystone
378
- const domainAddr = getIbGibAddr({ ibGib: domainI });
379
- const resSync = await apiBridge.putEvolveKeystone(domainAddr, evolvedI, [sessionS]);
380
-
381
- if (!resSync.success) {
382
- devLog(`✗ Server rejected evolution: ${resSync.message}`);
383
- btn.disabled = false;
384
- return;
385
- }
386
-
387
- devLog('✓ Server accepted Domain Keystone evolution!');
388
- btn.textContent = '✓ Domain Keystone Evolved';
389
-
390
- // Enable next step
391
- const nextBtn = document.getElementById('btn-perform-sync') as HTMLButtonElement;
392
- if (nextBtn) nextBtn.disabled = false;
393
-
394
- } catch (error) {
395
- devLog(`✗ ${extractErrorMsg(error)}`);
396
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
397
- btn.disabled = false;
398
- }
399
- });
400
- }
401
-
402
- // ---------------------------------------------------------------------------
403
- // Perform Sync Connect (S) button
404
- // ---------------------------------------------------------------------------
405
-
406
- function initPerformSyncButton(): void {
407
- const lc_fn = `${lc}[initPerformSyncButton]`;
408
- const btn = document.getElementById('btn-perform-sync') as HTMLButtonElement | null;
409
- if (!btn) return;
410
-
411
- btn.addEventListener('click', async () => {
412
- try {
413
- debugger; // walk through sync
414
- btn.disabled = true;
415
- devLog('Initiating Sync Connect via WebSocket...');
416
-
417
- const sessionS = debugState.sessionS;
418
- const sessionSecret = debugState.sessionSecret;
419
- const domainI = debugState.domainI;
420
-
421
- if (!sessionS || !sessionSecret || !domainI) {
422
- devLog('⚠ Incomplete state. Please complete steps 1-4.');
423
- btn.disabled = false;
424
- return;
425
- }
426
-
427
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
428
- const space = await metaspace.getLocalUserSpace({});
429
- if (!space) { throw new Error("No space."); }
430
-
431
- devLog('Pre-solving upfront picket-fence challenge...');
432
- const connectPool = (sessionS.data?.challengePools ?? []).find(p => p.id === SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID);
433
- if (!connectPool) {
434
- throw new Error(`Session keystone missing "${SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID}" pool`);
435
- }
436
-
437
- const { challengeId } = getConnectChallenge(sessionS);
438
- const strategy = KeystoneStrategyFactory.create({ config: connectPool.config });
439
- const poolSecret = await strategy.derivePoolSecret({ masterSecret: sessionSecret });
440
- const solution = await strategy.generateSolution({
441
- poolSecret,
442
- poolId: SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID,
443
- challengeId
444
- });
445
-
446
- const sAddr = getIbGibAddr({ ibGib: sessionS });
447
- const domainAddr = getIbGibAddr({ ibGib: domainI });
448
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
449
- const wsUrl = `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}` +
450
- `?sAddr=${encodeURIComponent(sAddr)}` +
451
- `&solution=${solution.value}`;
452
-
453
- devLog(`→ connecting to ${wsUrl}`);
454
- const ws = new WebSocket(wsUrl);
455
-
456
- ws.addEventListener('open', () => {
457
- devLog('✓ WebSocket connected. Waiting for server challenge...');
458
- });
459
-
460
- ws.addEventListener('message', async (ev) => {
461
- try {
462
- const msg = JSON.parse(ev.data);
463
- devLog(`← received: ${msg.type ?? 'message'}`);
464
-
465
- if (msg.type === 'auth-challenge-init') {
466
- devLog('→ sending auth-init with sAddr...');
467
- ws.send(JSON.stringify({
468
- type: 'auth-init',
469
- sAddr: getIbGibAddr({ ibGib: sessionS })
470
- }));
471
- } else if (msg.type === 'auth-challenge') {
472
- const { challengeUuid, demandedIds } = msg;
473
- devLog(`→ server demanded ${demandedIds.length} ids. Signing connect proof...`);
474
-
475
- const keystoneService = new KeystoneService_V1();
476
- const proofFrame = await keystoneService.sign({
477
- latestKeystone: sessionS,
478
- masterSecret: sessionSecret,
479
- poolId: POOL_ID_CONNECT,
480
- requiredChallengeIds: demandedIds,
481
- claim: {
482
- verb: KEYSTONE_VERB_CONNECT,
483
- target: challengeUuid
484
- },
485
- metaspace,
486
- space
487
- });
488
-
489
- devLog('→ sending auth-proof...');
490
- ws.send(JSON.stringify({
491
- type: 'auth-proof',
492
- proofFrame
493
- }));
494
- } else if (msg.type === 'auth-ok') {
495
- devLog('✓ Connect SUCCESS! Sync session authorized.');
496
- btn.textContent = '✓ Sync Authorized';
497
- } else if (msg.type === 'auth-fail') {
498
- devLog(`✗ Connect FAILED: ${msg.message}`);
499
- btn.disabled = false;
500
- }
501
- } catch (error) {
502
- devLog(`✗ Message handler error: ${extractErrorMsg(error)}`);
503
- console.error(`${lc_fn} Message handler error:`, error);
504
- btn.disabled = false;
505
- }
506
- });
507
-
508
- ws.addEventListener('close', (ev) => {
509
- devLog(`✗ WebSocket closed (code ${ev.code})`);
510
- btn.disabled = false;
511
- });
512
-
513
- ws.addEventListener('error', () => {
514
- devLog(`✗ WebSocket error — check server`);
515
- btn.disabled = false;
516
- });
517
-
518
- } catch (error) {
519
- devLog(`✗ ${extractErrorMsg(error)}`);
520
- console.error(`${lc_fn} ${extractErrorMsg(error)}`);
521
- btn.disabled = false;
522
- }
523
- });
524
- }
525
-
526
- // ---------------------------------------------------------------------------
527
- // Phase 1B: Standardized Setup / Sync / Check testing loop
528
- // ---------------------------------------------------------------------------
529
-
530
- function init1bSetupButton(): void {
531
- const lc_fn = `${lc}[init1bSetupButton]`;
532
- const btn = document.getElementById('btn-1b-setup') as HTMLButtonElement | null;
533
- if (!btn) return;
534
-
535
- btn.addEventListener('click', async () => {
536
- try {
537
- btn.disabled = true;
538
- devLog('1B Setup: Generating Alice\'s long-lived Domain Keystone (I) and Target (X)...');
539
-
540
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
541
- const space = await metaspace.getLocalUserSpace({});
542
- if (!space) { throw new Error("No default space."); }
543
-
544
- const masterSecret = 'test-sender-secret-phase1';
545
- const keystoneService = new KeystoneService_V1();
546
-
547
- // 1. Create Genesis Domain Keystone (I^Itjp) in local sourceSpace
548
- const domainI = await keystoneService.genesis({
549
- masterSecret,
550
- configs: [
551
- getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase1'),
552
- getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase1'),
553
- ],
554
- metaspace,
555
- space,
556
- frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
557
- });
558
-
559
- debugState.domainI = domainI;
560
- debugState.domainIMasterSecret = masterSecret;
561
-
562
- devLog(`1B Setup: ✓ Domain Keystone (I) created locally: ${getIbGibAddr({ ibGib: domainI })}`);
563
- devLog(`1B Setup: Starting postGenesisKeystone...`);
564
-
565
- // 2. Post Genesis Domain Keystone to receiver/server
566
- const apiBridge = new SpaceGibApiBridge();
567
- const resGenesis = await apiBridge.postGenesisKeystone(domainI);
568
- if (resGenesis.success) {
569
- devLog(`1B Setup: ✓ Domain Keystone registered and stored on receiver (server).`);
570
- } else {
571
- devLog(`1B Setup: X postGenesisKeystone failed: ${resGenesis.message}.`);
572
- throw new Error(`1B Setup: Server rejected genesis domain keystone: ${resGenesis.message}`);
573
- }
574
-
575
- // 3. Create Test IbGib (X) locally
576
- const resX = await factory.firstGen({
577
- parentIbGib: ROOT,
578
- ib: 'test data',
579
- data: { hello: 'world', random: Math.random() },
580
- dna: true,
581
- nCounter: true,
582
- tjp: { uuid: true, timestamp: true }
583
- });
584
- debugState.targetX = resX.newIbGib;
585
- devLog(`1B Setup: ✓ Target (X) created locally: ${getIbGibAddr({ ibGib: resX.newIbGib })}`);
586
-
587
- devLog('✓ 1B Setup Complete! Ready for 1B Sync.');
588
- btn.textContent = '✓ 1B Setup Complete';
589
-
590
- // Enable next button in the phase flow
591
- const syncBtn = document.getElementById('btn-1b-sync') as HTMLButtonElement | null;
592
- if (syncBtn) syncBtn.disabled = false;
593
-
594
- } catch (error) {
595
- devLog(`✗ 1B Setup FAILED: ${extractErrorMsg(error)}`);
596
- console.error(`${lc_fn} 1B Setup error:`, error);
597
- btn.disabled = false;
598
- }
599
- });
600
- }
601
-
602
- function init1bSyncButton(): void {
603
- const lc_fn = `${lc}[init1bSyncButton]`;
604
- const btn = document.getElementById('btn-1b-sync') as HTMLButtonElement | null;
605
- if (!btn) return;
606
-
607
- btn.addEventListener('click', async () => {
608
- try {
609
- btn.disabled = true;
610
- devLog('1B Sync: Executing senderCoordinator.sync(...) using WebSocket Peer...');
611
-
612
- const domainI = debugState.domainI;
613
- const targetX = debugState.targetX;
614
- if (!domainI || !targetX) {
615
- devLog('⚠ 1B Sync: Missing setup state. Please run Setup first.');
616
- btn.disabled = false;
617
- return;
618
- }
619
-
620
- const domainAddr = getIbGibAddr({ ibGib: domainI });
621
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
622
- const space = await metaspace.getLocalUserSpace({});
623
- if (!space) { throw new Error("No default space."); }
624
-
625
- // Instantiate WebSocket sender peer
626
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
627
- const senderPeer = new SyncPeerWebSocketSender_V1({
628
- classname: 'SyncPeerWebSocketSender_V1',
629
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
630
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
631
- });
632
-
633
- const coordinator = new SyncSagaCoordinator();
634
- const sagaId = await getUUID();
635
- debugState.sagaId = sagaId;
636
- debugState.senderPeer = senderPeer;
637
-
638
- await senderPeer.initializeOpts({
639
- localMetaspace: metaspace,
640
- localSpace: space,
641
- senderIdentity: domainI,
642
- fnSenderSecret: async () => debugState.domainIMasterSecret!,
643
- sagaId,
644
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
645
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
646
- targetAddrs: [domainAddr]
647
- });
648
-
649
- try {
650
- // Execute sync saga — triggers establishSessionIdentity internally!
651
- const syncSaga = await coordinator.sync({
652
- domainIbGibs: [targetX],
653
- senderIdentity: domainI,
654
- fnSenderSecret: async () => debugState.domainIMasterSecret!,
655
- peer: senderPeer,
656
- localSpace: space,
657
- metaspace,
658
- conflictStrategy: 'optimisticWithLCS' as any
659
- });
660
- await syncSaga.done;
661
- } catch (err) {
662
- // connection/sync error is fine/expected right now since connection is in Phase 2
663
- devLog(`1B Sync: Coordinator sync executed (establish phase successfully run; connection/sync errors expected in 1B): ${extractErrorMsg(err)}`);
664
- }
665
-
666
- devLog('✓ 1B Sync Execution Complete! Ready for State Checks.');
667
- btn.textContent = '✓ 1B Sync Run';
668
-
669
- // Enable check button
670
- const checkBtn = document.getElementById('btn-1b-check') as HTMLButtonElement | null;
671
- if (checkBtn) checkBtn.disabled = false;
672
-
673
- } catch (error) {
674
- devLog(`✗ 1B Sync FAILED: ${extractErrorMsg(error)}`);
675
- console.error(`${lc_fn} 1B Sync error:`, error);
676
- btn.disabled = false;
677
- }
678
- });
679
- }
680
-
681
- function init1bCheckButton(): void {
682
- const lc_fn = `${lc}[init1bCheckButton]`;
683
- const btn = document.getElementById('btn-1b-check') as HTMLButtonElement | null;
684
- if (!btn) return;
685
-
686
- btn.addEventListener('click', async () => {
687
- try {
688
- devLog('1B Check: Asserting cryptographic and durable state expectations from respec...');
689
-
690
- debugger; // allow for walkthrough 1B check
691
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
692
- const space = await metaspace.getLocalUserSpace({});
693
- if (!space) { throw new Error("No default space."); }
694
-
695
- const domainI = debugState.domainI!;
696
- const targetX = debugState.targetX!;
697
- const xAddr = getIbGibAddr({ ibGib: targetX });
698
-
699
- // 1. Resolve evolved sender identity I1 locally
700
- const newSenderIdentityAddr = await metaspace.getLatestAddr({
701
- addr: getIbGibAddr({ ibGib: domainI }),
702
- space
703
- });
704
-
705
- if (!newSenderIdentityAddr) {
706
- devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
707
- return;
708
- }
709
- devLog(`✓ Check: Evolved Domain Keystone (I1) created and stored locally.`);
710
-
711
- const getRes = await metaspace.get({ addrs: [newSenderIdentityAddr], space });
712
- const newSenderIdentity = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
713
-
714
- if (!newSenderIdentity) {
715
- devLog('✗ Check: Failed to load I1 from local space.');
716
- return;
717
- }
718
-
719
- const syncProof = newSenderIdentity.data?.proofs?.find(p => p.claim?.verb === 'sync');
720
- if (!syncProof) {
721
- devLog('✗ Check: I1 is missing sync-verb claim proof!');
722
- } else {
723
- devLog('✓ Check: I1 contains valid sync-verb claim proof.');
724
- }
725
-
726
- const sessionIdentityTjpAddr = syncProof?.claim?.target;
727
- if (!sessionIdentityTjpAddr) {
728
- devLog('✗ Check: I1 sync claim does not target a session keystone.');
729
- return;
730
- }
731
- devLog(`✓ Check: Sync claim targets session keystone: ${sessionIdentityTjpAddr}`);
732
-
733
- // 2. Load Session Keystone (S) locally
734
- const sRes = await metaspace.get({ addrs: [sessionIdentityTjpAddr], space });
735
- const sessionIdentity = sRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
736
-
737
- if (!sessionIdentity) {
738
- devLog('✗ Check: Session Keystone (S) NOT found in local space.');
739
- return;
740
- }
741
- devLog('✓ Check: Session Keystone (S) successfully created locally.');
742
-
743
- const sPools = sessionIdentity.data?.challengePools ?? [];
744
- const hasConnectPool = sPools.some(p => p.id === POOL_ID_CONNECT);
745
- const hasSyncPool = sPools.some(p => p.id === POOL_ID_SYNC);
746
-
747
- if (hasConnectPool && hasSyncPool) {
748
- devLog('✓ Check: S contains both connect and sync challenge pools.');
749
- } else {
750
- devLog(`✗ Check: S is missing challenge pools! (connect: ${hasConnectPool}, sync: ${hasSyncPool})`);
751
- }
752
-
753
- // we don't check this yet until sync ping pong
754
- // const targetAddrs = sessionIdentity.data?.frameDetails?.targetAddrs ?? [];
755
- // if (targetAddrs.includes(xAddr)) {
756
- // devLog('✓ Check: S is securely bound to target domain X in frameDetails.');
757
- // } else {
758
- // devLog('✗ Check: S is not bound to target domain X!');
759
- // }
760
-
761
- // #region 3. Verify Server-Side (receiver) registrations via GET REST API
762
- devLog('Check: Verifying registrations on server (receiver metaspace)...');
763
- const apiBridge = new SpaceGibApiBridge();
764
-
765
- // Check if I, evolved I1 and session S exist on server
766
- let hasI = false;
767
- let hasI1 = false;
768
- let hasS = false;
769
-
770
- const domainAddr = getIbGibAddr({ ibGib: domainI });
771
- const resGetDomainIGraphFromServer = await apiBridge.getKeystoneGraph(domainAddr);
772
- if (resGetDomainIGraphFromServer.success && resGetDomainIGraphFromServer.graph) {
773
- const domainGraph = resGetDomainIGraphFromServer.graph;
774
- hasI = domainGraph[domainAddr] !== undefined;
775
- hasI1 = domainGraph[newSenderIdentityAddr] !== undefined;
776
- } else {
777
- devLog(`✗ Check Server: Failed to fetch keystone graph from server: ${resGetDomainIGraphFromServer.message}`);
778
- }
779
-
780
- const resGetSessionSFromServer = await apiBridge.getIbGib(domainAddr, sessionIdentityTjpAddr);
781
- if (resGetSessionSFromServer.success && resGetSessionSFromServer.ibGib) {
782
- hasS = true;
783
- } else {
784
- devLog(`✗ Check Server: Failed to fetch session keystone from server: ${resGetSessionSFromServer.message}`);
785
- }
786
-
787
- if (hasI) devLog('✓ Check Server: Genesis Domain Keystone (I) registered on server.');
788
- else devLog('✗ Check Server: Genesis Domain Keystone (I) missing on server!');
789
- if (hasI1) devLog('✓ Check Server: Evolved Domain Keystone (I1) accepted and stored on server.');
790
- else devLog('✗ Check Server: Evolved Domain Keystone (I1) missing on server!');
791
- if (hasS) devLog('✓ Check Server: Session Keystone (S) accepted and stored on server.');
792
- else devLog('✗ Check Server: Session Keystone (S) missing on server!');
793
- if (hasI && hasI1 && hasS) {
794
- devLog('🎉 ALL PHASE 1B ESTABLISH CHECKS PASSED FLAWLESSLY! ✓');
795
- btn.textContent = '✓ 1B All Passed';
796
-
797
- const btn2bSetup = document.getElementById('btn-2b-setup') as HTMLButtonElement | null;
798
- if (btn2bSetup) btn2bSetup.disabled = false;
799
- }
800
-
801
- // #endregion 3. Verify Server-Side (receiver) registrations via GET REST API
802
-
803
- } catch (error) {
804
- devLog(`✗ 1B Check FAILED: ${extractErrorMsg(error)}`);
805
- console.error(`${lc_fn} 1B Check error:`, error);
806
- }
807
- });
808
- }
809
-
810
- // ---------------------------------------------------------------------------
811
- // Phase 2B Implementation
812
- // ---------------------------------------------------------------------------
813
-
814
- function init2bSetupButton(): void {
815
- const lc_fn = `${lc}[init2bSetupButton]`;
816
- const btn = document.getElementById('btn-2b-setup') as HTMLButtonElement | null;
817
- if (!btn) return;
818
-
819
- btn.addEventListener('click', async () => {
820
- try {
821
- btn.disabled = true;
822
- devLog('2B Setup: Generating Alice\'s long-lived Domain Keystone (I) and Target (X)...');
823
-
824
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
825
- const space = await metaspace.getLocalUserSpace({});
826
- if (!space) { throw new Error("No default space."); }
827
-
828
- const masterSecret = 'test-sender-secret-phase2';
829
- const keystoneService = new KeystoneService_V1();
830
-
831
- // 1. Create Genesis Domain Keystone (I^Itjp) in local sourceSpace
832
- const domainI = await keystoneService.genesis({
833
- masterSecret,
834
- configs: [
835
- getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase2'),
836
- getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase2'),
837
- ],
838
- metaspace,
839
- space,
840
- frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
841
- });
842
-
843
- debugState.domainI = domainI;
844
- debugState.domainIMasterSecret = masterSecret;
845
-
846
- devLog(`2B Setup: ✓ Domain Keystone (I) created locally: ${getIbGibAddr({ ibGib: domainI })}`);
847
- devLog(`2B Setup: Starting postGenesisKeystone...`);
848
-
849
- // 2. Post Genesis Domain Keystone to receiver/server
850
- const apiBridge = new SpaceGibApiBridge();
851
- const resGenesis = await apiBridge.postGenesisKeystone(domainI);
852
- if (resGenesis.success) {
853
- devLog(`2B Setup: ✓ Domain Keystone registered and stored on receiver (server).`);
854
- } else {
855
- devLog(`2B Setup: X postGenesisKeystone failed: ${resGenesis.message}.`);
856
- throw new Error(`2B Setup: Server rejected genesis domain keystone: ${resGenesis.message}`);
857
- }
858
-
859
- // 3. Create Test IbGib (X) locally
860
- const resX = await factory.firstGen({
861
- parentIbGib: ROOT,
862
- ib: 'test data',
863
- data: { hello: 'world2', random: Math.random() },
864
- dna: true,
865
- nCounter: true,
866
- tjp: { uuid: true, timestamp: true }
867
- });
868
- debugState.targetX = resX.newIbGib;
869
- devLog(`2B Setup: ✓ Target (X) created locally: ${getIbGibAddr({ ibGib: resX.newIbGib })}`);
870
-
871
- devLog('✓ 2B Setup Complete! Ready for 2B Sync.');
872
- btn.textContent = '✓ 2B Setup Complete';
873
-
874
- // Enable next button in the phase flow
875
- const syncBtn = document.getElementById('btn-2b-sync') as HTMLButtonElement | null;
876
- if (syncBtn) syncBtn.disabled = false;
877
-
878
- } catch (error) {
879
- devLog(`✗ 2B Setup FAILED: ${extractErrorMsg(error)}`);
880
- console.error(`${lc_fn} 2B Setup error:`, error);
881
- btn.disabled = false;
882
- }
883
- });
884
- }
885
-
886
- function init2bSyncButton(): void {
887
- const lc_fn = `${lc}[init2bSyncButton]`;
888
- const btn = document.getElementById('btn-2b-sync') as HTMLButtonElement | null;
889
- if (!btn) return;
890
-
891
- btn.addEventListener('click', async () => {
892
- try {
893
- btn.disabled = true;
894
- devLog('2B Sync: Executing senderCoordinator.sync(...) using WebSocket Peer...');
895
-
896
- const domainI = debugState.domainI;
897
- const targetX = debugState.targetX;
898
- if (!domainI || !targetX) {
899
- devLog('⚠ 2B Sync: Missing setup state. Please run Setup first.');
900
- btn.disabled = false;
901
- return;
902
- }
903
-
904
- const domainAddr = getIbGibAddr({ ibGib: domainI });
905
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
906
- const space = await metaspace.getLocalUserSpace({});
907
- if (!space) { throw new Error("No default space."); }
908
-
909
- // Instantiate WebSocket sender peer
910
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
911
- const senderPeer = new SyncPeerWebSocketSender_V1({
912
- classname: 'SyncPeerWebSocketSender_V1',
913
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
914
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
915
- });
916
-
917
- const coordinator = new SyncSagaCoordinator();
918
- const sagaId = await getUUID();
919
- debugState.sagaId = sagaId;
920
- debugState.senderPeer = senderPeer;
921
-
922
- await senderPeer.initializeOpts({
923
- localMetaspace: metaspace,
924
- localSpace: space,
925
- senderIdentity: domainI,
926
- fnSenderSecret: async () => debugState.domainIMasterSecret!,
927
- sagaId,
928
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
929
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
930
- targetAddrs: [domainAddr]
931
- });
932
-
933
- try {
934
- // Execute sync saga — triggers establishSessionIdentity and connectImpl internally!
935
- const syncSaga = await coordinator.sync({
936
- domainIbGibs: [targetX],
937
- senderIdentity: domainI,
938
- fnSenderSecret: async () => debugState.domainIMasterSecret!,
939
- peer: senderPeer,
940
- localSpace: space,
941
- metaspace,
942
- conflictStrategy: 'optimisticWithLCS' as any
943
- });
944
- await syncSaga.done;
945
- } catch (err) {
946
- // connection/sync error is fine/expected right now since sync protocol (Phase 3) might be incomplete
947
- devLog(`2B Sync: Coordinator sync executed (connect phase successfully run; subsequent sync errors expected in 2B): ${extractErrorMsg(err)}`);
948
- }
949
-
950
- devLog('✓ 2B Sync Execution Complete! Ready for State Checks.');
951
- btn.textContent = '✓ 2B Sync Run';
952
-
953
- // Enable check button
954
- const checkBtn = document.getElementById('btn-2b-check') as HTMLButtonElement | null;
955
- if (checkBtn) checkBtn.disabled = false;
956
-
957
- } catch (error) {
958
- devLog(`✗ 2B Sync FAILED: ${extractErrorMsg(error)}`);
959
- console.error(`${lc_fn} 2B Sync error:`, error);
960
- btn.disabled = false;
961
- }
962
- });
963
- }
964
-
965
- function init2bCheckButton(): void {
966
- const lc_fn = `${lc}[init2bCheckButton]`;
967
- const btn = document.getElementById('btn-2b-check') as HTMLButtonElement | null;
968
- if (!btn) return;
969
-
970
- btn.addEventListener('click', async () => {
971
- try {
972
- debugger; // allow for walkthrough 2B check
973
- devLog('2B Check: Asserting cryptographic and WebSocket state expectations...');
974
-
975
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
976
- const space = await metaspace.getLocalUserSpace({});
977
- if (!space) { throw new Error("No default space."); }
978
-
979
- const domainI = debugState.domainI!;
980
- const targetX = debugState.targetX!;
981
- const xAddr = getIbGibAddr({ ibGib: targetX });
982
-
983
- // 1. Resolve evolved sender identity I1 locally
984
- const domainAddr = getIbGibAddr({ ibGib: domainI });
985
- const newSenderIdentityAddr = await metaspace.getLatestAddr({
986
- addr: domainAddr,
987
- space
988
- });
989
-
990
- if (!newSenderIdentityAddr) {
991
- devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
992
- return;
993
- }
994
- devLog(`✓ Check: Evolved Domain Keystone (I1) created and stored locally.`);
995
-
996
- const getRes = await metaspace.get({ addrs: [newSenderIdentityAddr], space });
997
- const newSenderIdentity = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
998
-
999
- if (!newSenderIdentity) {
1000
- devLog('✗ Check: Failed to load I1 from local space.');
1001
- return;
1002
- }
1003
-
1004
- const syncProof = newSenderIdentity.data?.proofs?.find(p => p.claim?.verb === 'sync');
1005
- const sessionIdentityTjpAddr = syncProof?.claim?.target;
1006
- if (!sessionIdentityTjpAddr) {
1007
- devLog('✗ Check: I1 sync claim does not target a session keystone.');
1008
- return;
1009
- }
1010
- devLog(`✓ Check: Sync claim targets session keystone: ${sessionIdentityTjpAddr}`);
1011
-
1012
- // 2. Load Session Keystone (S) locally and get latest tip
1013
- const latestSessionSAddr = await metaspace.getLatestAddr({
1014
- addr: sessionIdentityTjpAddr,
1015
- space
1016
- });
1017
- if (!latestSessionSAddr) {
1018
- devLog('✗ Check: Latest Session Keystone (S) NOT found in local space.');
1019
- return;
1020
- }
1021
- devLog(`✓ Check: Found latest session keystone (S) locally.`);
1022
-
1023
- const sRes = await metaspace.get({ addrs: [latestSessionSAddr], space });
1024
- const sessionIdentity = sRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
1025
-
1026
- if (!sessionIdentity) {
1027
- devLog('✗ Check: Failed to load latest Session Keystone (S).');
1028
- return;
1029
- }
1030
-
1031
- // Verify S contains connect and sync pools
1032
- const sPools = sessionIdentity.data?.challengePools ?? [];
1033
- const connectPool = sPools.find(p => p.id === POOL_ID_CONNECT);
1034
- const syncPool = sPools.find(p => p.id === POOL_ID_SYNC);
1035
-
1036
- if (connectPool && syncPool) {
1037
- devLog('✓ Check: S contains both connect and sync challenge pools.');
1038
- } else {
1039
- devLog(`✗ Check: S is missing challenge pools! (connect: ${!!connectPool}, sync: ${!!syncPool})`);
1040
- return;
1041
- }
1042
-
1043
- // Verify S was successfully evolved (depleted connect pool)
1044
- const remainingChallenges = Object.keys(connectPool.challenges).length;
1045
- if (remainingChallenges === 0) {
1046
- devLog('✓ Check: S connect pool successfully depleted (0 challenges remaining).');
1047
- } else {
1048
- devLog(`✗ Check: S connect pool not depleted! (${remainingChallenges} challenges remaining)`);
1049
- return;
1050
- }
1051
-
1052
- // we don't check this yet until sync ping pong
1053
- // const targetAddrs = sessionIdentity.data?.frameDetails?.targetAddrs ?? [];
1054
- // if (targetAddrs.includes(xAddr)) {
1055
- // devLog('✓ Check: S is securely bound to target domain X in frameDetails.');
1056
- // } else {
1057
- // devLog('✗ Check: S is not bound to target domain X!');
1058
- // }
1059
-
1060
- // 3. Verify WebSocket Connection is open and active
1061
- if (debugState.senderPeer && debugState.senderPeer.isSocketOpen) {
1062
- devLog('✓ Check: WebSocket connection is active and OPEN.');
1063
- } else {
1064
- devLog('✗ Check: WebSocket connection is NOT open or peer is missing!');
1065
- return;
1066
- }
1067
-
1068
- devLog('🎉 ALL PHASE 2B CONNECT CHECKS PASSED FLAWLESSLY! ✓');
1069
- btn.textContent = '✓ 2B All Passed';
1070
-
1071
- // Enable Phase 3B setup
1072
- const p3SetupBtn = document.getElementById('btn-3b-setup') as HTMLButtonElement | null;
1073
- if (p3SetupBtn) p3SetupBtn.disabled = false;
1074
-
1075
- } catch (error) {
1076
- devLog(`✗ 2B Check FAILED: ${extractErrorMsg(error)}`);
1077
- console.error(`${lc_fn} 2B Check error:`, error);
1078
- }
1079
- });
1080
- }
1081
-
1082
- function init3bPlaceholder(): void {
1083
- const btnSetup = document.getElementById('btn-3b-setup') as HTMLButtonElement | null;
1084
- const btnSync = document.getElementById('btn-3b-sync') as HTMLButtonElement | null;
1085
- const btnCheck = document.getElementById('btn-3b-check') as HTMLButtonElement | null;
1086
-
1087
- if (btnSetup) {
1088
- btnSetup.addEventListener('click', () => devLog('3B Setup: Placeholders ready for Phase 3B (Transactional Sync).'));
1089
- }
1090
- if (btnSync) {
1091
- btnSync.addEventListener('click', () => devLog('3B Sync: Placeholders ready for Phase 3B (Transactional Sync).'));
1092
- }
1093
- if (btnCheck) {
1094
- btnCheck.addEventListener('click', () => devLog('3B Check: Placeholders ready for Phase 3B (Transactional Sync).'));
1095
- }
1096
- }
1097
-
1098
- // ---------------------------------------------------------------------------
1099
- // Dev Tools UI Init
1100
- // ---------------------------------------------------------------------------
12
+ initWsTestButton, initPrintStateButton, initCreateDomainKeystoneButton,
13
+ initCreateTestIbGibButton, initCreateSessionKeystoneButton
14
+ } from './dev-tools/base-tools.mjs';
15
+ import { init1bSetupButton, init1bSyncButton, init1bCheckButton } from './dev-tools/phase-1.mjs';
16
+ import { init2bSetupButton, init2bSyncButton, init2bCheckButton } from './dev-tools/phase-2.mjs';
17
+ import { init3bSetupButton, init3bSyncButton, init3bCheckButton } from './dev-tools/phase-3.mjs';
18
+ import { init4_1bSetupButton, init4_1bSyncButton, init4_1bCheckButton } from './dev-tools/phase-4-1.mjs';
19
+ import { init4_2bSetupButton, init4_2bSyncButton, init4_2bCheckButton } from './dev-tools/phase-4-2.mjs';
20
+ import { init4_3bSetupButton, init4_3bSyncButton, init4_3bCheckButton } from './dev-tools/phase-4-3.mjs';
21
+ import { init4_4bSetupButton, init4_4bSyncButton, init4_4bCheckButton } from './dev-tools/phase-4-4.mjs';
22
+ import { init4_5bSetupButton, init4_5bSyncButton, init4_5bCheckButton } from './dev-tools/phase-4-5.mjs';
23
+ import { init4_6bSetupButton, init4_6bSyncButton, init4_6bCheckButton } from './dev-tools/phase-4-6.mjs';
24
+ import { init4_7bSetupButton, init4_7bSyncButton, init4_7bCheckButton } from './dev-tools/phase-4-7.mjs';
25
+ import { init4_8bSetupButton, init4_8bSyncButton, init4_8bCheckButton } from './dev-tools/phase-4-8.mjs';
26
+ import { init4_9bSetupButton, init4_9bSyncButton, init4_9bCheckButton } from './dev-tools/phase-4-9.mjs';
27
+ import { init4_10bSetupButton, init4_10bSyncButton, init4_10bCheckButton } from './dev-tools/phase-4-10.mjs';
28
+
29
+ export { devLog, debugState };
1101
30
 
1102
31
  /**
1103
32
  * Call once inside DOMContentLoaded to wire up all dev-tool buttons.
@@ -1110,15 +39,45 @@ export function initDevTools(): void {
1110
39
  initWsTestButton();
1111
40
  initCreateTestIbGibButton();
1112
41
  initCreateSessionKeystoneButton();
1113
- initEvolveDomainKeystoneButton();
1114
- initPerformSyncButton();
1115
42
  init1bSetupButton();
1116
43
  init1bSyncButton();
1117
44
  init1bCheckButton();
1118
45
  init2bSetupButton();
1119
46
  init2bSyncButton();
1120
47
  init2bCheckButton();
1121
- init3bPlaceholder();
48
+ init3bSetupButton();
49
+ init3bSyncButton();
50
+ init3bCheckButton();
51
+ init4_1bSetupButton();
52
+ init4_1bSyncButton();
53
+ init4_1bCheckButton();
54
+ init4_2bSetupButton();
55
+ init4_2bSyncButton();
56
+ init4_2bCheckButton();
57
+ init4_3bSetupButton();
58
+ init4_3bSyncButton();
59
+ init4_3bCheckButton();
60
+ init4_4bSetupButton();
61
+ init4_4bSyncButton();
62
+ init4_4bCheckButton();
63
+ init4_5bSetupButton();
64
+ init4_5bSyncButton();
65
+ init4_5bCheckButton();
66
+ init4_6bSetupButton();
67
+ init4_6bSyncButton();
68
+ init4_6bCheckButton();
69
+ init4_7bSetupButton();
70
+ init4_7bSyncButton();
71
+ init4_7bCheckButton();
72
+ init4_8bSetupButton();
73
+ init4_8bSyncButton();
74
+ init4_8bCheckButton();
75
+ init4_9bSetupButton();
76
+ init4_9bSyncButton();
77
+ init4_9bCheckButton();
78
+ init4_10bSetupButton();
79
+ init4_10bSyncButton();
80
+ init4_10bCheckButton();
1122
81
  } catch (error) {
1123
82
  console.error(`${lc_fn} ${extractErrorMsg(error)}`);
1124
83
  }