import { extractErrorMsg, getUUID } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs'; import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs'; import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs'; import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs'; import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs'; import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs"; import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs'; import { debugState, devLog, lc, performPhaseSetup, runSyncPass, verifyIdentitiesOnServer } from './common.mjs'; export function init4_2bSetupButton(): void { const btn = document.getElementById('btn-4-2b-setup') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', () => { performPhaseSetup({ phaseText: '4.2B', btnId: 'btn-4-2b-setup', nextBtnId: 'btn-4-2b-sync', masterSecret: 'test-sender-secret-phase4-2', syncSalt: 'senderidentitysyncsaltphase4-2', manageSalt: 'senderidentitymanagesaltphase4-2', ib: 'dummy target 4.2b', data: { hello: 'dummy' } }); }); } async function performPhaseSync4_2b(): Promise { const lc_fn = `${lc}[performPhaseSync4_2b]`; const btn = document.getElementById('btn-4-2b-sync') as HTMLButtonElement | null; if (!btn) { return; } try { btn.disabled = true; devLog(`4.2B Sync: Creating Constants and executing three-pass WebSocket Sync...`); if (!debugState.domainI) { devLog(`⚠ 4.2B Sync: Missing setup state. Please run Setup first.`); btn.disabled = false; return; } const metaspace = await getGlobalMetaspace_waitIfNeeded(); const space = await metaspace.getLocalUserSpace({}); if (!space) { throw new Error("No default space."); } // 1. Create Constant C1 locally const c1 = await factory.constant({ parentPrimitiveIb: 'root', ib: 'constant_c1_' + (await getUUID()).slice(0, 8), data: { some: 'data_4_2b', random: Math.random() }, }); const addrC1 = getIbGibAddr({ ibGib: c1 }); await metaspace.put({ ibGib: c1, space }); await metaspace.registerNewIbGib({ ibGib: c1 }); debugState.targetC1 = c1; devLog(`4.2B Sync: ✓ Constant C1 created: ${addrC1}`); // --- Sync 1: C1 First Pass --- devLog(`4.2B Sync: Starting Pass 1 (Sync C1)...`); await runSyncPass({ domainIbGibs: [c1], passLabel: 'Pass 1 (Sync C1)', metaspace, space }); devLog(`4.2B Sync: ✓ Pass 1 Complete.`); // --- Sync 2: C1 Second Pass (Idempotent check) --- devLog(`4.2B Sync: Starting Pass 2 (Sync C1 - Idempotent)...`); await runSyncPass({ domainIbGibs: [c1], passLabel: 'Pass 2 (Sync C1 idempotent)', metaspace, space }); devLog(`4.2B Sync: ✓ Pass 2 Complete.`); // 2. Create Constant C2 locally linking to C1 const c2 = await factory.constant({ ib: 'constant_c2_' + (await getUUID()).slice(0, 8), parentPrimitiveIb: 'root', rel8ns: { link: [addrC1] }, }); const addrC2 = getIbGibAddr({ ibGib: c2 }); await metaspace.put({ ibGib: c2, space }); await metaspace.registerNewIbGib({ ibGib: c2 }); debugState.targetC2 = c2; devLog(`4.2B Sync: ✓ Constant C2 created linking to C1: ${addrC2}`); // --- Sync 3: C2 Pass --- devLog(`4.2B Sync: Starting Pass 3 (Sync C2)...`); await runSyncPass({ domainIbGibs: [c2], passLabel: 'Pass 3 (Sync C2)', metaspace, space }); devLog(`4.2B Sync: ✓ Pass 3 Complete.`); devLog(`✓ 4.2B Sync Sequence Complete! Ready for State Checks.`); btn.textContent = `✓ 4.2B Sync Run`; const checkBtn = document.getElementById('btn-4-2b-check') as HTMLButtonElement | null; if (checkBtn) { checkBtn.disabled = false; } } catch (error) { devLog(`✗ 4.2B Sync FAILED: ${extractErrorMsg(error)}`); console.error(`${lc_fn} 4.2B Sync error:`, error); btn.disabled = false; } } export function init4_2bSyncButton(): void { const btn = document.getElementById('btn-4-2b-sync') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', () => { performPhaseSync4_2b(); }); } export function init4_2bCheckButton(): void { const lc_fn = `${lc}[init4_2bCheckButton]`; const btn = document.getElementById('btn-4-2b-check') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', async () => { try { devLog('4.2B Check: Asserting cryptographic and WebSocket state expectations...'); const metaspace = await getGlobalMetaspace_waitIfNeeded(); const space = await metaspace.getLocalUserSpace({}); if (!space) { throw new Error("No default space."); } const domainI = debugState.domainI!; const targetC1 = debugState.targetC1!; const targetC2 = debugState.targetC2!; const c1Addr = getIbGibAddr({ ibGib: targetC1 }); const c2Addr = getIbGibAddr({ ibGib: targetC2 }); const domainAddr = getIbGibAddr({ ibGib: domainI }); const apiBridge = new SpaceGibApiBridge(); // 1. Verify C1 and C2 exist locally const localC1Res = await metaspace.get({ addrs: [c1Addr], space }); const localC2Res = await metaspace.get({ addrs: [c2Addr], space }); if (!localC1Res.success || !localC1Res.ibGibs?.[0]) { devLog('✗ Check: Constant C1 NOT found locally.'); return; } if (!localC2Res.success || !localC2Res.ibGibs?.[0]) { devLog('✗ Check: Constant C2 NOT found locally.'); return; } devLog(`✓ Check: Constants C1 and C2 exist locally.`); // 2. Verify C1 and C2 on server, C2 dependency graph matches const serverC1Res = await apiBridge.getIbGib(domainAddr, c1Addr); const serverC2Res = await apiBridge.getIbGib(domainAddr, c2Addr); if (!serverC1Res.success || !serverC1Res.ibGib) { devLog(`✗ Check: Constant C1 NOT found on server: ${serverC1Res.message}`); return; } if (!serverC2Res.success || !serverC2Res.ibGib) { devLog(`✗ Check: Constant C2 NOT found on server: ${serverC2Res.message}`); return; } devLog(`✓ Check: Constants C1 and C2 exist on server.`); const localC2Graph = await metaspace.getDependencyGraph({ ibGibAddr: c2Addr, space }); const serverC2GetGraphRes = await apiBridge.getIbGibGraph(domainAddr, c2Addr, true); if (!serverC2GetGraphRes.success || !serverC2GetGraphRes.graph) { devLog(`✗ Check: Failed to fetch C2 graph from server: ${serverC2GetGraphRes.message}`); return; } if (!graphsAreEquivalent({ graphA: localC2Graph, graphB: serverC2GetGraphRes.graph })) { devLog('✗ Check: C2 dependency graphs mismatch between client and server!'); return; } devLog('✓ Check: C2 dependency graphs are equivalent on client and server.'); // 3. Verify domain keystone n=1, then verify domain/delegate/session on server. // I only evolves once (delegate registration during setup). // The delegate is the sync sender and evolves during sync passes, not I. const latestLocalIAddr = await metaspace.getLatestAddr({ addr: domainAddr, space }); if (!latestLocalIAddr) { devLog('✗ Check: Domain keystone tip not found locally!'); return; } const localIRes = await metaspace.get({ addrs: [latestLocalIAddr], space }); const localI = localIRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined; if (!localI) { devLog('✗ Check: Failed to load domain keystone!'); return; } const nI = localI.data?.n; devLog(`✓ Check: Evolved I tip is at n = ${nI}.`); if (nI !== 1) { devLog(`✗ Check: Expected I to evolve to n = 1 (delegate registration only), got n = ${nI}.`); return; } const { sessionIdentityTjpAddr } = await verifyIdentitiesOnServer({ localI, metaspace, space, apiBridge, domainAddr }); // 4. Verify session keystone S n=3 and graph matches. // The session S from the final (3rd) pass goes through connect(n=1), sync(n=2), disconnect(n=3). const latestLocalSAddr = await metaspace.getLatestAddr({ addr: sessionIdentityTjpAddr, space }); if (!latestLocalSAddr) { devLog('✗ Check: Latest Session Keystone (S) NOT found in local space.'); return; } devLog(`✓ Check: Found latest session keystone (S) locally: ${latestLocalSAddr}`); const localSRes = await metaspace.get({ addrs: [latestLocalSAddr], space }); const sessionS = localSRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined; if (!sessionS) { devLog('✗ Check: Failed to load Session Keystone (S) locally.'); return; } const nS = sessionS.data?.n; devLog(`✓ Check: Latest session S tip evolved to n = ${nS}.`); if (nS !== 3) { devLog(`✗ Check: Expected latest session S to evolve to n = 3 (connect+sync+disconnect), got n = ${nS}.`); return; } const serverSGetRes = await apiBridge.getIbGib(domainAddr, latestLocalSAddr); if (!serverSGetRes.success || !serverSGetRes.ibGib) { devLog(`✗ Check: Latest Session Keystone (S) NOT found on server!`); return; } devLog(`✓ Check: Latest Session Keystone (S) exists on server.`); const localSGraph = await metaspace.getDependencyGraph({ ibGibAddr: latestLocalSAddr, space }); const serverSGetGraphRes = await apiBridge.getIbGibGraph(domainAddr, sessionIdentityTjpAddr, true); if (!serverSGetGraphRes.success || !serverSGetGraphRes.graph) { devLog(`✗ Check: Failed to fetch session S graph from server: ${serverSGetGraphRes.message}`); return; } if (!graphsAreEquivalent({ graphA: localSGraph, graphB: serverSGetGraphRes.graph })) { devLog('✗ Check: Session Keystone (S) dependency graphs mismatch between client and server!'); return; } devLog('✓ Check: Session Keystone (S) dependency graphs are equivalent on client and server.'); devLog('🎉 ALL PHASE 4.2B TRANSACTION SYNC CHECKS PASSED FLAWLESSLY! ✓'); btn.textContent = '✓ 4.2B All Passed'; } catch (error) { devLog(`✗ 4.2B Check FAILED: ${extractErrorMsg(error)}`); console.error(`${lc_fn} 4.2B Check error:`, error); } }); }