@ibgib/space-gib 0.0.3 → 0.0.5

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 (63) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/IMPLEMENTATION.md +9 -13
  3. package/README.md +7 -0
  4. package/dist/client/bootstrap.mjs +1 -1
  5. package/dist/client/bootstrap.mjs.map +1 -1
  6. package/dist/client/chunk-ANGVYAEK.mjs +42 -0
  7. package/dist/client/chunk-ANGVYAEK.mjs.map +7 -0
  8. package/dist/client/chunk-IRGFDQRD.mjs +1920 -0
  9. package/dist/client/chunk-IRGFDQRD.mjs.map +7 -0
  10. package/dist/client/index.html +103 -5
  11. package/dist/client/index.mjs +1 -1
  12. package/dist/client/script.mjs +1 -1
  13. package/dist/client/style.css +466 -61
  14. package/dist/respec-gib.node.mjs +5 -0
  15. package/dist/server/server.mjs +533 -233
  16. package/dist/server/server.mjs.map +2 -2
  17. package/package.json +6 -6
  18. package/src/client/AUTO-GENERATED-version.mts +1 -1
  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 +52 -1194
  47. package/src/client/index.html +103 -5
  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 +3 -5
  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-genesis.handler.mts +1 -1
  57. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +1 -1
  58. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +31 -3
  59. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  60. package/dist/client/chunk-2KJC5XKE.mjs +0 -31
  61. package/dist/client/chunk-2KJC5XKE.mjs.map +0 -7
  62. package/dist/client/chunk-QNIXTRFO.mjs +0 -235
  63. package/dist/client/chunk-QNIXTRFO.mjs.map +0 -7
