@ibgib/space-gib 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/IMPLEMENTATION.md +9 -13
  3. package/dist/client/bootstrap.mjs +1 -1
  4. package/dist/client/bootstrap.mjs.map +1 -1
  5. package/dist/client/chunk-NCXKCVYS.mjs +42 -0
  6. package/dist/client/chunk-NCXKCVYS.mjs.map +7 -0
  7. package/dist/client/chunk-ZUEU37Z5.mjs +1920 -0
  8. package/dist/client/chunk-ZUEU37Z5.mjs.map +7 -0
  9. package/dist/client/index.html +103 -5
  10. package/dist/client/index.mjs +1 -1
  11. package/dist/client/script.mjs +1 -1
  12. package/dist/client/style.css +466 -61
  13. package/dist/respec-gib.node.mjs +5 -0
  14. package/dist/server/server.mjs +294 -225
  15. package/dist/server/server.mjs.map +2 -2
  16. package/package.json +6 -6
  17. package/src/client/AUTO-GENERATED-version.mts +1 -1
  18. package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
  19. package/src/client/components/identity-header/identity-header.css +74 -0
  20. package/src/client/components/identity-header/identity-header.html +10 -0
  21. package/src/client/components/identity-header/identity-header.mts +361 -0
  22. package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
  23. package/src/client/components/identity-manager/identity-manager.css +467 -0
  24. package/src/client/components/identity-manager/identity-manager.html +113 -0
  25. package/src/client/components/identity-manager/identity-manager.mts +767 -0
  26. package/src/client/components/keystone-creator/keystone-creator.css +2 -76
  27. package/src/client/components/keystone-creator/keystone-creator.html +41 -26
  28. package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
  29. package/src/client/dev-tools/base-tools.mts +252 -0
  30. package/src/client/dev-tools/common.mts +217 -0
  31. package/src/client/dev-tools/phase-1.mts +156 -0
  32. package/src/client/dev-tools/phase-2.mts +143 -0
  33. package/src/client/dev-tools/phase-3.mts +189 -0
  34. package/src/client/dev-tools/phase-4-1.mts +197 -0
  35. package/src/client/dev-tools/phase-4-10.mts +884 -0
  36. package/src/client/dev-tools/phase-4-2.mts +388 -0
  37. package/src/client/dev-tools/phase-4-3.mts +391 -0
  38. package/src/client/dev-tools/phase-4-4.mts +374 -0
  39. package/src/client/dev-tools/phase-4-5.mts +376 -0
  40. package/src/client/dev-tools/phase-4-6.mts +273 -0
  41. package/src/client/dev-tools/phase-4-7.mts +399 -0
  42. package/src/client/dev-tools/phase-4-8.mts +430 -0
  43. package/src/client/dev-tools/phase-4-9.mts +398 -0
  44. package/src/client/dev-tools/phase-4.mts +1302 -0
  45. package/src/client/dev-tools.mts +52 -1194
  46. package/src/client/index.html +103 -5
  47. package/src/client/style.css +466 -61
  48. package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
  49. package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
  50. package/src/common/common-constants.mts +0 -0
  51. package/src/common/keystone-policies.json +40 -43
  52. package/src/common/keystone-policies.mts +3 -5
  53. package/src/server/path-helper.respec.mts +99 -94
  54. package/src/server/serve-gib/README.md +9 -0
  55. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
  56. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +1 -1
  57. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +31 -3
  58. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  59. package/dist/client/chunk-2KJC5XKE.mjs +0 -31
  60. package/dist/client/chunk-2KJC5XKE.mjs.map +0 -7
  61. package/dist/client/chunk-QNIXTRFO.mjs +0 -235
  62. package/dist/client/chunk-QNIXTRFO.mjs.map +0 -7
