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