@@ -0,0 +1,252 @@
1
+ import { extractErrorMsg, getTimestamp, getUUID, } 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 { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
6
+ import { KeystoneReplenishStrategy } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
7
+ import { createManagePoolConfig } from '@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs';
8
+ import { KeystoneStrategyFactory } from '@ibgib/core-gib/dist/keystone/strategy/keystone-strategy-factory.mjs';
9
+ import { KEYSTONE_VERB_CONNECT, POOL_ID_CONNECT } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
10
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
11
+ import { SESSION_KEYSTONE_POLICY, getConnectChallenge } from "../../common/keystone-policies.mjs";
12
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
13
+
14
+ import { debugState, devLog, lc } from './common.mjs';
15
+
16
+ let _ws: WebSocket | null = null;
17
+
18
+ export function initWsTestButton(): void {
19
+ const lc_fn = `${lc}[initWsTestButton]`;
20
+ const btn = document.getElementById('btn-test-ws') as HTMLButtonElement | null;
21
+ if (!btn) {
22
+ console.warn(`${lc_fn} btn-test-ws not found — skipping`);
23
+ return;
24
+ }
25
+
26
+ btn.addEventListener('click', () => {
27
+ try {
28
+ if (_ws && _ws.readyState === WebSocket.OPEN) {
29
+ _ws.send(JSON.stringify({ ping: 'hello from client', ts: Date.now() }));
30
+ devLog('→ sent ping on existing connection');
31
+ return;
32
+ }
33
+
34
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
35
+ const wsUrl = `${protocol}//${location.host}/api/debug/ws-echo`;
36
+ devLog(`→ connecting to ${wsUrl}`);
37
+
38
+ _ws = new WebSocket(wsUrl);
39
+
40
+ _ws.addEventListener('open', () => {
41
+ devLog('✓ WebSocket connected');
42
+ btn.textContent = 'Send WS Ping';
43
+ });
44
+
45
+ _ws.addEventListener('message', (ev) => {
46
+ devLog(`← ${ev.data}`);
47
+ });
48
+
49
+ _ws.addEventListener('close', (ev) => {
50
+ devLog(`✗ WebSocket closed (code ${ev.code})`);
51
+ btn.textContent = 'Test WebSocket';
52
+ _ws = null;
53
+ });
54
+
55
+ _ws.addEventListener('error', (ev) => {
56
+ devLog(`✗ WebSocket error — check console`);
57
+ console.error(`${lc_fn} WebSocket error`, ev);
58
+ });
59
+
60
+ } catch (error) {
61
+ devLog(`✗ ${extractErrorMsg(error)}`);
62
+ console.error(`${lc_fn} ${extractErrorMsg(error)}`);
63
+ }
64
+ });
65
+ }
66
+
67
+ export function initPrintStateButton(): void {
68
+ const btn = document.getElementById('btn-print-dev-state') as HTMLButtonElement | null;
69
+ if (!btn) { return; }
70
+ btn.addEventListener('click', () => {
71
+ devLog(`Printing debug state to console...`);
72
+ console.dir(debugState);
73
+ });
74
+ }
75
+
76
+ export function initCreateDomainKeystoneButton(): void {
77
+ const lc_fn = `${lc}[initCreateDomainKeystoneButton]`;
78
+ const btn = document.getElementById('btn-create-domain-keystone') as HTMLButtonElement | null;
79
+ if (!btn) { return; }
80
+
81
+ btn.addEventListener('click', async () => {
82
+ try {
83
+ btn.disabled = true;
84
+ devLog('Generating dummy Domain Keystone (I)...');
85
+
86
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
87
+ const space = await metaspace.getLocalUserSpace({});
88
+ if (!space) { throw new Error("No default space found in metaspace."); }
89
+
90
+ const masterSecret = 'password';
91
+ const keystoneService = new KeystoneService_V1();
92
+
93
+ const domainI = await keystoneService.genesis({
94
+ masterSecret,
95
+ configs: [
96
+ createManagePoolConfig({
97
+ id: 'default',
98
+ salt: await getUUID(),
99
+ replenishStrategy: KeystoneReplenishStrategy.topUp,
100
+ }),
101
+ ],
102
+ metaspace,
103
+ space,
104
+ frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
105
+ });
106
+
107
+ const iAddr = getIbGibAddr({ ibGib: domainI });
108
+ devLog(`✓ Local genesis complete: ${iAddr}`);
109
+
110
+ debugState.domainI = domainI;
111
+ debugState.domainIMasterSecret = masterSecret;
112
+
113
+ devLog(`Posting genesis keystone to server...`);
114
+ const apiBridge = new SpaceGibApiBridge();
115
+ const resSync = await apiBridge.postGenesisKeystone(domainI);
116
+ if (!resSync.success) {
117
+ devLog(`✗ Server rejected genesis keystone: ${resSync.message}`);
118
+ btn.disabled = false;
119
+ return;
120
+ }
121
+
122
+ devLog(`✓ Server accepted Domain Keystone (I)`);
123
+ btn.textContent = '✓ Domain Keystone Created';
124
+
125
+ const nextBtn = document.getElementById('btn-create-test-ibgib') as HTMLButtonElement;
126
+ if (nextBtn) { nextBtn.disabled = false; }
127
+
128
+ } catch (error) {
129
+ devLog(`✗ ${extractErrorMsg(error)}`);
130
+ console.error(`${lc_fn} ${extractErrorMsg(error)}`);
131
+ btn.disabled = false;
132
+ }
133
+ });
134
+ }
135
+
136
+ export function initCreateTestIbGibButton(): void {
137
+ const lc_fn = `${lc}[initCreateTestIbGibButton]`;
138
+ const btn = document.getElementById('btn-create-test-ibgib') as HTMLButtonElement | null;
139
+ if (!btn) {
140
+ console.warn(`${lc_fn} btn-create-test-ibgib not found — skipping`);
141
+ return;
142
+ }
143
+
144
+ btn.addEventListener('click', async () => {
145
+ try {
146
+ devLog('Generating dummy X^Xtjp ibgib...');
147
+ const resX = await factory.firstGen({
148
+ parentIbGib: ROOT,
149
+ ib: 'test data',
150
+ data: { hello: 'world', random: Math.random() },
151
+ dna: true,
152
+ nCounter: true,
153
+ tjp: { uuid: true, timestamp: true }
154
+ });
155
+ const xIbGib = resX.newIbGib;
156
+ const xAddr = getIbGibAddr({ ibGib: xIbGib });
157
+
158
+ debugState.targetX = xIbGib;
159
+ devLog(`✓ Created X: ${xAddr}`);
160
+ btn.textContent = '✓ Test IbGib (X) Created';
161
+
162
+ const nextBtn = document.getElementById('btn-create-session-keystone') as HTMLButtonElement;
163
+ if (nextBtn) { nextBtn.disabled = false; }
164
+ } catch (error) {
165
+ devLog(`✗ ${extractErrorMsg(error)}`);
166
+ console.error(`${lc_fn} ${extractErrorMsg(error)}`);
167
+ }
168
+ });
169
+ }
170
+
171
+ export function initCreateSessionKeystoneButton(): void {
172
+ const lc_fn = `${lc}[initCreateSessionKeystoneButton]`;
173
+ const btn = document.getElementById('btn-create-session-keystone') as HTMLButtonElement | null;
174
+ if (!btn) {
175
+ console.warn(`${lc_fn} btn-create-session-keystone not found — skipping`);
176
+ return;
177
+ }
178
+
179
+ btn.addEventListener('click', async () => {
180
+ try {
181
+ devLog('Generating Session Keystone (S^Stjp)...');
182
+
183
+ const domainI = debugState.domainI;
184
+ const targetX = debugState.targetX;
185
+
186
+ if (!domainI) { devLog('⚠ No domain keystone (I) found in state. Please Create Domain Keystone first.'); return; }
187
+ if (!targetX) { devLog('⚠ No target ibgib (X) found in state. Please Create Test IbGib first.'); return; }
188
+
189
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
190
+ const space = await metaspace.getLocalUserSpace({});
191
+ if (!space) { throw new Error("No default space found in metaspace."); }
192
+
193
+ const sessionSecret = 'ephemeral-' + Math.random().toString();
194
+ const keystoneService = new KeystoneService_V1();
195
+
196
+ console.warn(`${lc}[NAG] placeholder genesis keystone config right now (W: 69b108687cf8bec0f9a8e148bcca8d26)`);
197
+ const sIbGib = await keystoneService.genesis({
198
+ masterSecret: sessionSecret,
199
+ configs: [
200
+ {
201
+ id: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.ID,
202
+ salt: await getUUID(),
203
+ type: SESSION_KEYSTONE_POLICY.COMMON.TYPE,
204
+ algo: SESSION_KEYSTONE_POLICY.COMMON.ALGO,
205
+ rounds: SESSION_KEYSTONE_POLICY.COMMON.ROUNDS,
206
+ behavior: {
207
+ size: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SIZE,
208
+ replenish: SESSION_KEYSTONE_POLICY.COMMON.REPLENISH,
209
+ selectSequentially: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SELECT_SEQUENTIALLY,
210
+ selectRandomly: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.SELECT_RANDOMLY,
211
+ targetBindingCount: SESSION_KEYSTONE_POLICY.DEFAULT_POOL.TARGET_BINDING_COUNT,
212
+ },
213
+ allowedVerbs: [],
214
+ },
215
+ {
216
+ id: SESSION_KEYSTONE_POLICY.CONNECT_POOL.ID,
217
+ salt: await getUUID(),
218
+ type: SESSION_KEYSTONE_POLICY.COMMON.TYPE,
219
+ algo: SESSION_KEYSTONE_POLICY.COMMON.ALGO,
220
+ rounds: SESSION_KEYSTONE_POLICY.COMMON.ROUNDS,
221
+ behavior: {
222
+ size: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SIZE,
223
+ replenish: SESSION_KEYSTONE_POLICY.COMMON.REPLENISH,
224
+ selectSequentially: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SELECT_SEQUENTIALLY,
225
+ selectRandomly: SESSION_KEYSTONE_POLICY.CONNECT_POOL.SELECT_RANDOMLY,
226
+ targetBindingCount: SESSION_KEYSTONE_POLICY.CONNECT_POOL.TARGET_BINDING_COUNT,
227
+ },
228
+ allowedVerbs: [SESSION_KEYSTONE_POLICY.CONNECT_POOL.VERB],
229
+ }
230
+ ],
231
+ metaspace,
232
+ space,
233
+ frameDetails: {
234
+ client: 'space-gib-web-session',
235
+ target_I: domainI ? getIbGibAddr({ ibGib: domainI }) : undefined,
236
+ target_X: targetX ? getIbGibAddr({ ibGib: targetX }) : undefined,
237
+ }
238
+ });
239
+
240
+ const sAddr = getIbGibAddr({ ibGib: sIbGib });
241
+ debugState.sessionS = sIbGib;
242
+ debugState.sessionSecret = sessionSecret;
243
+
244
+ devLog(`✓ Created Session Keystone: ${sAddr}`);
245
+ btn.textContent = '✓ Session Keystone Created';
246
+ } catch (error) {
247
+ devLog(`✗ ${extractErrorMsg(error)}`);
248
+ console.error(`${lc_fn} ${extractErrorMsg(error)}`);
249
+ }
250
+ });
251
+ }
252
+
@@ -0,0 +1,217 @@
1
+ import { extractErrorMsg, getTimestamp, getUUID, } 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 { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
6
+ import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
7
+ import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
8
+ import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
9
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
10
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
11
+ import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
12
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
13
+ import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
14
+ import { GLOBAL_LOG_A_LOT } from '../constants.mjs';
15
+
16
+ export const logalot = GLOBAL_LOG_A_LOT;
17
+ export const lc = '[dev-tools]';
18
+
19
+ export interface DebugState {
20
+ domainI?: KeystoneIbGib_V1;
21
+ domainIMasterSecret?: string;
22
+ targetX?: IbGib_V1;
23
+ targetC1?: IbGib_V1;
24
+ targetC2?: IbGib_V1;
25
+ sessionS?: KeystoneIbGib_V1;
26
+ sessionSecret?: string;
27
+ senderPeer?: SyncPeerWebSocketSender_V1;
28
+ sagaId?: string;
29
+ }
30
+
31
+ export const debugState: DebugState = {};
32
+ (window as any).ibgibDebugState = debugState;
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Dev panel log helper
36
+ // ---------------------------------------------------------------------------
37
+
38
+ export function devLog(msg: string): void {
39
+ const logEl = document.getElementById('dev-panel-log') as HTMLPreElement | null;
40
+ if (!logEl) { return; }
41
+ const timestamp = new Date().toISOString().slice(11, 23); // HH:MM:SS.mmm
42
+ logEl.textContent = `[${timestamp}] ${msg}\n` + logEl.textContent;
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Phase Setup / Sync common runners
47
+ // ---------------------------------------------------------------------------
48
+
49
+ export interface PhaseSetupOptions {
50
+ phaseText: '1B' | '2B' | '3B' | '4.1B' | '4.2B' | '4.3B';
51
+ btnId: string;
52
+ nextBtnId: string;
53
+ masterSecret: string;
54
+ syncSalt: string;
55
+ manageSalt: string;
56
+ ib: string;
57
+ data: any;
58
+ }
59
+
60
+ export async function performPhaseSetup(opts: PhaseSetupOptions): Promise<void> {
61
+ const lc_fn = `${lc}[performPhaseSetup(${opts.phaseText})]`;
62
+ const btn = document.getElementById(opts.btnId) as HTMLButtonElement | null;
63
+ if (!btn) { return; }
64
+
65
+ try {
66
+ btn.disabled = true;
67
+ devLog(`${opts.phaseText} Setup: Generating Alice's long-lived Domain Keystone (I) and Target (X)...`);
68
+
69
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
70
+ const space = await metaspace.getLocalUserSpace({});
71
+ if (!space) { throw new Error("No default space found in metaspace."); }
72
+
73
+ const keystoneService = new KeystoneService_V1();
74
+
75
+ // 1. Create Genesis Domain Keystone (I^Itjp) in local space
76
+ const domainI = await keystoneService.genesis({
77
+ masterSecret: opts.masterSecret,
78
+ configs: [
79
+ getSpaceGibPoolConfig('sync', opts.syncSalt),
80
+ getSpaceGibPoolConfig('manage', opts.manageSalt),
81
+ ],
82
+ metaspace,
83
+ space,
84
+ frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
85
+ });
86
+
87
+ debugState.domainI = domainI;
88
+ debugState.domainIMasterSecret = opts.masterSecret;
89
+
90
+ devLog(`${opts.phaseText} Setup: ✓ Domain Keystone (I) created locally: ${getIbGibAddr({ ibGib: domainI })}`);
91
+ devLog(`${opts.phaseText} Setup: Starting postGenesisKeystone...`);
92
+
93
+ // 2. Post Genesis Domain Keystone to receiver/server
94
+ const apiBridge = new SpaceGibApiBridge();
95
+ const resGenesis = await apiBridge.postGenesisKeystone(domainI);
96
+ if (resGenesis.success) {
97
+ devLog(`${opts.phaseText} Setup: ✓ Domain Keystone registered and stored on receiver (server).`);
98
+ } else {
99
+ devLog(`${opts.phaseText} Setup: X postGenesisKeystone failed: ${resGenesis.message}.`);
100
+ throw new Error(`${opts.phaseText} Setup: Server rejected genesis domain keystone: ${resGenesis.message}`);
101
+ }
102
+
103
+ // 3. Create Test IbGib (X) locally
104
+ const resX = await factory.firstGen({
105
+ parentIbGib: ROOT,
106
+ ib: opts.ib,
107
+ data: opts.data,
108
+ dna: true,
109
+ nCounter: true,
110
+ tjp: { uuid: true, timestamp: true }
111
+ });
112
+ const xIbGib = resX.newIbGib;
113
+
114
+ // Persist target X to local space so coordinator can build the sync history
115
+ await metaspace.persistTransformResult({ resTransform: resX, space });
116
+ await metaspace.registerNewIbGib({ ibGib: xIbGib });
117
+
118
+ debugState.targetX = xIbGib;
119
+ devLog(`${opts.phaseText} Setup: ✓ Target (X) created and persisted locally: ${getIbGibAddr({ ibGib: xIbGib })}`);
120
+
121
+ devLog(`✓ ${opts.phaseText} Setup Complete! Ready for ${opts.phaseText} Sync.`);
122
+ btn.textContent = `✓ ${opts.phaseText} Setup Complete`;
123
+
124
+ const syncBtn = document.getElementById(opts.nextBtnId) as HTMLButtonElement | null;
125
+ if (syncBtn) { syncBtn.disabled = false; }
126
+
127
+ } catch (error) {
128
+ devLog(`✗ ${opts.phaseText} Setup FAILED: ${extractErrorMsg(error)}`);
129
+ console.error(`${lc_fn} ${opts.phaseText} Setup error:`, error);
130
+ btn.disabled = false;
131
+ }
132
+ }
133
+
134
+ export interface PhaseSyncOptions {
135
+ phaseText: '1B' | '2B' | '3B' | '4.1B' | '4.2B' | '4.3B';
136
+ btnId: string;
137
+ nextBtnId: string;
138
+ expectSyncFailure?: boolean;
139
+ failureMessageSuffix?: string;
140
+ }
141
+
142
+ export async function performPhaseSync(opts: PhaseSyncOptions): Promise<void> {
143
+ const lc_fn = `${lc}[performPhaseSync(${opts.phaseText})]`;
144
+ const btn = document.getElementById(opts.btnId) as HTMLButtonElement | null;
145
+ if (!btn) { return; }
146
+
147
+ try {
148
+ btn.disabled = true;
149
+ devLog(`${opts.phaseText} Sync: Executing senderCoordinator.sync(...) using WebSocket Peer...`);
150
+
151
+ const domainI = debugState.domainI;
152
+ const targetX = debugState.targetX;
153
+ if (!domainI || !targetX) {
154
+ devLog(`⚠ ${opts.phaseText} Sync: Missing setup state. Please run Setup first.`);
155
+ btn.disabled = false;
156
+ return;
157
+ }
158
+
159
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
160
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
161
+ const space = await metaspace.getLocalUserSpace({});
162
+ if (!space) { throw new Error("No default space."); }
163
+
164
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
165
+ const senderPeer = new SyncPeerWebSocketSender_V1({
166
+ classname: 'SyncPeerWebSocketSender_V1',
167
+ httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
168
+ wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
169
+ });
170
+
171
+ const coordinator = new SyncSagaCoordinator();
172
+ const sagaId = await getUUID();
173
+ debugState.sagaId = sagaId;
174
+ debugState.senderPeer = senderPeer;
175
+
176
+ await senderPeer.initializeOpts({
177
+ localMetaspace: metaspace,
178
+ localSpace: space,
179
+ senderIdentity: domainI,
180
+ fnSenderSecret: async () => debugState.domainIMasterSecret!,
181
+ sagaId,
182
+ sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
183
+ sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
184
+ targetAddrs: [domainAddr]
185
+ });
186
+
187
+ try {
188
+ const syncSaga = await coordinator.sync({
189
+ domainIbGibs: [targetX],
190
+ senderIdentity: domainI,
191
+ fnSenderSecret: async () => debugState.domainIMasterSecret!,
192
+ peer: senderPeer,
193
+ localSpace: space,
194
+ metaspace,
195
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
196
+ });
197
+ await syncSaga.done;
198
+ } catch (err) {
199
+ if (opts.expectSyncFailure) {
200
+ devLog(`${opts.phaseText} Sync: Coordinator sync executed (${opts.failureMessageSuffix ?? 'errors expected'}): ${extractErrorMsg(err)}`);
201
+ } else {
202
+ throw err;
203
+ }
204
+ }
205
+
206
+ devLog(`✓ ${opts.phaseText} Sync Execution Complete! Ready for State Checks.`);
207
+ btn.textContent = `✓ ${opts.phaseText} Sync Run`;
208
+
209
+ const checkBtn = document.getElementById(opts.nextBtnId) as HTMLButtonElement | null;
210
+ if (checkBtn) { checkBtn.disabled = false; }
211
+
212
+ } catch (error) {
213
+ devLog(`✗ ${opts.phaseText} Sync FAILED: ${extractErrorMsg(error)}`);
214
+ console.error(`${lc_fn} ${opts.phaseText} Sync error:`, error);
215
+ btn.disabled = false;
216
+ }
217
+ }
@@ -0,0 +1,156 @@
1
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
+ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
3
+ import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
4
+ import { POOL_ID_CONNECT, POOL_ID_SYNC } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
5
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
6
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
7
+
8
+ import { debugState, devLog, lc, performPhaseSetup, performPhaseSync } from './common.mjs';
9
+
10
+ export function init1bSetupButton(): void {
11
+ const btn = document.getElementById('btn-1b-setup') as HTMLButtonElement | null;
12
+ if (!btn) { return; }
13
+ btn.addEventListener('click', () => {
14
+ performPhaseSetup({
15
+ phaseText: '1B',
16
+ btnId: 'btn-1b-setup',
17
+ nextBtnId: 'btn-1b-sync',
18
+ masterSecret: 'test-sender-secret-phase1',
19
+ syncSalt: 'senderidentitysyncsaltphase1',
20
+ manageSalt: 'senderidentitymanagesaltphase1',
21
+ ib: 'test data',
22
+ data: { hello: 'world', random: Math.random() }
23
+ });
24
+ });
25
+ }
26
+
27
+ export function init1bSyncButton(): void {
28
+ const btn = document.getElementById('btn-1b-sync') as HTMLButtonElement | null;
29
+ if (!btn) { return; }
30
+ btn.addEventListener('click', () => {
31
+ performPhaseSync({
32
+ phaseText: '1B',
33
+ btnId: 'btn-1b-sync',
34
+ nextBtnId: 'btn-1b-check',
35
+ expectSyncFailure: true,
36
+ failureMessageSuffix: 'establish phase successfully run; connection/sync errors expected in 1B'
37
+ });
38
+ });
39
+ }
40
+
41
+ export function init1bCheckButton(): void {
42
+ const lc_fn = `${lc}[init1bCheckButton]`;
43
+ const btn = document.getElementById('btn-1b-check') as HTMLButtonElement | null;
44
+ if (!btn) { return; }
45
+
46
+ btn.addEventListener('click', async () => {
47
+ try {
48
+ devLog('1B Check: Asserting cryptographic and durable state expectations from respec...');
49
+
50
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
51
+ const space = await metaspace.getLocalUserSpace({});
52
+ if (!space) { throw new Error("No default space."); }
53
+
54
+ const domainI = debugState.domainI!;
55
+ const targetX = debugState.targetX!;
56
+
57
+ // 1. Resolve evolved sender identity I1 locally
58
+ const newSenderIdentityAddr = await metaspace.getLatestAddr({
59
+ addr: getIbGibAddr({ ibGib: domainI }),
60
+ space
61
+ });
62
+
63
+ if (!newSenderIdentityAddr) {
64
+ devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
65
+ return;
66
+ }
67
+ devLog(`✓ Check: Evolved Domain Keystone (I1) created and stored locally.`);
68
+
69
+ const getRes = await metaspace.get({ addrs: [newSenderIdentityAddr], space });
70
+ const newSenderIdentity = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
71
+
72
+ if (!newSenderIdentity) {
73
+ devLog('✗ Check: Failed to load I1 from local space.');
74
+ return;
75
+ }
76
+
77
+ const syncProof = newSenderIdentity.data?.proofs?.find(p => p.claim?.verb === 'sync');
78
+ if (!syncProof) {
79
+ devLog('✗ Check: I1 is missing sync-verb claim proof!');
80
+ } else {
81
+ devLog('✓ Check: I1 contains valid sync-verb claim proof.');
82
+ }
83
+
84
+ const sessionIdentityTjpAddr = syncProof?.claim?.target;
85
+ if (!sessionIdentityTjpAddr) {
86
+ devLog('✗ Check: I1 sync claim does not target a session keystone.');
87
+ return;
88
+ }
89
+ devLog(`✓ Check: Sync claim targets session keystone: ${sessionIdentityTjpAddr}`);
90
+
91
+ // 2. Load Session Keystone (S) locally
92
+ const sRes = await metaspace.get({ addrs: [sessionIdentityTjpAddr], space });
93
+ const sessionIdentity = sRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
94
+
95
+ if (!sessionIdentity) {
96
+ devLog('✗ Check: Session Keystone (S) NOT found in local space.');
97
+ return;
98
+ }
99
+ devLog('✓ Check: Session Keystone (S) successfully created locally.');
100
+
101
+ const sPools = sessionIdentity.data?.challengePools ?? [];
102
+ const hasConnectPool = sPools.some(p => p.id === POOL_ID_CONNECT);
103
+ const hasSyncPool = sPools.some(p => p.id === POOL_ID_SYNC);
104
+
105
+ if (hasConnectPool && hasSyncPool) {
106
+ devLog('✓ Check: S contains both connect and sync challenge pools.');
107
+ } else {
108
+ devLog(`✗ Check: S is missing challenge pools! (connect: ${hasConnectPool}, sync: ${hasSyncPool})`);
109
+ }
110
+
111
+ // 3. Verify Server-Side (receiver) registrations via GET REST API
112
+ devLog('Check: Verifying registrations on server (receiver metaspace)...');
113
+ const apiBridge = new SpaceGibApiBridge();
114
+
115
+ let hasI = false;
116
+ let hasI1 = false;
117
+ let hasS = false;
118
+
119
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
120
+ const resGetDomainIGraphFromServer = await apiBridge.getKeystoneGraph(domainAddr);
121
+ if (resGetDomainIGraphFromServer.success && resGetDomainIGraphFromServer.graph) {
122
+ const domainGraph = resGetDomainIGraphFromServer.graph;
123
+ hasI = domainGraph[domainAddr] !== undefined;
124
+ hasI1 = domainGraph[newSenderIdentityAddr] !== undefined;
125
+ } else {
126
+ devLog(`✗ Check Server: Failed to fetch keystone graph from server: ${resGetDomainIGraphFromServer.message}`);
127
+ }
128
+
129
+ const resGetSessionSFromServer = await apiBridge.getIbGib(domainAddr, sessionIdentityTjpAddr);
130
+ if (resGetSessionSFromServer.success && resGetSessionSFromServer.ibGib) {
131
+ hasS = true;
132
+ } else {
133
+ devLog(`✗ Check Server: Failed to fetch session keystone from server: ${resGetSessionSFromServer.message}`);
134
+ }
135
+
136
+ if (hasI) { devLog('✓ Check Server: Genesis Domain Keystone (I) registered on server.'); }
137
+ else devLog('✗ Check Server: Genesis Domain Keystone (I) missing on server!');
138
+ if (hasI1) { devLog('✓ Check Server: Evolved Domain Keystone (I1) accepted and stored on server.'); }
139
+ else devLog('✗ Check Server: Evolved Domain Keystone (I1) missing on server!');
140
+ if (hasS) { devLog('✓ Check Server: Session Keystone (S) accepted and stored on server.'); }
141
+ else devLog('✗ Check Server: Session Keystone (S) missing on server!');
142
+
143
+ if (hasI && hasI1 && hasS) {
144
+ devLog('🎉 ALL PHASE 1B ESTABLISH CHECKS PASSED FLAWLESSLY! ✓');
145
+ btn.textContent = '✓ 1B All Passed';
146
+
147
+ const btn2bSetup = document.getElementById('btn-2b-setup') as HTMLButtonElement | null;
148
+ if (btn2bSetup) { btn2bSetup.disabled = false; }
149
+ }
150
+
151
+ } catch (error) {
152
+ devLog(`✗ 1B Check FAILED: ${extractErrorMsg(error)}`);
153
+ console.error(`${lc_fn} 1B Check error:`, error);
154
+ }
155
+ });
156
+ }