@ibgib/space-gib 0.0.4 → 0.0.6

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 (42) hide show
  1. package/README.md +7 -0
  2. package/dist/client/bootstrap.mjs +1 -1
  3. package/dist/client/chunk-734MMI4C.mjs +42 -0
  4. package/dist/client/chunk-734MMI4C.mjs.map +7 -0
  5. package/dist/client/{chunk-ZUEU37Z5.mjs → chunk-SMOZ2D5E.mjs} +170 -41
  6. package/dist/client/chunk-SMOZ2D5E.mjs.map +7 -0
  7. package/dist/client/index.html +35 -14
  8. package/dist/client/index.mjs +1 -1
  9. package/dist/client/script.mjs +1 -1
  10. package/dist/client/style.css +29 -5
  11. package/dist/server/server.mjs +338 -31
  12. package/dist/server/server.mjs.map +3 -3
  13. package/package.json +4 -4
  14. package/src/client/AUTO-GENERATED-version.mts +1 -1
  15. package/src/client/components/identity-header/identity-header.css +40 -2
  16. package/src/client/components/identity-header/identity-header.html +3 -2
  17. package/src/client/components/identity-header/identity-header.mts +87 -26
  18. package/src/client/components/identity-manager/IMPLEMENTATION.md +10 -10
  19. package/src/client/components/identity-manager/identity-manager.css +39 -0
  20. package/src/client/components/identity-manager/identity-manager.html +20 -0
  21. package/src/client/components/identity-manager/identity-manager.mts +59 -0
  22. package/src/client/components/keystone-creator/keystone-creator.mts +88 -12
  23. package/src/client/dev-tools/common.mts +505 -10
  24. package/src/client/dev-tools/phase-4-1.mts +19 -4
  25. package/src/client/dev-tools/phase-4-10.mts +77 -305
  26. package/src/client/dev-tools/phase-4-2.mts +46 -212
  27. package/src/client/dev-tools/phase-4-3.mts +57 -198
  28. package/src/client/dev-tools/phase-4-4.mts +57 -170
  29. package/src/client/dev-tools/phase-4-5.mts +48 -204
  30. package/src/client/dev-tools/phase-4-6.mts +37 -103
  31. package/src/client/dev-tools/phase-4-7.mts +44 -228
  32. package/src/client/dev-tools/phase-4-8.mts +33 -136
  33. package/src/client/dev-tools/phase-4-9.mts +33 -137
  34. package/src/client/dev-tools/phase-4.mts +30 -6
  35. package/src/client/dev-tools.mts +18 -0
  36. package/src/client/index.html +35 -14
  37. package/src/client/style.css +29 -5
  38. package/src/client/types.mts +4 -1
  39. package/dist/client/chunk-NCXKCVYS.mjs +0 -42
  40. package/dist/client/chunk-NCXKCVYS.mjs.map +0 -7
  41. package/dist/client/chunk-ZUEU37Z5.mjs.map +0 -7
  42. package/dist/respec-gib.node.mjs +0 -5
@@ -1,92 +1,64 @@
1
- import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
1
+ import { extractErrorMsg, getUUID } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
2
  import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
3
3
  import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
4
4
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
5
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
6
  import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
7
  import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
9
8
  import { getTjpAddr } from '@ibgib/core-gib/dist/common/other/ibgib-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
9
  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
10
  import { GRAFT_BASE_REL8N_NAME, GRAFT_ORPHAN_REL8N_NAME, GRAFT_INFO_REL8N_NAME } from '@ibgib/core-gib/dist/sync/graft-info/graft-info-constants.mjs';
14
- import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
15
11
  import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
16
12
 
17
- import { debugState, devLog } from './common.mjs';
13
+ import {
14
+ debugState, devLog, lc,
15
+ setupDomainAndDelegateIdentities, runSyncPass, runSyncPassFromSpace, copyIdentitiesToSpace
16
+ } from './common.mjs';
18
17
 
19
18
  interface Phase47State {
20
- domainI_latest?: KeystoneIbGib_V1;
21
19
  testRoot?: any;
22
20
  targetAlphaV2a?: any;
23
21
  targetBetaV2b?: any;
24
22
  }
25
-
26
23
  const state: Phase47State = {};
27
24
 
