import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs'; import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs'; import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs'; import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs'; import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs'; import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs"; import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs'; import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs'; import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs'; import { debugState, devLog, lc, setupDomainAndDelegateIdentities, runSyncPass, verifyIdentitiesOnServer } from './common.mjs'; export function init4_3bSetupButton(): void { const btn = document.getElementById('btn-4-3b-setup') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', async () => { try { btn.disabled = true; devLog('4.3B Setup: Generating Domain Keystone (I) and Target timeline V0 -> V1...'); const metaspace = await getGlobalMetaspace_waitIfNeeded(); const space = await metaspace.getLocalUserSpace({}); if (!space) { throw new Error("No default space."); } const apiBridge = new SpaceGibApiBridge(); // Create domain + delegate identities (DRY helper) await setupDomainAndDelegateIdentities({ masterSecret: 'test-sender-secret-phase4-3', syncSalt: 'senderidentitysyncsaltphase4-3', manageSalt: 'senderidentitymanagesaltphase4-3', metaspace, space, apiBridge, phaseText: '4.3B' }); // Create timeline V0 → V1 const resV0 = await factory.firstGen({ parentIbGib: ROOT, ib: 'timeline_root_partial_4_3b', data: { type: 'root', label: 'Root4_3b', random: Math.random() }, dna: true, nCounter: true, tjp: { uuid: true, timestamp: true } }); const r1_v0 = resV0.newIbGib; await metaspace.persistTransformResult({ resTransform: resV0, space }); await metaspace.registerNewIbGib({ ibGib: r1_v0 }); const r1_v1 = await mut8Timeline({ timeline: r1_v0, mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1_4_3b' } }, metaspace, space, }); debugState.targetC1 = r1_v1; debugState.targetX = r1_v1; devLog(`4.3B Setup: ✓ Timeline V0 -> V1 created and stored locally. V1: ${getIbGibAddr({ ibGib: r1_v1 })}`); devLog('✓ 4.3B Setup Complete! Ready for 4.3B Sync.'); btn.textContent = '✓ 4.3B Setup Complete'; const syncBtn = document.getElementById('btn-4-3b-sync') as HTMLButtonElement | null; if (syncBtn) { syncBtn.disabled = false; } } catch (error) { devLog(`✗ 4.3B Setup FAILED: ${extractErrorMsg(error)}`); console.error(error); btn.disabled = false; } }); } async function performPhaseSync4_3b(): Promise { const lc_fn = `${lc}[performPhaseSync4_3b]`; const btn = document.getElementById('btn-4-3b-sync') as HTMLButtonElement | null; if (!btn) { return; } try { btn.disabled = true; const targetV1 = debugState.targetX; if (!debugState.domainI || !targetV1) { devLog(`⚠ 4.3B 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."); } // Pass 1: Sync V1 devLog(`4.3B Sync: Starting Pass 1 (Sync V1 to server)...`); await runSyncPass({ domainIbGibs: [targetV1], passLabel: 'Pass 1 (Sync V1)', metaspace, space }); devLog(`4.3B Sync: ✓ Pass 1 Complete (V1 synced).`); // Mutate V1 → V2 devLog(`4.3B Sync: Mutating V1 to V2 locally...`); const r1_v2 = await mut8Timeline({ timeline: targetV1, mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V2_4_3b' } }, metaspace, space, }); debugState.targetX = r1_v2; devLog(`4.3B Sync: ✓ V2 created locally: ${getIbGibAddr({ ibGib: r1_v2 })}`); // Pass 2: Sync V2 devLog(`4.3B Sync: Starting Pass 2 (Sync V2 delta to server)...`); await runSyncPass({ domainIbGibs: [r1_v2], passLabel: 'Pass 2 (Sync V2)', metaspace, space }); devLog(`4.3B Sync: ✓ Pass 2 Complete (V2 synced).`); devLog(`✓ 4.3B Sync Sequence Complete! Ready for State Checks.`); btn.textContent = `✓ 4.3B Sync Run`; const checkBtn = document.getElementById('btn-4-3b-check') as HTMLButtonElement | null; if (checkBtn) { checkBtn.disabled = false; } } catch (error) { devLog(`✗ 4.3B Sync FAILED: ${extractErrorMsg(error)}`); console.error(error); btn.disabled = false; } } export function init4_3bSyncButton(): void { const btn = document.getElementById('btn-4-3b-sync') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', () => { performPhaseSync4_3b(); }); } export function init4_3bCheckButton(): void { const lc_fn = `${lc}[init4_3bCheckButton]`; const btn = document.getElementById('btn-4-3b-check') as HTMLButtonElement | null; if (!btn) { return; } btn.addEventListener('click', async () => { try { devLog('4.3B 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 targetV1 = debugState.targetC1!; const targetV2 = debugState.targetX!; const v1Addr = getIbGibAddr({ ibGib: targetV1 }); const v2Addr = getIbGibAddr({ ibGib: targetV2 }); const domainAddr = getIbGibAddr({ ibGib: domainI }); const apiBridge = new SpaceGibApiBridge(); // 1. Verify V1 and V2 exist locally const localV1Res = await metaspace.get({ addrs: [v1Addr], space }); const localV2Res = await metaspace.get({ addrs: [v2Addr], space }); if (!localV1Res.success || !localV1Res.ibGibs?.[0]) { devLog('✗ Check: Timeline frame V1 NOT found locally.'); return; } if (!localV2Res.success || !localV2Res.ibGibs?.[0]) { devLog('✗ Check: Timeline frame V2 NOT found locally.'); return; } devLog(`✓ Check: Timeline frames V1 and V2 exist locally.`); // 2. Verify V2 on server with correct past ref and matching graph const serverV2Res = await apiBridge.getIbGib(domainAddr, v2Addr); if (!serverV2Res.success || !serverV2Res.ibGib) { devLog(`✗ Check: Timeline frame V2 NOT found on server: ${serverV2Res.message}`); return; } devLog(`✓ Check: Timeline frame V2 exists on server.`); const pastAddr = serverV2Res.ibGib.rel8ns?.past?.at(-1); if (pastAddr === v1Addr) { devLog('✓ Check: Server V2 correctly references V1 in its past relation.'); } else { devLog(`✗ Check: Server V2 does not reference V1 in past relation! got: ${pastAddr}`); return; } const localV2Graph = await metaspace.getDependencyGraph({ ibGibAddr: v2Addr, space }); const serverV2GetGraphRes = await apiBridge.getIbGibGraph(domainAddr, v2Addr, true); if (!serverV2GetGraphRes.success || !serverV2GetGraphRes.graph) { devLog(`✗ Check: Failed to fetch V2 graph from server: ${serverV2GetGraphRes.message}`); return; } if (!graphsAreEquivalent({ graphA: localV2Graph, graphB: serverV2GetGraphRes.graph })) { devLog('✗ Check: V2 timeline dependency graphs mismatch between client and server!'); return; } devLog('✓ Check: V2 timeline 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 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, 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.3B TRANSACTION SYNC CHECKS PASSED FLAWLESSLY! ✓'); btn.textContent = '✓ 4.3B All Passed'; } catch (error) { devLog(`✗ 4.3B Check FAILED: ${extractErrorMsg(error)}`); console.error(`${lc_fn} 4.3B Check error:`, error); } }); }