@@ -0,0 +1,143 @@
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
+
7
+ import { debugState, devLog, lc, performPhaseSetup, performPhaseSync } from './common.mjs';
8
+
9
+ export function init2bSetupButton(): void {
10
+ const btn = document.getElementById('btn-2b-setup') as HTMLButtonElement | null;
11
+ if (!btn) { return; }
12
+ btn.addEventListener('click', () => {
13
+ performPhaseSetup({
14
+ phaseText: '2B',
15
+ btnId: 'btn-2b-setup',
16
+ nextBtnId: 'btn-2b-sync',
17
+ masterSecret: 'test-sender-secret-phase2',
18
+ syncSalt: 'senderidentitysyncsaltphase2',
19
+ manageSalt: 'senderidentitymanagesaltphase2',
20
+ ib: 'test data',
21
+ data: { hello: 'world2', random: Math.random() }
22
+ });
23
+ });
24
+ }
25
+
26
+ export function init2bSyncButton(): void {
27
+ const btn = document.getElementById('btn-2b-sync') as HTMLButtonElement | null;
28
+ if (!btn) { return; }
29
+ btn.addEventListener('click', () => {
30
+ performPhaseSync({
31
+ phaseText: '2B',
32
+ btnId: 'btn-2b-sync',
33
+ nextBtnId: 'btn-2b-check',
34
+ expectSyncFailure: true,
35
+ failureMessageSuffix: 'connect phase successfully run; subsequent sync errors expected in 2B'
36
+ });
37
+ });
38
+ }
39
+
40
+ export function init2bCheckButton(): void {
41
+ const lc_fn = `${lc}[init2bCheckButton]`;
42
+ const btn = document.getElementById('btn-2b-check') as HTMLButtonElement | null;
43
+ if (!btn) { return; }
44
+
45
+ btn.addEventListener('click', async () => {
46
+ try {
47
+ devLog('2B Check: Asserting cryptographic and WebSocket state expectations...');
48
+
49
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
50
+ const space = await metaspace.getLocalUserSpace({});
51
+ if (!space) { throw new Error("No default space."); }
52
+
53
+ const domainI = debugState.domainI!;
54
+
55
+ // 1. Resolve evolved sender identity I1 locally
56
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
57
+ const newSenderIdentityAddr = await metaspace.getLatestAddr({
58
+ addr: domainAddr,
59
+ space
60
+ });
61
+
62
+ if (!newSenderIdentityAddr) {
63
+ devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
64
+ return;
65
+ }
66
+ devLog(`✓ Check: Evolved Domain Keystone (I1) created and stored locally.`);
67
+
68
+ const getRes = await metaspace.get({ addrs: [newSenderIdentityAddr], space });
69
+ const newSenderIdentity = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
70
+
71
+ if (!newSenderIdentity) {
72
+ devLog('✗ Check: Failed to load I1 from local space.');
73
+ return;
74
+ }
75
+
76
+ const syncProof = newSenderIdentity.data?.proofs?.find(p => p.claim?.verb === 'sync');
77
+ const sessionIdentityTjpAddr = syncProof?.claim?.target;
78
+ if (!sessionIdentityTjpAddr) {
79
+ devLog('✗ Check: I1 sync claim does not target a session keystone.');
80
+ return;
81
+ }
82
+ devLog(`✓ Check: Sync claim targets session keystone: ${sessionIdentityTjpAddr}`);
83
+
84
+ // 2. Load Session Keystone (S) locally and get latest tip
85
+ const latestSessionSAddr = await metaspace.getLatestAddr({
86
+ addr: sessionIdentityTjpAddr,
87
+ space
88
+ });
89
+ if (!latestSessionSAddr) {
90
+ devLog('✗ Check: Latest Session Keystone (S) NOT found in local space.');
91
+ return;
92
+ }
93
+ devLog(`✓ Check: Found latest session keystone (S) locally.`);
94
+
95
+ const sRes = await metaspace.get({ addrs: [latestSessionSAddr], space });
96
+ const sessionIdentity = sRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
97
+
98
+ if (!sessionIdentity) {
99
+ devLog('✗ Check: Failed to load latest Session Keystone (S).');
100
+ return;
101
+ }
102
+
103
+ // Verify S contains connect and sync pools
104
+ const sPools = sessionIdentity.data?.challengePools ?? [];
105
+ const connectPool = sPools.find(p => p.id === POOL_ID_CONNECT);
106
+ const syncPool = sPools.find(p => p.id === POOL_ID_SYNC);
107
+
108
+ if (connectPool && syncPool) {
109
+ devLog('✓ Check: S contains both connect and sync challenge pools.');
110
+ } else {
111
+ devLog(`✗ Check: S is missing challenge pools! (connect: ${!!connectPool}, sync: ${!!syncPool})`);
112
+ return;
113
+ }
114
+
115
+ // Verify S was successfully evolved (depleted connect pool)
116
+ const remainingChallenges = Object.keys(connectPool.challenges).length;
117
+ if (remainingChallenges === 0) {
118
+ devLog('✓ Check: S connect pool successfully depleted (0 challenges remaining).');
119
+ } else {
120
+ devLog(`✗ Check: S connect pool not depleted! (${remainingChallenges} challenges remaining)`);
121
+ return;
122
+ }
123
+
124
+ // 3. Verify WebSocket Connection is open and active
125
+ if (debugState.senderPeer && debugState.senderPeer.isSocketOpen) {
126
+ devLog('✓ Check: WebSocket connection is active and OPEN.');
127
+ } else {
128
+ devLog('✗ Check: WebSocket connection is NOT open or peer is missing!');
129
+ return;
130
+ }
131
+
132
+ devLog('🎉 ALL PHASE 2B CONNECT CHECKS PASSED FLAWLESSLY! ✓');
133
+ btn.textContent = '✓ 2B All Passed';
134
+
135
+ const p3SetupBtn = document.getElementById('btn-3b-setup') as HTMLButtonElement | null;
136
+ if (p3SetupBtn) { p3SetupBtn.disabled = false; }
137
+
138
+ } catch (error) {
139
+ devLog(`✗ 2B Check FAILED: ${extractErrorMsg(error)}`);
140
+ console.error(`${lc_fn} 2B Check error:`, error);
141
+ }
142
+ });
143
+ }
@@ -0,0 +1,189 @@
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 { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
5
+ import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.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 init3bSetupButton(): void {
11
+ const btn = document.getElementById('btn-3b-setup') as HTMLButtonElement | null;
12
+ if (!btn) { return; }
13
+ btn.addEventListener('click', () => {
14
+ performPhaseSetup({
15
+ phaseText: '3B',
16
+ btnId: 'btn-3b-setup',
17
+ nextBtnId: 'btn-3b-sync',
18
+ masterSecret: 'test-sender-secret-phase3',
19
+ syncSalt: 'senderidentitysyncsaltphase3',
20
+ manageSalt: 'senderidentitymanagesaltphase3',
21
+ ib: 'test data 3b',
22
+ data: { hello: 'world3', random: Math.random() }
23
+ });
24
+ });
25
+ }
26
+
27
+ export function init3bSyncButton(): void {
28
+ const btn = document.getElementById('btn-3b-sync') as HTMLButtonElement | null;
29
+ if (!btn) { return; }
30
+ btn.addEventListener('click', () => {
31
+ performPhaseSync({
32
+ phaseText: '3B',
33
+ btnId: 'btn-3b-sync',
34
+ nextBtnId: 'btn-3b-check'
35
+ });
36
+ });
37
+ }
38
+
39
+ export function init3bCheckButton(): void {
40
+ const lc_fn = `${lc}[init3bCheckButton]`;
41
+ const btn = document.getElementById('btn-3b-check') as HTMLButtonElement | null;
42
+ if (!btn) { return; }
43
+
44
+ btn.addEventListener('click', async () => {
45
+ try {
46
+ devLog('3B Check: Asserting cryptographic and WebSocket state expectations...');
47
+
48
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
49
+ const space = await metaspace.getLocalUserSpace({});
50
+ if (!space) { throw new Error("No default space."); }
51
+
52
+ const domainI = debugState.domainI!;
53
+ const targetX = debugState.targetX!;
54
+ const xAddr = getIbGibAddr({ ibGib: targetX });
55
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
56
+
57
+ // 1. Assert Target X exists locally (with evolved timeline) and get latest local graph
58
+ const latestLocalXAddr = await metaspace.getLatestAddr({
59
+ addr: xAddr,
60
+ space
61
+ });
62
+ if (!latestLocalXAddr) {
63
+ devLog('✗ Check: Evolved target X NOT found in local space!');
64
+ return;
65
+ }
66
+ devLog(`✓ Check: Evolved target X found locally at: ${latestLocalXAddr}`);
67
+
68
+ const localXGraph = await metaspace.getDependencyGraph({
69
+ ibGibAddr: latestLocalXAddr,
70
+ space
71
+ });
72
+ if (!localXGraph || Object.keys(localXGraph).length === 0) {
73
+ devLog('✗ Check: Failed to load target X dependency graph locally.');
74
+ return;
75
+ }
76
+ devLog(`✓ Check: Target X local graph loaded (${Object.keys(localXGraph).length} nodes).`);
77
+
78
+ // 2. Fetch server's Target X graph via API bridge
79
+ const apiBridge = new SpaceGibApiBridge();
80
+ const serverGetRes = await apiBridge.getIbGibGraph(domainAddr, xAddr, true);
81
+ if (!serverGetRes.success || !serverGetRes.graph) {
82
+ devLog(`✗ Check: Failed to fetch target X graph from server: ${serverGetRes.message}`);
83
+ return;
84
+ }
85
+ const serverXGraph = serverGetRes.graph;
86
+ devLog(`✓ Check: Target X server graph loaded (${Object.keys(serverXGraph).length} nodes).`);
87
+
88
+ // 3. Verify graphs are equivalent using graphsAreEquivalent
89
+ const equal = graphsAreEquivalent({ graphA: localXGraph, graphB: serverXGraph });
90
+ if (equal) {
91
+ devLog('✓ Check: Target X dependency graphs are equivalent on client and server.');
92
+ } else {
93
+ devLog('✗ Check: Target X dependency graphs mismatch between client and server!');
94
+ return;
95
+ }
96
+
97
+ // 4. Assert evolved sender identity I1 exists locally and on server
98
+ const latestLocalIAddr = await metaspace.getLatestAddr({
99
+ addr: domainAddr,
100
+ space
101
+ });
102
+ if (!latestLocalIAddr) {
103
+ devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
104
+ return;
105
+ }
106
+ devLog(`✓ Check: Evolved Domain Keystone (I1) exists locally.`);
107
+
108
+ const getRes = await metaspace.get({ addrs: [latestLocalIAddr], space });
109
+ const localI = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
110
+ if (!localI) {
111
+ devLog('✗ Check: Failed to load I1 from local space.');
112
+ return;
113
+ }
114
+
115
+ const syncProof = localI.data?.proofs?.find(p => p.claim?.verb === 'sync');
116
+ const sessionIdentityTjpAddr = syncProof?.claim?.target;
117
+ if (!sessionIdentityTjpAddr) {
118
+ devLog('✗ Check: I1 sync claim does not target a session keystone.');
119
+ return;
120
+ }
121
+
122
+ const serverIGetRes = await apiBridge.getIbGib(domainAddr, latestLocalIAddr);
123
+ if (!serverIGetRes.success || !serverIGetRes.ibGib) {
124
+ devLog(`✗ Check: Evolved Domain Keystone (I1) NOT found on server!`);
125
+ return;
126
+ }
127
+ devLog(`✓ Check: Evolved Domain Keystone (I1) exists on server.`);
128
+
129
+ // 5. Assert session identity S tip exists locally and on server
130
+ const latestLocalSAddr = await metaspace.getLatestAddr({
131
+ addr: sessionIdentityTjpAddr,
132
+ space
133
+ });
134
+ if (!latestLocalSAddr) {
135
+ devLog('✗ Check: Latest Session Keystone (S) NOT found in local space.');
136
+ return;
137
+ }
138
+ devLog(`✓ Check: Found latest session keystone (S) locally: ${latestLocalSAddr}`);
139
+
140
+ const localSRes = await metaspace.get({ addrs: [latestLocalSAddr], space });
141
+ const sessionS = localSRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
142
+ if (!sessionS) {
143
+ devLog('✗ Check: Failed to load latest Session Keystone (S) locally.');
144
+ return;
145
+ }
146
+
147
+ // Verify S evolved to correct n (n === 3 or 4)
148
+ const n = sessionS.data?.n;
149
+ devLog(`✓ Check: S tip evolved to n = ${n}.`);
150
+ if (n !== 3 && n !== 4) {
151
+ devLog(`⚠ Check: Expected S to evolve to n = 3 or 4, got n = ${n}. Continuing anyway...`);
152
+ }
153
+
154
+ const serverSGetRes = await apiBridge.getIbGib(domainAddr, latestLocalSAddr);
155
+ if (!serverSGetRes.success || !serverSGetRes.ibGib) {
156
+ devLog(`✗ Check: Latest Session Keystone (S) NOT found on server!`);
157
+ return;
158
+ }
159
+ devLog(`✓ Check: Latest Session Keystone (S) exists on server.`);
160
+
161
+ // 6. Assert S graph is identical on client and server
162
+ const localSGraph = await metaspace.getDependencyGraph({
163
+ ibGibAddr: latestLocalSAddr,
164
+ space
165
+ });
166
+ const serverSGetGraphRes = await apiBridge.getIbGibGraph(domainAddr, sessionIdentityTjpAddr, true);
167
+ if (!serverSGetGraphRes.success || !serverSGetGraphRes.graph) {
168
+ devLog(`✗ Check: Failed to fetch session S graph from server: ${serverSGetGraphRes.message}`);
169
+ return;
170
+ }
171
+ const serverSGraph = serverSGetGraphRes.graph;
172
+
173
+ const sGraphsEqual = graphsAreEquivalent({ graphA: localSGraph, graphB: serverSGraph });
174
+ if (sGraphsEqual) {
175
+ devLog('✓ Check: Session Keystone (S) dependency graphs are equivalent on client and server.');
176
+ } else {
177
+ devLog('✗ Check: Session Keystone (S) dependency graphs mismatch between client and server!');
178
+ return;
179
+ }
180
+
181
+ devLog('🎉 ALL PHASE 3B TRANSACTION SYNC CHECKS PASSED FLAWLESSLY! ✓');
182
+ btn.textContent = '✓ 3B All Passed';
183
+
184
+ } catch (error) {
185
+ devLog(`✗ 3B Check FAILED: ${extractErrorMsg(error)}`);
186
+ console.error(`${lc_fn} 3B Check error:`, error);
187
+ }
188
+ });
189
+ }
@@ -0,0 +1,197 @@
1
+ import { extractErrorMsg, getUUID, getTimestamp } 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 { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
6
+ import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
7
+ import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
+ import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
9
+ import { graphsAreEquivalent } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs';
10
+ import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
11
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
12
+ import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
13
+ import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
14
+ import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
15
+
16
+ import { debugState, devLog, lc, performPhaseSetup, performPhaseSync } from './common.mjs';
17
+
18
+ export function init4_1bSetupButton(): void {
19
+ const btn = document.getElementById('btn-4-1b-setup') as HTMLButtonElement | null;
20
+ if (!btn) { return; }
21
+ btn.addEventListener('click', () => {
22
+ performPhaseSetup({
23
+ phaseText: '4.1B',
24
+ btnId: 'btn-4-1b-setup',
25
+ nextBtnId: 'btn-4-1b-sync',
26
+ masterSecret: 'test-sender-secret-phase4-1',
27
+ syncSalt: 'senderidentitysyncsaltphase4-1',
28
+ manageSalt: 'senderidentitymanagesaltphase4-1',
29
+ ib: 'test data 4.1b',
30
+ data: { hello: 'world4_1', random: Math.random() }
31
+ });
32
+ });
33
+ }
34
+
35
+ export function init4_1bSyncButton(): void {
36
+ const btn = document.getElementById('btn-4-1b-sync') as HTMLButtonElement | null;
37
+ if (!btn) { return; }
38
+ btn.addEventListener('click', () => {
39
+ performPhaseSync({
40
+ phaseText: '4.1B',
41
+ btnId: 'btn-4-1b-sync',
42
+ nextBtnId: 'btn-4-1b-check'
43
+ });
44
+ });
45
+ }
46
+
47
+ export function init4_1bCheckButton(): void {
48
+ const lc_fn = `${lc}[init4_1bCheckButton]`;
49
+ const btn = document.getElementById('btn-4-1b-check') as HTMLButtonElement | null;
50
+ if (!btn) { return; }
51
+
52
+ btn.addEventListener('click', async () => {
53
+ try {
54
+ devLog('4.1B Check: Asserting cryptographic and WebSocket state expectations...');
55
+
56
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
57
+ const space = await metaspace.getLocalUserSpace({});
58
+ if (!space) { throw new Error("No default space."); }
59
+
60
+ const domainI = debugState.domainI!;
61
+ const targetX = debugState.targetX!;
62
+ const xAddr = getIbGibAddr({ ibGib: targetX });
63
+ const domainAddr = getIbGibAddr({ ibGib: domainI });
64
+
65
+ // 1. Assert Target X exists locally (with evolved timeline) and get latest local graph
66
+ const latestLocalXAddr = await metaspace.getLatestAddr({
67
+ addr: xAddr,
68
+ space
69
+ });
70
+ if (!latestLocalXAddr) {
71
+ devLog('✗ Check: Evolved target X NOT found in local space!');
72
+ return;
73
+ }
74
+ devLog(`✓ Check: Evolved target X found locally at: ${latestLocalXAddr}`);
75
+
76
+ const localXGraph = await metaspace.getDependencyGraph({
77
+ ibGibAddr: latestLocalXAddr,
78
+ space
79
+ });
80
+ if (!localXGraph || Object.keys(localXGraph).length === 0) {
81
+ devLog('✗ Check: Failed to load target X dependency graph locally.');
82
+ return;
83
+ }
84
+ devLog(`✓ Check: Target X local graph loaded (${Object.keys(localXGraph).length} nodes).`);
85
+
86
+ // 2. Fetch server's Target X graph via API bridge
87
+ const apiBridge = new SpaceGibApiBridge();
88
+ const serverGetRes = await apiBridge.getIbGibGraph(domainAddr, xAddr, true);
89
+ if (!serverGetRes.success || !serverGetRes.graph) {
90
+ devLog(`✗ Check: Failed to fetch target X graph from server: ${serverGetRes.message}`);
91
+ return;
92
+ }
93
+ const serverXGraph = serverGetRes.graph;
94
+ devLog(`✓ Check: Target X server graph loaded (${Object.keys(serverXGraph).length} nodes).`);
95
+
96
+ // 3. Verify graphs are equivalent using graphsAreEquivalent
97
+ const equal = graphsAreEquivalent({ graphA: localXGraph, graphB: serverXGraph });
98
+ if (equal) {
99
+ devLog('✓ Check: Target X dependency graphs are equivalent on client and server.');
100
+ } else {
101
+ devLog('✗ Check: Target X dependency graphs mismatch between client and server!');
102
+ return;
103
+ }
104
+
105
+ // 4. Assert evolved sender identity I1 exists locally and on server
106
+ const latestLocalIAddr = await metaspace.getLatestAddr({
107
+ addr: domainAddr,
108
+ space
109
+ });
110
+ if (!latestLocalIAddr) {
111
+ devLog('✗ Check: Evolved domain keystone tip I1 NOT found in local space!');
112
+ return;
113
+ }
114
+ devLog(`✓ Check: Evolved Domain Keystone (I1) exists locally.`);
115
+
116
+ const getRes = await metaspace.get({ addrs: [latestLocalIAddr], space });
117
+ const localI = getRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
118
+ if (!localI) {
119
+ devLog('✗ Check: Failed to load I1 from local space.');
120
+ return;
121
+ }
122
+
123
+ const syncProof = localI.data?.proofs?.find(p => p.claim?.verb === 'sync');
124
+ const sessionIdentityTjpAddr = syncProof?.claim?.target;
125
+ if (!sessionIdentityTjpAddr) {
126
+ devLog('✗ Check: I1 sync claim does not target a session keystone.');
127
+ return;
128
+ }
129
+
130
+ const serverIGetRes = await apiBridge.getIbGib(domainAddr, latestLocalIAddr);
131
+ if (!serverIGetRes.success || !serverIGetRes.ibGib) {
132
+ devLog(`✗ Check: Evolved Domain Keystone (I1) NOT found on server!`);
133
+ return;
134
+ }
135
+ devLog(`✓ Check: Evolved Domain Keystone (I1) exists on server.`);
136
+
137
+ // 5. Assert session identity S tip exists locally and on server
138
+ const latestLocalSAddr = await metaspace.getLatestAddr({
139
+ addr: sessionIdentityTjpAddr,
140
+ space
141
+ });
142
+ if (!latestLocalSAddr) {
143
+ devLog('✗ Check: Latest Session Keystone (S) NOT found in local space.');
144
+ return;
145
+ }
146
+ devLog(`✓ Check: Found latest session keystone (S) locally: ${latestLocalSAddr}`);
147
+
148
+ const localSRes = await metaspace.get({ addrs: [latestLocalSAddr], space });
149
+ const sessionS = localSRes.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
150
+ if (!sessionS) {
151
+ devLog('✗ Check: Failed to load latest Session Keystone (S) locally.');
152
+ return;
153
+ }
154
+
155
+ // Verify S evolved to correct n (n === 3 or 4)
156
+ const n = sessionS.data?.n;
157
+ devLog(`✓ Check: S tip evolved to n = ${n}.`);
158
+ if (n !== 3 && n !== 4) {
159
+ devLog(`⚠ Check: Expected S to evolve to n = 3 or 4, got n = ${n}. Continuing anyway...`);
160
+ }
161
+
162
+ const serverSGetRes = await apiBridge.getIbGib(domainAddr, latestLocalSAddr);
163
+ if (!serverSGetRes.success || !serverSGetRes.ibGib) {
164
+ devLog(`✗ Check: Latest Session Keystone (S) NOT found on server!`);
165
+ return;
166
+ }
167
+ devLog(`✓ Check: Latest Session Keystone (S) exists on server.`);
168
+
169
+ // 6. Assert S graph is identical on client and server
170
+ const localSGraph = await metaspace.getDependencyGraph({
171
+ ibGibAddr: latestLocalSAddr,
172
+ space
173
+ });
174
+ const serverSGetGraphRes = await apiBridge.getIbGibGraph(domainAddr, sessionIdentityTjpAddr, true);
175
+ if (!serverSGetGraphRes.success || !serverSGetGraphRes.graph) {
176
+ devLog(`✗ Check: Failed to fetch session S graph from server: ${serverSGetGraphRes.message}`);
177
+ return;
178
+ }
179
+ const serverSGraph = serverSGetGraphRes.graph;
180
+
181
+ const sGraphsEqual = graphsAreEquivalent({ graphA: localSGraph, graphB: serverSGraph });
182
+ if (sGraphsEqual) {
183
+ devLog('✓ Check: Session Keystone (S) dependency graphs are equivalent on client and server.');
184
+ } else {
185
+ devLog('✗ Check: Session Keystone (S) dependency graphs mismatch between client and server!');
186
+ return;
187
+ }
188
+
189
+ devLog('🎉 ALL PHASE 4.1B TRANSACTION SYNC CHECKS PASSED FLAWLESSLY! ✓');
190
+ btn.textContent = '✓ 4.1B All Passed';
191
+
192
+ } catch (error) {
193
+ devLog(`✗ 4.1B Check FAILED: ${extractErrorMsg(error)}`);
194
+ console.error(`${lc_fn} 4.1B Check error:`, error);
195
+ }
196
+ });
197
+ }