25
+ const MASTER_SECRET = 'test-sender-secret-phase4-7b';
26
+
28
27
  export function init4_7bSetupButton(): void {
29
28
  const btn = document.getElementById('btn-4-7b-setup') as HTMLButtonElement | null;
30
29
  if (!btn) { return; }
31
30
  btn.addEventListener('click', async () => {
32
31
  try {
33
32
  btn.disabled = true;
34
- devLog('4.7B Setup: Setting up identities, seeding history, and creating divergent branches in client and remote...');
33
+ devLog('4.7B Setup: Setting up identities, seeding history, and creating divergent branches...');
35
34
 
36
35
  const metaspace = await getGlobalMetaspace_waitIfNeeded();
37
36
  const space = await metaspace.getLocalUserSpace({}) as any;
38
37
  if (!space) { throw new Error("No default space."); }
39
38
 
40
- const keystoneService = new KeystoneService_V1();
41
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
39
+ const apiBridge = new SpaceGibApiBridge();
42
40
 
43
- // 1. Generate Domain User Identity
44
- const domainI = await keystoneService.genesis({
45
- masterSecret: 'test-sender-secret-phase4-7b',
46
- configs: [
47
- getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-7b'),
48
- getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-7b'),
49
- ],
50
- metaspace,
51
- space,
52
- frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
41
+ await setupDomainAndDelegateIdentities({
42
+ masterSecret: MASTER_SECRET,
43
+ syncSalt: 'senderidentitysyncsaltphase4-7b',
44
+ manageSalt: 'senderidentitymanagesaltphase4-7b',
45
+ metaspace, space, apiBridge, phaseText: '4.7B'
53
46
  });
54
- state.domainI_latest = domainI;
55
- let domainI_latest: any = domainI;
56
- const domainAddr = getIbGibAddr({ ibGib: domainI });
57
- devLog(`4.7B Setup: ✓ Created identity: ${domainAddr}`);
58
47
 
59
- // Register on server
60
- const apiBridge = new SpaceGibApiBridge();
61
- const resGenesis = await apiBridge.postGenesisKeystone(domainI);
62
- if (!resGenesis.success) {
63
- throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
64
- }
65
- devLog('4.7B Setup: ✓ Identity registered on server.');
48
+ const domainI = debugState.domainI!;
66
49
 
67
- // 2. Create the divergent "remote" space
68
- devLog('4.7B Setup: Creating temporary remote space...');
69
50
  const remoteSpace = await metaspace.createNewLocalSpace({
70
- opts: {
71
- allowCancel: false,
72
- spaceName: 'remote_space_4_7b',
73
- getFnPrompt: metaspace.getFnPrompt!
74
- }
51
+ opts: { allowCancel: false, spaceName: 'remote_space_4_7b', getFnPrompt: metaspace.getFnPrompt! }
75
52
  }) as any;
76
53
  await remoteSpace.initialized;
77
-
78
- // Copy user identity to remote space
79
54
  await metaspace.put({ ibGib: domainI, space: remoteSpace });
80
55
  await metaspace.registerNewIbGib({ ibGib: domainI, space: remoteSpace });
81
56
 
82
- // 3. Seed common history root -> v1 locally
83
57
  const resRoot = await factory.firstGen({
84
58
  parentIbGib: ROOT,
85
59
  ib: 'timeline_root_conflict_4_7b',
86
60
  data: { type: 'root', label: 'CommonRoot', random: Math.random() },
87
- dna: true,
88
- nCounter: true,
89
- tjp: { uuid: true, timestamp: true }
61
+ dna: true, nCounter: true, tjp: { uuid: true, timestamp: true }
90
62
  });
91
63
  const testRoot = resRoot.newIbGib;
92
64
  await metaspace.persistTransformResult({ resTransform: resRoot, space });
@@ -96,130 +68,44 @@ export function init4_7bSetupButton(): void {
96
68
  const v1_common = await mut8Timeline({
97
69
  timeline: testRoot,
98
70
  mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1Common' } },
99
- metaspace,
100
- space,
71
+ metaspace, space,
101
72
  });
102
73
 
103
- // 4. Copy common history to remote space
104
74
  const graphRoot = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: testRoot }), space });
105
75
  const graphV1 = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: v1_common }), space });
106
- const commonDepGraph = { ...graphRoot, ...graphV1 };
107
- await metaspace.put({ ibGibs: Object.values(commonDepGraph), space: remoteSpace });
76
+ await metaspace.put({ ibGibs: Object.values({ ...graphRoot, ...graphV1 }), space: remoteSpace });
108
77
  await metaspace.registerNewIbGib({ ibGib: testRoot, space: remoteSpace });
109
78
  await metaspace.registerNewIbGib({ ibGib: v1_common, space: remoteSpace });
110
79
 
111
- // 5. Initial sync of v1_common to the server so server has it
112
80
  devLog('4.7B Setup: Syncing v1_common to server...');
113
- const senderPeerInit = new SyncPeerWebSocketSender_V1({
114
- classname: 'SyncPeerWebSocketSender_V1',
115
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
116
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
117
- });
118
- const coordinatorInit = new SyncSagaCoordinator();
119
- await senderPeerInit.initializeOpts({
120
- localMetaspace: metaspace,
121
- localSpace: space,
122
- senderIdentity: domainI,
123
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
124
- sagaId: await getUUID(),
125
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
126
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
127
- targetAddrs: [domainAddr]
128
- });
129
- const syncSagaInit = await coordinatorInit.sync({
130
- domainIbGibs: [v1_common],
131
- senderIdentity: domainI,
132
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
133
- peer: senderPeerInit,
134
- localSpace: space,
135
- metaspace,
136
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
137
- });
138
- await syncSagaInit.done;
81
+ await runSyncPass({ domainIbGibs: [v1_common], passLabel: 'Seed v1_common', metaspace, space });
139
82
  devLog('4.7B Setup: ✓ Seeding complete on server.');
140
83
 
141
- // Fetch evolved user identity from space (now at n=2)
142
- const domainLatestAddr = await metaspace.getLatestAddr({ ibGib: domainI, space });
143
- if (!domainLatestAddr) { throw new Error("Could not find latest evolved identity address in local space."); }
144
- const resGetLatest = await metaspace.get({ addr: domainLatestAddr, space });
145
- if (!resGetLatest.success || !resGetLatest.ibGibs || resGetLatest.ibGibs.length === 0) {
146
- throw new Error("Could not find latest evolved identity in local space.");
147
- }
148
- domainI_latest = resGetLatest.ibGibs[0] as KeystoneIbGib_V1;
149
- state.domainI_latest = domainI_latest;
150
- devLog(`4.7B Setup: ✓ Fetched evolved identity: ${domainLatestAddr}`);
151
-
152
- // Copy evolved user identity to remote space
153
- await metaspace.put({ ibGib: domainI_latest, space: remoteSpace });
154
- await metaspace.registerNewIbGib({ ibGib: domainI_latest, space: remoteSpace });
84
+ const domainIEvolved = debugState.domainI!;
85
+ await copyIdentitiesToSpace({ domainI: domainIEvolved, metaspace, fromSpace: space, toSpace: remoteSpace });
155
86
 
156
- // 6. Create Divergence:
157
- // Client (default space) gets V2a (fieldA edit)
158
87
  const v2a = await mut8Timeline({
159
- timeline: v1_common,
160
- mut8Opts: { dataToAddOrPatch: { fieldA: 'source_edit' } },
161
- metaspace,
162
- space,
88
+ timeline: v1_common, mut8Opts: { dataToAddOrPatch: { fieldA: 'source_edit' } }, metaspace, space,
163
89
  });
164
90
  state.targetAlphaV2a = v2a;
165
91
  devLog(`4.7B Setup: ✓ Created client divergent edit V2a: ${getIbGibAddr({ ibGib: v2a })}`);
166
92
 
167
- // Remote Space gets V2b (fieldB edit)
168
93
  const v2b = await mut8Timeline({
169
- timeline: v1_common,
170
- mut8Opts: { dataToAddOrPatch: { fieldB: 'dest_edit' } },
171
- metaspace,
172
- space: remoteSpace,
94
+ timeline: v1_common, mut8Opts: { dataToAddOrPatch: { fieldB: 'dest_edit' } }, metaspace, space: remoteSpace,
173
95
  });
174
96
  state.targetBetaV2b = v2b;
175
97
  devLog(`4.7B Setup: ✓ Created remote divergent edit V2b: ${getIbGibAddr({ ibGib: v2b })}`);
176
98
 
177
- // 7. Sync V2b from remote space to server, so server tip becomes V2b
178
99
  devLog('4.7B Setup: Pushing V2b from remote space to server...');
179
- const senderPeerRemote = new SyncPeerWebSocketSender_V1({
180
- classname: 'SyncPeerWebSocketSender_V1',
181
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
182
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
100
+ await runSyncPassFromSpace({
101
+ domainIbGibs: [v2b], passLabel: 'Push V2b from remoteSpace',
102
+ metaspace, space: remoteSpace, primarySpace: space,
103
+ domainI: domainIEvolved, masterSecret: MASTER_SECRET,
183
104
  });
184
- const coordinatorRemote = new SyncSagaCoordinator();
185
- await senderPeerRemote.initializeOpts({
186
- localMetaspace: metaspace,
187
- localSpace: remoteSpace,
188
- senderIdentity: domainI_latest,
189
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
190
- sagaId: await getUUID(),
191
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
192
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
193
- targetAddrs: [domainAddr]
194
- });
195
- const syncSagaRemote = await coordinatorRemote.sync({
196
- domainIbGibs: [v2b],
197
- senderIdentity: domainI_latest,
198
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
199
- peer: senderPeerRemote,
200
- localSpace: remoteSpace,
201
- metaspace,
202
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
203
- });
204
- await syncSagaRemote.done;
205
105
  devLog('4.7B Setup: ✓ Server tip is now V2b.');
206
106
 
207
- // Fetch evolved user identity from remote space (now at n=3)
208
- const domainLatestAddrRemote = await metaspace.getLatestAddr({ ibGib: domainI, space: remoteSpace });
209
- if (!domainLatestAddrRemote) { throw new Error("Could not find latest evolved identity address in remote space."); }
210
- const resGetLatestRemote = await metaspace.get({ addr: domainLatestAddrRemote, space: remoteSpace });
211
- if (!resGetLatestRemote.success || !resGetLatestRemote.ibGibs || resGetLatestRemote.ibGibs.length === 0) {
212
- throw new Error("Could not find latest evolved identity in remote space.");
213
- }
214
- const domainI_latestRemote = resGetLatestRemote.ibGibs[0] as KeystoneIbGib_V1;
215
- await metaspace.put({ ibGib: domainI_latestRemote, space });
216
- await metaspace.registerNewIbGib({ ibGib: domainI_latestRemote, space });
217
- state.domainI_latest = domainI_latestRemote;
218
- devLog(`4.7B Setup: ✓ Copied evolved identity tip (n=3) back to default space: ${domainLatestAddrRemote}`);
219
-
220
107
  devLog('✓ 4.7B Setup Complete! Ready for 4.7B Sync.');
221
108
  btn.textContent = '✓ 4.7B Setup Complete';
222
-
223
109
  const syncBtn = document.getElementById('btn-4-7b-sync') as HTMLButtonElement | null;
224
110
  if (syncBtn) { syncBtn.disabled = false; }
225
111
 
@@ -238,60 +124,20 @@ export function init4_7bSyncButton(): void {
238
124
  try {
239
125
  btn.disabled = true;
240
126
  devLog('4.7B Sync: Initiating WebSocket Sync for divergent edit V2a...');
241
-
242
- const domainI = state.domainI_latest;
243
127
  const targetAlphaV2a = state.targetAlphaV2a;
244
- if (!domainI || !targetAlphaV2a) {
128
+ if (!debugState.domainI || !targetAlphaV2a) {
245
129
  devLog('⚠ 4.7B Sync: Missing setup state. Please run Setup first.');
246
130
  btn.disabled = false;
247
131
  return;
248
132
  }
249
-
250
- const domainAddr = getIbGibAddr({ ibGib: domainI });
251
133
  const metaspace = await getGlobalMetaspace_waitIfNeeded();
252
134
  const space = await metaspace.getLocalUserSpace({}) as any;
253
135
  if (!space) { throw new Error("No default space."); }
254
-
255
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
256
-
257
- const senderPeer = new SyncPeerWebSocketSender_V1({
258
- classname: 'SyncPeerWebSocketSender_V1',
259
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
260
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
261
- });
262
-
263
- const coordinator = new SyncSagaCoordinator();
264
- const sagaId = await getUUID();
265
-
266
- await senderPeer.initializeOpts({
267
- localMetaspace: metaspace,
268
- localSpace: space,
269
- senderIdentity: domainI,
270
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
271
- sagaId,
272
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
273
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
274
- targetAddrs: [domainAddr]
275
- });
276
-
277
- // Run Sync. Server has V2b, client has V2a. This will trigger optimistic graft merge!
278
- const syncSaga = await coordinator.sync({
279
- domainIbGibs: [targetAlphaV2a],
280
- senderIdentity: domainI,
281
- fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
282
- peer: senderPeer,
283
- localSpace: space,
284
- metaspace,
285
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
286
- });
287
- await syncSaga.done;
288
-
136
+ await runSyncPass({ domainIbGibs: [targetAlphaV2a], passLabel: 'Sync V2a (conflict merge)', metaspace, space });
289
137
  devLog('✓ 4.7B Sync Execution Complete! Ready for 4.7B Check.');
290
138
  btn.textContent = '✓ 4.7B Sync Run';
291
-
292
139
  const checkBtn = document.getElementById('btn-4-7b-check') as HTMLButtonElement | null;
293
140
  if (checkBtn) { checkBtn.disabled = false; }
294
-
295
141
  } catch (error) {
296
142
  devLog(`✗ 4.7B Sync FAILED: ${extractErrorMsg(error)}`);
297
143
  console.error(error);
@@ -307,87 +153,57 @@ export function init4_7bCheckButton(): void {
307
153
  try {
308
154
  btn.disabled = true;
309
155
  devLog('4.7B Check: Verifying merged tip (V3) contains both edits on client and server...');
310
-
311
- const domainI = state.domainI_latest;
312
156
  const testRoot = state.testRoot;
313
157
  const targetAlphaV2a = state.targetAlphaV2a;
314
158
  const targetBetaV2b = state.targetBetaV2b;
315
- if (!domainI || !testRoot || !targetAlphaV2a || !targetBetaV2b) {
159
+ if (!debugState.domainI || !testRoot || !targetAlphaV2a || !targetBetaV2b) {
316
160
  devLog('⚠ 4.7B Check: Missing state. Did Setup and Sync run?');
317
161
  btn.disabled = false;
318
162
  return;
319
163
  }
320
-
321
- const domainAddr = getIbGibAddr({ ibGib: domainI });
164
+ const domainAddr = getIbGibAddr({ ibGib: debugState.domainI });
322
165
  const tjpAddr = getTjpAddr({ ibGib: testRoot, defaultIfNone: 'incomingAddr' }) ?? getIbGibAddr({ ibGib: testRoot });
323
-
324
166
  const metaspace = await getGlobalMetaspace_waitIfNeeded();
325
167
  const space = await metaspace.getLocalUserSpace({}) as any;
326
168
  if (!space) { throw new Error("No default space."); }
327
169
 
328
- // 1. Check client default space tip
329
- const clientKV = await metaspace.getLocalUserSpace({}).then((space: any) => {
330
- return new SyncSagaCoordinator().getKnowledgeMap({
331
- space,
332
- metaspace,
333
- domainIbGibs: [testRoot]
334
- });
335
- });
170
+ const clientKV = await (metaspace.getLocalUserSpace({}) as Promise<any>).then((sp: any) =>
171
+ new SyncSagaCoordinator().getKnowledgeMap({ space: sp, metaspace, domainIbGibs: [testRoot] })
172
+ );
336
173
  const clientTipAddr = clientKV[tjpAddr];
337
174
  devLog(`4.7B Check: Client tip address: ${clientTipAddr}`);
338
-
339
- if (!clientTipAddr) {
340
- throw new Error("Client default space is missing the timeline tip.");
341
- }
175
+ if (!clientTipAddr) { throw new Error("Client default space is missing the timeline tip."); }
342
176
 
343
177
  const resTip = await metaspace.get({ addr: clientTipAddr, space });
344
- if (!resTip.success || !resTip.ibGibs || resTip.ibGibs.length === 0) {
345
- throw new Error("Client tip not found in default local space.");
346
- }
178
+ if (!resTip.success || !resTip.ibGibs?.length) { throw new Error("Client tip not found in default local space."); }
347
179
  const clientTip = resTip.ibGibs[0];
348
-
349
- if (!clientTip.data || !clientTip.data.fieldA || !clientTip.data.fieldB) {
350
- throw new Error(`Merged client tip is missing expected data edits: fieldA: ${clientTip.data?.fieldA}, fieldB: ${clientTip.data?.fieldB}`);
180
+ if (!clientTip.data?.fieldA || !clientTip.data?.fieldB) {
181
+ throw new Error(`Merged client tip missing edits: fieldA: ${clientTip.data?.fieldA}, fieldB: ${clientTip.data?.fieldB}`);
351
182
  }
352
183
  devLog('4.7B Check: ✓ Client tip has both fieldA and fieldB edits.');
353
184
 
354
- // Verify graftinfo rel8n exists
355
185
  const graftInfoRel = clientTip.rel8ns?.[GRAFT_INFO_REL8N_NAME];
356
- if (!graftInfoRel?.[0]) {
357
- throw new Error("Client tip is missing graftinfo relations.");
358
- }
186
+ if (!graftInfoRel?.[0]) { throw new Error("Client tip is missing graftinfo relations."); }
359
187
  const resGraft = await metaspace.get({ addr: graftInfoRel[0], space });
360
- if (!resGraft.success || !resGraft.ibGibs || resGraft.ibGibs.length === 0) {
361
- throw new Error("GraftInfo not found in local space.");
362
- }
188
+ if (!resGraft.success || !resGraft.ibGibs?.length) { throw new Error("GraftInfo not found in local space."); }
363
189
  const graftInfo = resGraft.ibGibs[0];
364
- const baseRel = graftInfo.rel8ns?.[GRAFT_BASE_REL8N_NAME];
365
- const orphanRel = graftInfo.rel8ns?.[GRAFT_ORPHAN_REL8N_NAME];
366
-
367
- if (!baseRel || !orphanRel) {
190
+ if (!graftInfo.rel8ns?.[GRAFT_BASE_REL8N_NAME] || !graftInfo.rel8ns?.[GRAFT_ORPHAN_REL8N_NAME]) {
368
191
  throw new Error("GraftInfo is missing graftbase or graftorphan relations.");
369
192
  }
370
193
  devLog('4.7B Check: ✓ Client graft base and orphan relations are correctly set.');
371
194
 
372
- // 2. Check server tip
373
195
  const apiBridge = new SpaceGibApiBridge();
374
- devLog('4.7B Check: Fetching server timeline graph...');
375
196
  const resServerGraph = await apiBridge.getIbGibGraph(domainAddr, clientTipAddr, true);
376
197
  if (!resServerGraph.success || !resServerGraph.graph) {
377
198
  throw new Error(`Failed to fetch merged graph from server: ${resServerGraph.message}`);
378
199
  }
379
-
380
200
  const serverTip = resServerGraph.graph[clientTipAddr];
381
- if (!serverTip) {
382
- throw new Error("Merged V3 tip is not present on the server!");
383
- }
384
-
201
+ if (!serverTip) { throw new Error("Merged V3 tip is not present on the server!"); }
385
202
  if (serverTip.data?.fieldA !== 'source_edit' || serverTip.data?.fieldB !== 'dest_edit') {
386
203
  throw new Error("Server tip data edits do not match merged values.");
387
204
  }
388
205
  devLog('4.7B Check: ✓ Server tip has matching merged edits.');
389
-
390
- devLog('✓ 4.7B Check SUCCESS: Divergent branches merged successfully on both client and server via optimistic graft!');
206
+ devLog('✓ 4.7B Check SUCCESS: Divergent branches merged successfully via optimistic graft!');
391
207
  btn.textContent = '✓ 4.7B Check Success';
392
208
 
393
209
  } catch (error) {
@@ -1,20 +1,19 @@
1
- import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
1
+ import { extractErrorMsg, getUUID } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
2
  import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
3
3
  import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
4
4
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
5
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
6
  import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
8
7
  import { mut8Timeline, appendToTimeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
9
8
  import { getTjpAddr } from '@ibgib/core-gib/dist/common/other/ibgib-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
9
  import { GRAFT_BASE_REL8N_NAME, GRAFT_ORPHAN_REL8N_NAME, GRAFT_INFO_REL8N_NAME } from '@ibgib/core-gib/dist/sync/graft-info/graft-info-constants.mjs';
14
- import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
15
10
  import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
11
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
16
12
 
17
- import { debugState, devLog } from './common.mjs';
13
+ import {
14
+ debugState, devLog, lc,
15
+ setupDomainAndDelegateIdentities, runSyncPass, runSyncPassFromSpace, copyIdentitiesToSpace
16
+ } from './common.mjs';
18
17
 
19
18
  interface Phase48State {
20
19
  domainI_latest?: KeystoneIbGib_V1;
@@ -37,32 +36,19 @@ export function init4_8bSetupButton(): void {
37
36
  const space = await metaspace.getLocalUserSpace({}) as any;
38
37
  if (!space) { throw new Error("No default space."); }
39
38
 
40
- const keystoneService = new KeystoneService_V1();
41
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
39
+ const apiBridge = new SpaceGibApiBridge();
42
40
 
43
- // 1. Generate Domain User Identity
44
- const domainI = await keystoneService.genesis({
41
+ // 1. Create domain + delegate identities (DRY helper)
42
+ await setupDomainAndDelegateIdentities({
45
43
  masterSecret: 'test-sender-secret-phase4-8b',
46
- configs: [
47
- getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-8b'),
48
- getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-8b'),
49
- ],
50
- metaspace,
51
- space,
52
- frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
44
+ syncSalt: 'senderidentitysyncsaltphase4-8b',
45
+ manageSalt: 'senderidentitymanagesaltphase4-8b',
46
+ metaspace, space, apiBridge,
47
+ phaseText: '4.8B'
53
48
  });
49
+ const domainI = debugState.domainI!;
54
50
  state.domainI_latest = domainI;
55
- let domainI_latest: any = domainI;
56
51
  const domainAddr = getIbGibAddr({ ibGib: domainI });
57
- devLog(`4.8B Setup: ✓ Created identity: ${domainAddr}`);
58
-
59
- // Register on server
60
- const apiBridge = new SpaceGibApiBridge();
61
- const resGenesis = await apiBridge.postGenesisKeystone(domainI);
62
- if (!resGenesis.success) {
63
- throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
64
- }
65
- devLog('4.8B Setup: ✓ Identity registered on server.');
66
52
 
67
53
  // 2. Create the divergent "remote" space
68
54
  devLog('4.8B Setup: Creating temporary remote space...');
@@ -75,9 +61,8 @@ export function init4_8bSetupButton(): void {
75
61
  }) as any;
76
62
  await remoteSpace.initialized;
77
63
 
78
- // Copy user identity to remote space
79
- await metaspace.put({ ibGib: domainI, space: remoteSpace });
80
- await metaspace.registerNewIbGib({ ibGib: domainI, space: remoteSpace });
64
+ // Copy user identity and delegate to remote space
65
+ await copyIdentitiesToSpace({ domainI, metaspace, fromSpace: space, toSpace: remoteSpace });
81
66
 
82
67
  // 3. Seed common history root -> v1 locally
83
68
  const resRoot = await factory.firstGen({
@@ -110,48 +95,16 @@ export function init4_8bSetupButton(): void {
110
95
 
111
96
  // 5. Initial sync of v1_common to the server so server has it
112
97
  devLog('4.8B Setup: Syncing v1_common to server...');
113
- const senderPeerInit = new SyncPeerWebSocketSender_V1({
114
- classname: 'SyncPeerWebSocketSender_V1',
115
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
116
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
117
- });
118
- const coordinatorInit = new SyncSagaCoordinator();
119
- await senderPeerInit.initializeOpts({
120
- localMetaspace: metaspace,
121
- localSpace: space,
122
- senderIdentity: domainI,
123
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
124
- sagaId: await getUUID(),
125
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
126
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
127
- targetAddrs: [domainAddr]
128
- });
129
- const syncSagaInit = await coordinatorInit.sync({
98
+ await runSyncPass({
130
99
  domainIbGibs: [v1_common],
131
- senderIdentity: domainI,
132
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
133
- peer: senderPeerInit,
134
- localSpace: space,
100
+ passLabel: 'Seed v1_common',
135
101
  metaspace,
136
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
102
+ space
137
103
  });
138
- await syncSagaInit.done;
139
104
  devLog('4.8B Setup: ✓ Seeding complete on server.');
140
105
 
141
- // Fetch evolved user identity from space (now at n=2)
142
- const domainLatestAddr = await metaspace.getLatestAddr({ ibGib: domainI, space });
143
- if (!domainLatestAddr) { throw new Error("Could not find latest evolved identity address in local space."); }
144
- const resGetLatest = await metaspace.get({ addr: domainLatestAddr, space });
145
- if (!resGetLatest.success || !resGetLatest.ibGibs || resGetLatest.ibGibs.length === 0) {
146
- throw new Error("Could not find latest evolved identity in local space.");
147
- }
148
- domainI_latest = resGetLatest.ibGibs[0] as KeystoneIbGib_V1;
149
- state.domainI_latest = domainI_latest;
150
- devLog(`4.8B Setup: ✓ Fetched evolved identity: ${domainLatestAddr}`);
151
-
152
- // Copy evolved user identity to remote space
153
- await metaspace.put({ ibGib: domainI_latest, space: remoteSpace });
154
- await metaspace.registerNewIbGib({ ibGib: domainI_latest, space: remoteSpace });
106
+ // Copy evolved delegate and domain tip to remoteSpace
107
+ await copyIdentitiesToSpace({ domainI: debugState.domainI!, metaspace, fromSpace: space, toSpace: remoteSpace });
155
108
 
156
109
  // 6. Create Divergence:
157
110
  // Client (default space) gets V2a (fieldA edit + relates newly created independent timeline Beta)
@@ -198,46 +151,17 @@ export function init4_8bSetupButton(): void {
198
151
 
199
152
  // 7. Sync V2b from remote space to server, so server tip becomes V2b
200
153
  devLog('4.8B Setup: Pushing V2b from remote space to server...');
201
- const senderPeerRemote = new SyncPeerWebSocketSender_V1({
202
- classname: 'SyncPeerWebSocketSender_V1',
203
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
204
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
205
- });
206
- const coordinatorRemote = new SyncSagaCoordinator();
207
- await senderPeerRemote.initializeOpts({
208
- localMetaspace: metaspace,
209
- localSpace: remoteSpace,
210
- senderIdentity: domainI_latest,
211
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
212
- sagaId: await getUUID(),
213
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
214
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
215
- targetAddrs: [domainAddr]
216
- });
217
- const syncSagaRemote = await coordinatorRemote.sync({
154
+ await runSyncPassFromSpace({
218
155
  domainIbGibs: [v2b],
219
- senderIdentity: domainI_latest,
220
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
221
- peer: senderPeerRemote,
222
- localSpace: remoteSpace,
156
+ passLabel: 'Push V2b from remoteSpace',
223
157
  metaspace,
224
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
158
+ space: remoteSpace,
159
+ primarySpace: space,
160
+ domainI: debugState.domainI!,
161
+ masterSecret: 'test-sender-secret-phase4-8b'
225
162
  });
226
- await syncSagaRemote.done;
227
- devLog('4.8B Setup: ✓ Server tip is now V2b.');
228
-
229
- // Fetch evolved user identity from remote space (now at n=3)
230
- const domainLatestAddrRemote = await metaspace.getLatestAddr({ ibGib: domainI, space: remoteSpace });
231
- if (!domainLatestAddrRemote) { throw new Error("Could not find latest evolved identity address in remote space."); }
232
- const resGetLatestRemote = await metaspace.get({ addr: domainLatestAddrRemote, space: remoteSpace });
233
- if (!resGetLatestRemote.success || !resGetLatestRemote.ibGibs || resGetLatestRemote.ibGibs.length === 0) {
234
- throw new Error("Could not find latest evolved identity in remote space.");
235
- }
236
- const domainI_latestRemote = resGetLatestRemote.ibGibs[0] as KeystoneIbGib_V1;
237
- await metaspace.put({ ibGib: domainI_latestRemote, space });
238
- await metaspace.registerNewIbGib({ ibGib: domainI_latestRemote, space });
239
- state.domainI_latest = domainI_latestRemote;
240
- devLog(`4.8B Setup: ✓ Copied evolved identity tip (n=3) back to default space: ${domainLatestAddrRemote}`);
163
+ state.domainI_latest = debugState.domainI;
164
+ devLog('4.8B Setup: ✓ Server tip is now V2b. Evolved identity copied back.');
241
165
 
242
166
  devLog('✓ 4.8B Setup Complete! Ready for 4.8B Sync.');
243
167
  btn.textContent = '✓ 4.8B Setup Complete';
@@ -269,44 +193,17 @@ export function init4_8bSyncButton(): void {
269
193
  return;
270
194
  }
271
195
 
272
- const domainAddr = getIbGibAddr({ ibGib: domainI });
273
196
  const metaspace = await getGlobalMetaspace_waitIfNeeded();
274
197
  const space = await metaspace.getLocalUserSpace({}) as any;
275
198
  if (!space) { throw new Error("No default space."); }
276
199
 
277
- const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
278
-
279
- const senderPeer = new SyncPeerWebSocketSender_V1({
280
- classname: 'SyncPeerWebSocketSender_V1',
281
- httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
282
- wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
283
- });
284
-
285
- const coordinator = new SyncSagaCoordinator();
286
- const sagaId = await getUUID();
287
-
288
- await senderPeer.initializeOpts({
289
- localMetaspace: metaspace,
290
- localSpace: space,
291
- senderIdentity: domainI,
292
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
293
- sagaId,
294
- sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
295
- sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
296
- targetAddrs: [domainAddr]
297
- });
298
-
299
- // Run Sync. Client has V3a (with Beta), server has V2b. This will trigger optimistic graft merge!
300
- const syncSaga = await coordinator.sync({
200
+ await runSyncPass({
301
201
  domainIbGibs: [targetAlphaV3a],
302
- senderIdentity: domainI,
303
- fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
304
- peer: senderPeer,
305
- localSpace: space,
202
+ passLabel: 'Sync V3a and merge',
306
203
  metaspace,
307
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
204
+ space
308
205
  });
309
- await syncSaga.done;
206
+ state.domainI_latest = debugState.domainI;
310
207
 
311
208
  devLog('✓ 4.8B Sync Execution Complete! Ready for 4.8B Check.');
312
209
  btn.textContent = '✓ 4.8B Sync Run';