@ibgib/core-gib 0.1.57 → 0.1.58
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/dist/keystone/keystone-config-builder.d.mts +12 -1
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +58 -4
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +40 -5
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +39 -5
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +11 -1
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +37 -1
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-policy-types.d.mts +23 -0
- package/dist/keystone/keystone-policy-types.d.mts.map +1 -0
- package/dist/keystone/keystone-policy-types.mjs +2 -0
- package/dist/keystone/keystone-policy-types.mjs.map +1 -0
- package/dist/sync/graft-info/graft-info-helpers.respec.mjs +8 -8
- package/dist/sync/graft-info/graft-info-helpers.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +22 -22
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-basic-divergence.respec.mjs +3 -3
- package/dist/sync/sync-conflict-basic-divergence.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs +6 -6
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-text-merge.respec.mjs +26 -26
- package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
- package/dist/sync/sync-helpers.d.mts +19 -0
- package/dist/sync/sync-helpers.d.mts.map +1 -1
- package/dist/sync/sync-helpers.mjs +51 -1
- package/dist/sync/sync-helpers.mjs.map +1 -1
- package/dist/sync/sync-innerspace-constants.respec.mjs +2 -2
- package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs +2 -2
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +4 -4
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +2 -2
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-partial-update.respec.mjs +3 -3
- package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace.respec.mjs +4 -4
- package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts +5 -0
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs +18 -0
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts +5 -0
- package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs +21 -3
- package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +12 -0
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +34 -0
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts +69 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts +30 -0
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +88 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts +30 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs +2 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +66 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +280 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +85 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +332 -0
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts +29 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs +2 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts +42 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +282 -0
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -0
- package/dist/sync/sync-saga-coordinator.d.mts +35 -1
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +62 -1
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-withid.connect.respec.d.mts +12 -0
- package/dist/sync/sync-withid.connect.respec.d.mts.map +1 -0
- package/dist/sync/sync-withid.connect.respec.mjs +205 -0
- package/dist/sync/sync-withid.connect.respec.mjs.map +1 -0
- package/dist/sync/sync-withid.establish.respec.d.mts +19 -0
- package/dist/sync/sync-withid.establish.respec.d.mts.map +1 -0
- package/dist/sync/sync-withid.establish.respec.mjs +322 -0
- package/dist/sync/sync-withid.establish.respec.mjs.map +1 -0
- package/package.json +4 -4
- package/src/keystone/keystone-config-builder.mts +73 -4
- package/src/keystone/keystone-constants.mts +42 -6
- package/src/keystone/keystone-helpers.mts +44 -2
- package/src/keystone/keystone-policy-types.mts +25 -0
- package/src/keystone/keystone-policy.schema.json +51 -0
- package/src/keystone/keystone-service-v1.mts +3 -3
- package/src/sync/docs/architecture.md +20 -0
- package/src/sync/docs/security.md +207 -3
- package/src/sync/graft-info/graft-info-helpers.respec.mts +7 -7
- package/src/sync/sync-conflict-adv-multitimelines.respec.mts +21 -21
- package/src/sync/sync-conflict-basic-divergence.respec.mts +2 -2
- package/src/sync/sync-conflict-basic-multitimelines.respec.mts +5 -5
- package/src/sync/sync-conflict-text-merge.respec.mts +25 -25
- package/src/sync/sync-helpers.mts +51 -1
- package/src/sync/sync-innerspace-constants.respec.mts +1 -1
- package/src/sync/sync-innerspace-deep-updates.respec.mts +1 -1
- package/src/sync/sync-innerspace-dest-ahead.respec.mts +3 -3
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
- package/src/sync/sync-innerspace-partial-update.respec.mts +2 -2
- package/src/sync/sync-innerspace.respec.mts +3 -3
- package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mts +20 -0
- package/src/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mts +23 -3
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +38 -1
- package/src/sync/sync-peer/sync-peer-types.mts +70 -1
- package/src/sync/sync-peer/sync-peer-v1.mts +94 -1
- package/src/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mts +36 -0
- package/src/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +337 -0
- package/src/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +388 -0
- package/src/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mts +35 -0
- package/src/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +321 -0
- package/src/sync/sync-saga-coordinator.mts +84 -0
- package/src/sync/sync-withid.connect.respec.mts +243 -0
- package/src/sync/sync-withid.establish.respec.mts +361 -0
- package/src/sync/unused-identity-backup.mts.md +1 -1
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts +0 -2
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts.map +0 -1
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +0 -310
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +0 -1
- package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +0 -364
|
@@ -216,7 +216,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
216
216
|
|
|
217
217
|
// Verify Receiver has correct KV (Pre-Sync Check)
|
|
218
218
|
// This ensures the conflict precondition exists.
|
|
219
|
-
await
|
|
219
|
+
await ifWe(sir, 'verify receiver KV pre-sync', async () => {
|
|
220
220
|
try {
|
|
221
221
|
const destKV = await receiverCoordinator.getKnowledgeMap({
|
|
222
222
|
space: destSpace,
|
|
@@ -316,7 +316,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
316
316
|
const resTip = await getFromSpace({ space: sourceSpace, addr: sourceTipAddr });
|
|
317
317
|
const newTip = resTip.ibGibs![0] as IbGib_V1<TestData>;
|
|
318
318
|
|
|
319
|
-
await
|
|
319
|
+
await ifWe(sir, 'basics of alpha merge', async () => {
|
|
320
320
|
iReckon(sir, sourceTipAddr).asTo(`Source Tip (${sourceTipAddr}) should NOT be alpha_v3_source_rel8beta`).not.isGonnaBe(getIbGibAddr({ ibGib: alpha_v3_source_rel8beta }));
|
|
321
321
|
iReckon(sir, sourceTipAddr).asTo(`Source Tip (${sourceTipAddr}) should NOT be v2dest`).not.isGonnaBe(getIbGibAddr({ ibGib: alpha_v2_dest }));
|
|
322
322
|
|
|
@@ -329,7 +329,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
329
329
|
// Check Graft Structure
|
|
330
330
|
// Look for 'graftinfo' rel8n
|
|
331
331
|
|
|
332
|
-
await
|
|
332
|
+
await ifWe(sir, 'graft info is valid', async () => {
|
|
333
333
|
if (!newTip.rel8ns) { throw new Error(`(UNEXPECTED) newTip.rel8ns falsy? (E: eb4078712ea2f02c7ee84b983ed77826)`); }
|
|
334
334
|
const graftInfoRel = newTip.rel8ns[GRAFT_INFO_REL8N_NAME];
|
|
335
335
|
iReckon(sir, graftInfoRel).asTo('New Tip should have graftinfo rel8n').isGonnaBeTruthy();
|
|
@@ -353,7 +353,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
353
353
|
iReckon(sir, orphanRel![0]).asTo('orphan rel8ns will be later addr').isGonnaBe(orphanAddr);
|
|
354
354
|
});
|
|
355
355
|
|
|
356
|
-
await
|
|
356
|
+
await ifWe(sir, 'alpha and deps synced', async () => {
|
|
357
357
|
// alpha's full dep graph should exist on dest
|
|
358
358
|
const [beta_dest] = await getIbGibsFromCache_fallbackToSpaces({
|
|
359
359
|
addrs: [betaAddr_v0],
|
|
@@ -373,7 +373,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
|
|
|
373
373
|
}
|
|
374
374
|
});
|
|
375
375
|
|
|
376
|
-
await
|
|
376
|
+
await ifWe(sir, 'beta and deps synced', async () => {
|
|
377
377
|
// beta's full dep graph should exist on dest
|
|
378
378
|
const [beta_dest] = await getIbGibsFromCache_fallbackToSpaces({
|
|
379
379
|
addrs: [betaAddr_v0],
|
|
@@ -147,7 +147,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
147
147
|
});
|
|
148
148
|
const r1_alpha_source_tipAddr = r1_alpha_sourceKV[alpha_tjpAddr];
|
|
149
149
|
if (!r1_alpha_source_tipAddr) {
|
|
150
|
-
await
|
|
150
|
+
await ifWe(sir, 'r1_alpha_source_tipAddr is falsy?', async () => {
|
|
151
151
|
iReckon(sir, true).asTo('fail').isGonnaBeFalse();
|
|
152
152
|
});
|
|
153
153
|
return; /* <<<< returns early */
|
|
@@ -160,17 +160,17 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
160
160
|
});
|
|
161
161
|
const r1_alpha_dest_tipAddr = r1_alpha_destKV[alpha_tjpAddr];
|
|
162
162
|
if (!r1_alpha_dest_tipAddr) {
|
|
163
|
-
await
|
|
163
|
+
await ifWe(sir, 'r1_alpha_dest_tipAddr is falsy?', async () => {
|
|
164
164
|
iReckon(sir, true).asTo('fail').isGonnaBeFalse();
|
|
165
165
|
});
|
|
166
166
|
return; /* <<<< returns early */
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
await
|
|
169
|
+
await ifWe(sir, 'r1 tip addrs match', async () => {
|
|
170
170
|
iReckon(sir, r1_alpha_source_tipAddr).asTo('R1 source/dest have same tip').isGonnaBe(r1_alpha_dest_tipAddr);
|
|
171
171
|
});
|
|
172
172
|
|
|
173
|
-
await
|
|
173
|
+
await ifWe(sir, 'r1 text synced correctly', async () => {
|
|
174
174
|
if (!r1_alpha_dest_tipAddr) {
|
|
175
175
|
throw new Error(`r1_dest_tipAddr is null/undefined (E: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d)`);
|
|
176
176
|
}
|
|
@@ -180,7 +180,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
180
180
|
iReckon(sir, destTipIbGib.data!.text).asTo('Dest has initial text').isGonnaBe(INITIAL_TEXT);
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
await
|
|
183
|
+
await ifWe(sir, 'r1 dep graphs synced', async () => {
|
|
184
184
|
const [r1_alpha_source_tip] = await getIbGibsFromCache_fallbackToSpaces({
|
|
185
185
|
addrs: [r1_alpha_source_tipAddr],
|
|
186
186
|
space: sourceSpace,
|
|
@@ -259,7 +259,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
259
259
|
// #endregion r2 dest edits
|
|
260
260
|
|
|
261
261
|
await respecfully(sir, `r2 verify pre`, async () => {
|
|
262
|
-
await
|
|
262
|
+
await ifWe(sir, 'texts as expected', async () => {
|
|
263
263
|
// before the sync, each side only has their edit. after the sync,
|
|
264
264
|
// both sides should have both prepended and appended text
|
|
265
265
|
iReckon(sir, r2_alpha_v1_source_appendedText.ibGib.data?.text.includes(INITIAL_TEXT)).asTo('alpha source has initial text').isGonnaBeTrue();
|
|
@@ -294,14 +294,14 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
294
294
|
const kv_dest = await senderCoordinator.getKnowledgeMap({ space: destSpace, metaspace, domainIbGibs: [r1_alpha_v0_source.ibGib] });
|
|
295
295
|
const r2_alpha_source_tipAddr = kv_source[alpha_tjpAddr];
|
|
296
296
|
if (!r2_alpha_source_tipAddr) {
|
|
297
|
-
await
|
|
297
|
+
await ifWe(sir, 'r2_alpha_source_tipAddr falsy?', async () => {
|
|
298
298
|
iReckon(sir, true).asTo('fails').isGonnaBe(false);
|
|
299
299
|
});
|
|
300
300
|
return; /* <<<< returns early */
|
|
301
301
|
}
|
|
302
302
|
const r2_alpha_dest_tipAddr = kv_dest[alpha_tjpAddr];
|
|
303
303
|
if (!r2_alpha_dest_tipAddr) {
|
|
304
|
-
await
|
|
304
|
+
await ifWe(sir, 'r2_alpha_dest_tipAddr falsy?', async () => {
|
|
305
305
|
iReckon(sir, true).asTo('fails').isGonnaBe(false);
|
|
306
306
|
});
|
|
307
307
|
return; /* <<<< returns early */
|
|
@@ -315,11 +315,11 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
315
315
|
space: sourceSpace,
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
await
|
|
318
|
+
await ifWe(sir, 'r2 tip addrs match', async () => {
|
|
319
319
|
iReckon(sir, r2_alpha_source_tipAddr).asTo('alpha').isGonnaBe(r2_alpha_dest_tipAddr);
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
await
|
|
322
|
+
await ifWe(sir, 'r2 text merged correctly', async () => {
|
|
323
323
|
// before the sync, each side only has their edit. after the sync,
|
|
324
324
|
// both sides should have both prepended and appended text
|
|
325
325
|
iReckon(sir, r2_alpha_v1_source_appendedText.ibGib.data?.text.includes(INITIAL_TEXT)).asTo('alpha source has initial text').isGonnaBeTrue();
|
|
@@ -338,7 +338,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
338
338
|
iReckon(sir, text).asTo('R2 has both prepend and append').isGonnaBe(DEST_PREPEND + INITIAL_TEXT + SOURCE_APPEND);
|
|
339
339
|
});
|
|
340
340
|
|
|
341
|
-
await
|
|
341
|
+
await ifWe(sir, 'r2 dep graphs synced', async () => {
|
|
342
342
|
// alpha's full dep graph should exist on dest
|
|
343
343
|
const depGraph_alpha_source = await getDependencyGraph({
|
|
344
344
|
ibGib: r2_alpha_source_tip,
|
|
@@ -412,7 +412,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
412
412
|
// // #endregion r3 dest edits
|
|
413
413
|
|
|
414
414
|
// await respecfully(sir, `r3 verify pre`, async () => {
|
|
415
|
-
// await
|
|
415
|
+
// await ifWe(sir, 'dest has alpha after R2 graft', async () => {
|
|
416
416
|
// const kv = await receiverCoordinator.getKnowledgeMap({ space: destSpace, metaspace, domainIbGibs: [r3_v0_graft_fromDest] });
|
|
417
417
|
// iReckon(sir, !!kv[alpha_tjpAddr]).asTo('dest has tip').isGonnaBeTrue();
|
|
418
418
|
// });
|
|
@@ -442,11 +442,11 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
442
442
|
// const r3_tip_s = kv_s[alpha_tjpAddr];
|
|
443
443
|
// const r3_tip_d = kv_d[alpha_tjpAddr];
|
|
444
444
|
|
|
445
|
-
// await
|
|
445
|
+
// await ifWe(sir, 'r3 tip addrs match', async () => {
|
|
446
446
|
// iReckon(sir, r3_tip_s).asTo('R3 tips match').isGonnaBe(r3_tip_d);
|
|
447
447
|
// });
|
|
448
448
|
|
|
449
|
-
// await
|
|
449
|
+
// await ifWe(sir, 'r3 both paragraph edits merged', async () => {
|
|
450
450
|
// const res = await getFromSpace({ space: sourceSpace, addr: r3_tip_s! });
|
|
451
451
|
// const tip = res.ibGibs![0] as IbGib_V1<TestData>;
|
|
452
452
|
// const mergedText = tip.data!.text!;
|
|
@@ -465,7 +465,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
465
465
|
// .isGonnaBeTrue();
|
|
466
466
|
// });
|
|
467
467
|
|
|
468
|
-
// await
|
|
468
|
+
// await ifWe(sir, 'r3 dep graphs synced', async () => {
|
|
469
469
|
// const [d] = await getIbGibsFromCache_fallbackToSpaces({ addrs: [r3_tip_s!], space: destSpace });
|
|
470
470
|
// iReckon(sir, d).asTo('exists dest').isGonnaBeTruthy();
|
|
471
471
|
// });
|
|
@@ -499,7 +499,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
499
499
|
// // #endregion r4 dest edits
|
|
500
500
|
|
|
501
501
|
// await respecfully(sir, `r4 verify pre`, async () => {
|
|
502
|
-
// await
|
|
502
|
+
// await ifWe(sir, 'dest has alpha after R3 graft', async () => {
|
|
503
503
|
// // TODO: Verify pre-sync state
|
|
504
504
|
// });
|
|
505
505
|
// });
|
|
@@ -509,16 +509,16 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
509
509
|
// // TODO: Add sync operation
|
|
510
510
|
|
|
511
511
|
// await respecfully(sir, `r4 verify post`, async () => {
|
|
512
|
-
// await
|
|
512
|
+
// await ifWe(sir, 'r4 tip addrs match', async () => {
|
|
513
513
|
// // TODO: Verify tips match
|
|
514
514
|
// });
|
|
515
515
|
|
|
516
|
-
// await
|
|
516
|
+
// await ifWe(sir, 'r4 LCS merged both word changes', async () => {
|
|
517
517
|
// // TODO: Verify text has both source and dest word changes
|
|
518
518
|
// // TODO: Verify LCS algorithm preserved both edits correctly
|
|
519
519
|
// });
|
|
520
520
|
|
|
521
|
-
// await
|
|
521
|
+
// await ifWe(sir, 'r4 dep graphs synced', async () => {
|
|
522
522
|
// // TODO: Verify dep graphs
|
|
523
523
|
// });
|
|
524
524
|
// });
|
|
@@ -553,7 +553,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
553
553
|
// // #endregion r5 dest edits
|
|
554
554
|
|
|
555
555
|
// await respecfully(sir, `r5 verify pre`, async () => {
|
|
556
|
-
// await
|
|
556
|
+
// await ifWe(sir, 'dest has alpha after R4 graft', async () => {
|
|
557
557
|
// // TODO: Verify pre-sync state
|
|
558
558
|
// });
|
|
559
559
|
// });
|
|
@@ -563,24 +563,24 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
563
563
|
// // TODO: Add sync operation
|
|
564
564
|
|
|
565
565
|
// await respecfully(sir, `r5 verify post`, async () => {
|
|
566
|
-
// await
|
|
566
|
+
// await ifWe(sir, 'r5 tip addrs match', async () => {
|
|
567
567
|
// // TODO: Verify tips match
|
|
568
568
|
// });
|
|
569
569
|
|
|
570
|
-
// await
|
|
570
|
+
// await ifWe(sir, 'r5 text field merged', async () => {
|
|
571
571
|
// // TODO: Verify text field has both source and dest changes
|
|
572
572
|
// });
|
|
573
573
|
|
|
574
|
-
// await
|
|
574
|
+
// await ifWe(sir, 'r5 description field merged', async () => {
|
|
575
575
|
// // TODO: Verify description field has both source and dest changes
|
|
576
576
|
// });
|
|
577
577
|
|
|
578
|
-
// await
|
|
578
|
+
// await ifWe(sir, 'r5 both fields independently LCS-merged', async () => {
|
|
579
579
|
// // TODO: Verify each field was merged independently
|
|
580
580
|
// // TODO: Ensure one field's merge didn't affect the other
|
|
581
581
|
// });
|
|
582
582
|
|
|
583
|
-
// await
|
|
583
|
+
// await ifWe(sir, 'r5 dep graphs synced', async () => {
|
|
584
584
|
// // TODO: Verify dep graphs
|
|
585
585
|
// });
|
|
586
586
|
// });
|
|
@@ -20,6 +20,8 @@ import { SyncSagaConflictInfo, SyncSagaMessageCommitData_V1, SyncSagaMessageDelt
|
|
|
20
20
|
import { getIbGibsFromCache_fallbackToSpaces } from "../common/other/ibgib-helper.mjs";
|
|
21
21
|
import { isGraftInfo } from "./graft-info/graft-info-helpers.mjs";
|
|
22
22
|
import { GRAFT_ORPHAN_REL8N_NAME } from "./graft-info/graft-info-constants.mjs";
|
|
23
|
+
import { deriveKey } from "../keystone/kdf/kdf-helpers.mjs";
|
|
24
|
+
import { KdfStrategy } from "../keystone/kdf/kdf-constants.mjs";
|
|
23
25
|
|
|
24
26
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
25
27
|
|
|
@@ -70,7 +72,7 @@ export async function parseSyncIb({
|
|
|
70
72
|
] = parts;
|
|
71
73
|
|
|
72
74
|
if (atom !== SYNC_ATOM) {
|
|
73
|
-
throw new Error(`Atom mismatch. Expected ${SYNC_ATOM}. Got ${atom}
|
|
75
|
+
throw new Error(`Atom mismatch. Expected ${SYNC_ATOM}. Got ${atom}. (E: cc6a48143be7de70bafbfdbbc0776826)`);
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
return { atom, uuid };
|
|
@@ -527,3 +529,51 @@ export async function getAllOrphanedAddresses({
|
|
|
527
529
|
if (logalot) { console.log(`${lc} complete.`); }
|
|
528
530
|
}
|
|
529
531
|
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Derives a saga-specific session secret from the sender's master secret.
|
|
535
|
+
*
|
|
536
|
+
* Uses `KDF(senderSecret, sagaId)` via the `recursive_salt_wrap` strategy so
|
|
537
|
+
* the session secret is:
|
|
538
|
+
* - **Deterministic**: same inputs → same output (needed for the receiver to
|
|
539
|
+
* independently reproduce the session keystone genesis).
|
|
540
|
+
* - **Saga-bound**: different sagaId → completely different sessionSecret →
|
|
541
|
+
* completely different session keystone S.
|
|
542
|
+
* - **One-way**: knowing S cannot recover `senderSecret`.
|
|
543
|
+
*
|
|
544
|
+
* @param senderSecret - The sender's plaintext master secret (never transmitted).
|
|
545
|
+
* @param sagaId - The unique UUID for this sync saga.
|
|
546
|
+
* @returns The derived session secret string.
|
|
547
|
+
*/
|
|
548
|
+
export async function deriveSessionSecret({
|
|
549
|
+
senderSecret,
|
|
550
|
+
sagaId,
|
|
551
|
+
}: {
|
|
552
|
+
senderSecret: string;
|
|
553
|
+
sagaId: string;
|
|
554
|
+
}): Promise<string> {
|
|
555
|
+
const lc = `[${deriveSessionSecret.name}]`;
|
|
556
|
+
try {
|
|
557
|
+
if (logalot) { console.log(`${lc} starting... (I: 0de03f8dcd3e32f1fca244e8f2a8a826)`); }
|
|
558
|
+
|
|
559
|
+
if (!senderSecret) { throw new Error(`(UNEXPECTED) senderSecret falsy? (E: 8ce053fe59825a6678713128953b9d26)`); }
|
|
560
|
+
if (!sagaId) { throw new Error(`(UNEXPECTED) sagaId falsy? (E: 3a17e0c1b2f849de8a42cd15b8ee6826)`); }
|
|
561
|
+
|
|
562
|
+
const sessionSecret = await deriveKey({
|
|
563
|
+
masterSecret: senderSecret,
|
|
564
|
+
kdfOpts: {
|
|
565
|
+
strategy: KdfStrategy.recursive_salt_wrap,
|
|
566
|
+
salt: sagaId,
|
|
567
|
+
rounds: 10000,
|
|
568
|
+
algorithm: 'SHA-256',
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
return sessionSecret;
|
|
573
|
+
} catch (error) {
|
|
574
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
575
|
+
throw error;
|
|
576
|
+
} finally {
|
|
577
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
578
|
+
}
|
|
579
|
+
}
|
|
@@ -25,7 +25,7 @@ const lc = `[sync-innerspace-constants.respec]`;
|
|
|
25
25
|
|
|
26
26
|
await respecfully(sir, `Sync Constants (No TJP)`, async () => {
|
|
27
27
|
|
|
28
|
-
await
|
|
28
|
+
await ifWe(sir, `Verify Constants Sync`, async () => {
|
|
29
29
|
// 1. Setup Spaces
|
|
30
30
|
const metaspace = new Metaspace_Innerspace(undefined);
|
|
31
31
|
await metaspace.initialize({
|
|
@@ -127,7 +127,7 @@ await respecfully(sir, `Sync InnerSpaces (Deep Updates)`, async () => {
|
|
|
127
127
|
// 5. Verify Dest
|
|
128
128
|
console.log(`${lc} Verifying Destination...`);
|
|
129
129
|
|
|
130
|
-
await
|
|
130
|
+
await ifWe(sir, `verify deep timeline present`, async () => {
|
|
131
131
|
// Verify Tip (V2)
|
|
132
132
|
const getV2 = await getFromSpace({ space: destSpace, addr: addrV2 });
|
|
133
133
|
iReckon(sir, getV2.success).asTo('Tip V2 present').isGonnaBeTrue();
|
|
@@ -116,7 +116,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
116
116
|
return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
await
|
|
119
|
+
await ifWe(sir, 'verify setup', async () => {
|
|
120
120
|
// Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
|
|
121
121
|
// Ensure Source does NOT have V2
|
|
122
122
|
iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
|
|
@@ -154,7 +154,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
154
154
|
// 5. Verify Sync (v2 should be in both source and dest now)
|
|
155
155
|
console.log(`${lc} Verifying Sync...`);
|
|
156
156
|
|
|
157
|
-
await
|
|
157
|
+
await ifWe(sir, `verify v2 now also in source`, async () => {
|
|
158
158
|
// Verify Tip (V2)
|
|
159
159
|
|
|
160
160
|
iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
|
|
@@ -166,7 +166,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
166
166
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
-
await
|
|
169
|
+
await ifWe(sir, `dependency graphs the same`, async () => {
|
|
170
170
|
|
|
171
171
|
const sourceDepGraph = await getDependencyGraph({
|
|
172
172
|
ibGibAddr: addrV2,
|
|
@@ -129,7 +129,7 @@ await respecfully(sir, `Sync InnerSpaces (Multiple Timelines)`, async () => {
|
|
|
129
129
|
// 5. Verify Dest
|
|
130
130
|
console.log(`${lc} Verifying Destination...`);
|
|
131
131
|
|
|
132
|
-
await
|
|
132
|
+
await ifWe(sir, `verify timelines present`, async () => {
|
|
133
133
|
// Verify A
|
|
134
134
|
const getA = await getFromSpace({ space: destSpace, addr: addrA });
|
|
135
135
|
iReckon(sir, getA.success).asTo('Timeline A present').isGonnaBeTrue();
|
|
@@ -98,7 +98,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
|
|
|
98
98
|
// Transfer Root & V1 to Dest (Simulate previous sync)
|
|
99
99
|
await putInSpace({ space: destSpace, ibGibs: [root, v1] });
|
|
100
100
|
|
|
101
|
-
await
|
|
101
|
+
await ifWe(sir, 'verify setup', async () => {
|
|
102
102
|
// Verify Dest has V1
|
|
103
103
|
const checkV1 = await getFromSpace({ space: destSpace, addr: getIbGibAddr({ ibGib: v1 }) });
|
|
104
104
|
iReckon(sir, checkV1.success).asTo('Dest has V1').isGonnaBeTrue();
|
|
@@ -136,7 +136,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
|
|
|
136
136
|
// 5. Verify Dest (Should now have V2)
|
|
137
137
|
console.log(`${lc} Verifying Destination...`);
|
|
138
138
|
|
|
139
|
-
await
|
|
139
|
+
await ifWe(sir, `verify dest updated`, async () => {
|
|
140
140
|
// Verify Tip (V2)
|
|
141
141
|
const getV2 = await getFromSpace({ space: destSpace, addr: addrV2 });
|
|
142
142
|
iReckon(sir, getV2.success).asTo('V2 present in Dest').isGonnaBeTrue();
|
|
@@ -152,18 +152,18 @@ await respecfully(sir, `Sync InnerSpaces`, async () => {
|
|
|
152
152
|
try {
|
|
153
153
|
const getChildInDest = await getFromSpace({ space: destSpace, addr: childAddr });
|
|
154
154
|
|
|
155
|
-
await
|
|
155
|
+
await ifWe(sir, `verify success getChildInDest`, async () => {
|
|
156
156
|
iReckon(sir, getChildInDest.success).asTo('Child present in Dest').isGonnaBeTrue();
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
await
|
|
159
|
+
await ifWe(sir, `verify getChildInDest.ibGibs`, async () => {
|
|
160
160
|
const firstChild = getChildInDest.ibGibs?.[0];
|
|
161
161
|
if (logalot) { console.log(`${lc} firstChild: ${pretty(firstChild)}`); }
|
|
162
162
|
iReckon(sir, firstChild?.data?.n).asTo('Child content matches').isGonnaBe(2);
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
} catch (error) {
|
|
166
|
-
await
|
|
166
|
+
await ifWe(sir, `doh`, async () => {
|
|
167
167
|
// hack here I'm getting tired...
|
|
168
168
|
iReckon(sir, true).asTo(`error: ${extractErrorMsg(error)}`).isGonnaBeFalse();
|
|
169
169
|
});
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
ConnectSyncPeerHttpReceiverOpts
|
|
19
19
|
} from './sync-peer-http-receiver-types.mjs';
|
|
20
20
|
import { putInSpace, registerNewIbGib } from '../../../witness/space/space-helper.mjs';
|
|
21
|
+
import { KeystoneIbGib_V1 } from '../../../keystone/keystone-types.mjs';
|
|
21
22
|
|
|
22
23
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
23
24
|
|
|
@@ -72,6 +73,25 @@ export class SyncPeerHttpReceiver_V1
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
protected override async postEstablishToReceiver({
|
|
77
|
+
newSenderIdentity,
|
|
78
|
+
sessionIdentity,
|
|
79
|
+
}: {
|
|
80
|
+
newSenderIdentity: KeystoneIbGib_V1;
|
|
81
|
+
sessionIdentity: KeystoneIbGib_V1;
|
|
82
|
+
}): Promise<void> {
|
|
83
|
+
const lc = `${this.lc}[${this.postEstablishToReceiver.name}]`;
|
|
84
|
+
try {
|
|
85
|
+
if (logalot) { console.log(`${lc} starting... (I: f8d7c6b5a4e3d2c1b0a9f8e7d6c5b4a3)`); }
|
|
86
|
+
throw new Error(`not implemented for HTTP receiver peer yet (E: a1b2c3d4e5f67890abcdef1234567890)`);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
89
|
+
throw error;
|
|
90
|
+
} finally {
|
|
91
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
75
95
|
protected async ensureLocalTempSpace(): Promise<IbGibSpaceAny> {
|
|
76
96
|
const lc = `${this.lc}[${this.ensureLocalTempSpace.name}]`;
|
|
77
97
|
try {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
SyncPeerHttpSenderIbGib_V1,
|
|
15
15
|
ConnectSyncPeerHttpSenderOpts
|
|
16
16
|
} from './sync-peer-http-sender-types.mjs';
|
|
17
|
+
import { KeystoneIbGib_V1 } from '../../../keystone/keystone-types.mjs';
|
|
17
18
|
|
|
18
19
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
19
20
|
|
|
@@ -75,13 +76,32 @@ export class SyncPeerHttpSender_V1
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
protected override async postEstablishToReceiver({
|
|
80
|
+
newSenderIdentity,
|
|
81
|
+
sessionIdentity,
|
|
82
|
+
}: {
|
|
83
|
+
newSenderIdentity: KeystoneIbGib_V1;
|
|
84
|
+
sessionIdentity: KeystoneIbGib_V1;
|
|
85
|
+
}): Promise<void> {
|
|
86
|
+
const lc = `${this.lc}[${this.postEstablishToReceiver.name}]`;
|
|
87
|
+
try {
|
|
88
|
+
if (logalot) { console.log(`${lc} starting... (I: a3b2c1d0e9f8e7d6c5b4a3f2e1d0c9b8)`); }
|
|
89
|
+
throw new Error(`not implemented for HTTP sender peer yet (E: b1c2d3e4f5a67890abcdef1234567890)`);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
92
|
+
throw error;
|
|
93
|
+
} finally {
|
|
94
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
78
98
|
protected override async sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined> {
|
|
79
99
|
const lc = `${this.lc}[${this.sendContextRequest.name}]`;
|
|
80
100
|
try {
|
|
81
101
|
if (logalot) { console.log(`${lc} starting...`); }
|
|
82
102
|
|
|
83
|
-
if (!this.data?.syncEventsRoute) { throw new Error(`data.syncEventsRoute required
|
|
84
|
-
if (!this.data?.syncRoute) { throw new Error(`data.syncRoute required
|
|
103
|
+
if (!this.data?.syncEventsRoute) { throw new Error(`data.syncEventsRoute required. (E: 0338214dcd6fbe80f93a24e8a3df3226)`); }
|
|
104
|
+
if (!this.data?.syncRoute) { throw new Error(`data.syncRoute required. (E: eda70809feb81c880c6accf83fc38826)`); }
|
|
85
105
|
|
|
86
106
|
// 1. Establish SSE connection to `this.data.syncEventsRoute` if not already open
|
|
87
107
|
// (In a real implementation, you might initialize this elsewhere or ensure it stays reconnecting)
|
|
@@ -136,7 +156,7 @@ export class SyncPeerHttpSender_V1
|
|
|
136
156
|
});
|
|
137
157
|
|
|
138
158
|
if (!response.ok) {
|
|
139
|
-
throw new Error(`HTTP Sync Error: ${response.status} ${await response.text()}`);
|
|
159
|
+
throw new Error(`HTTP Sync Error: ${response.status} ${await response.text()} (E: f086e8ae65780182b894f638933ca826)`);
|
|
140
160
|
}
|
|
141
161
|
|
|
142
162
|
// 5. Wait for the SSE stream response to resolve with the responseContext
|
|
@@ -19,7 +19,7 @@ import { ConnectSyncPeerOpts, InitializeSyncPeerOpts } from '../sync-peer-types.
|
|
|
19
19
|
import { getSyncSagaFrameDependencyGraph, putInSpace_dnasThenNonDnas } from '../../sync-helpers.mjs';
|
|
20
20
|
import { getDependencyGraph } from '../../../common/other/graph-helper.mjs';
|
|
21
21
|
import { SyncStage } from '../../sync-constants.mjs';
|
|
22
|
-
import { toDto } from '../../../common/other/ibgib-helper.mjs';
|
|
22
|
+
import { toDto } from '../../../common/other/ibgib-helper.mjs';import { KeystoneIbGib_V1 } from '../../../keystone/keystone-types.mjs';
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
@@ -114,6 +114,43 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Innerspace implementation of the establish receiver post.
|
|
119
|
+
*
|
|
120
|
+
* Simulates the domain provider registration by putting `newSenderIdentity`
|
|
121
|
+
* (I1) and `sessionIdentity` (S) directly into `receiverMetaspace` /
|
|
122
|
+
* `receiverSpace`. In a real WebSocket peer this would be an HTTP POST.
|
|
123
|
+
*/
|
|
124
|
+
protected override async postEstablishToReceiver({
|
|
125
|
+
newSenderIdentity,
|
|
126
|
+
sessionIdentity,
|
|
127
|
+
}: {
|
|
128
|
+
newSenderIdentity: KeystoneIbGib_V1;
|
|
129
|
+
sessionIdentity: KeystoneIbGib_V1;
|
|
130
|
+
}): Promise<void> {
|
|
131
|
+
const lc = `${this.lc}[${this.postEstablishToReceiver.name}]`;
|
|
132
|
+
try {
|
|
133
|
+
if (logalot) { console.log(`${lc} starting... (I: a7b8c9d0e1f2a3b4c5d6e7f8a9b0c126)`); }
|
|
134
|
+
|
|
135
|
+
if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: b8c9d0e1f2a3b4c5d6e7f8a9b0c1d226)`); }
|
|
136
|
+
const { receiverMetaspace, receiverSpace } = this.opts;
|
|
137
|
+
|
|
138
|
+
// Post newSenderIdentity (I1) to receiver
|
|
139
|
+
await receiverMetaspace.put({ ibGib: newSenderIdentity, space: receiverSpace });
|
|
140
|
+
await receiverMetaspace.registerNewIbGib({ ibGib: newSenderIdentity, space: receiverSpace });
|
|
141
|
+
|
|
142
|
+
// Post sessionIdentity (S) to receiver
|
|
143
|
+
await receiverMetaspace.put({ ibGib: sessionIdentity, space: receiverSpace });
|
|
144
|
+
await receiverMetaspace.registerNewIbGib({ ibGib: sessionIdentity, space: receiverSpace });
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
148
|
+
throw error;
|
|
149
|
+
} finally {
|
|
150
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
117
154
|
protected async ensureReceiverTempSpace(): Promise<IbGibSpaceAny> {
|
|
118
155
|
const lc = `${this.lc}[${this.ensureReceiverTempSpace.name}]`;
|
|
119
156
|
try {
|
|
@@ -9,6 +9,7 @@ import { SyncSagaContextData_V1, SyncSagaContextIbGib_V1, SyncSagaContextRel8ns_
|
|
|
9
9
|
import { Witness_V1 } from '../../witness/witness-types.mjs';
|
|
10
10
|
import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
|
|
11
11
|
import { MetaspaceService } from '../../witness/space/metaspace/metaspace-types.mjs';
|
|
12
|
+
import { KeystoneIbGib_V1, KeystonePoolConfig } from '../../keystone/keystone-types.mjs';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Data for the SyncPeer witness.
|
|
@@ -36,13 +37,29 @@ export interface SyncPeerIbGib_V1 extends IbGib_V1<SyncPeerData_V1, SyncPeerRel8
|
|
|
36
37
|
* opts used in `connect(opts)`
|
|
37
38
|
*/
|
|
38
39
|
export interface ConnectSyncPeerOpts {
|
|
40
|
+
/**
|
|
41
|
+
* TODO: sagaId is now also on {@link InitializeSyncPeerOpts} since a peer
|
|
42
|
+
* is scoped to a single sync saga. Evaluate whether this duplicate is still
|
|
43
|
+
* needed when implementing the connect phase (Phase 2).
|
|
44
|
+
*/
|
|
39
45
|
sagaId: string;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
/**
|
|
43
|
-
* base initialization opts
|
|
49
|
+
* base initialization opts.
|
|
50
|
+
*
|
|
51
|
+
* A sync peer is scoped to exactly one sync saga. A new peer instance must be
|
|
52
|
+
* created for each `sync(...)` call. Reusing a peer across multiple sagas is
|
|
53
|
+
* not supported and would compromise the identity security model.
|
|
44
54
|
*/
|
|
45
55
|
export interface InitializeSyncPeerOpts {
|
|
56
|
+
/**
|
|
57
|
+
* Unique id for the sync saga this peer is servicing.
|
|
58
|
+
* Generated by `SyncSagaCoordinator.sync()` and passed here so that
|
|
59
|
+
* `establishSessionIdentity` can derive the session secret via
|
|
60
|
+
* `KDF(senderSecret, sagaId)`.
|
|
61
|
+
*/
|
|
62
|
+
sagaId?: string;
|
|
46
63
|
/**
|
|
47
64
|
* reference to the local metaspace
|
|
48
65
|
*/
|
|
@@ -62,6 +79,44 @@ export interface InitializeSyncPeerOpts {
|
|
|
62
79
|
* received/created throughout the transaction until commit.
|
|
63
80
|
*/
|
|
64
81
|
localTempSpace?: IbGibSpaceAny;
|
|
82
|
+
/**
|
|
83
|
+
* The sender's long-lived Domain Keystone (I) — Alice's identity.
|
|
84
|
+
* Optional; if omitted the sync runs without identity (anonymous).
|
|
85
|
+
* Must be the current tip frame of I's timeline.
|
|
86
|
+
*
|
|
87
|
+
* Both {@link senderIdentity} and {@link fnSenderSecret} must be provided
|
|
88
|
+
* together or omitted together.
|
|
89
|
+
*/
|
|
90
|
+
senderIdentity?: KeystoneIbGib_V1;
|
|
91
|
+
/**
|
|
92
|
+
* Returns the plaintext secret corresponding to {@link senderIdentity}.
|
|
93
|
+
* Wrapped in a function to avoid holding the secret in memory longer than needed.
|
|
94
|
+
*
|
|
95
|
+
* Both {@link senderIdentity} and {@link fnSenderSecret} must be provided
|
|
96
|
+
* together or omitted together.
|
|
97
|
+
*/
|
|
98
|
+
fnSenderSecret?: () => Promise<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Pool config for the session keystone's transport connect handshake pool.
|
|
101
|
+
* Required when {@link senderIdentity} is provided.
|
|
102
|
+
*
|
|
103
|
+
* @see {@link POOL_ID_CONNECT}
|
|
104
|
+
*/
|
|
105
|
+
sessionConnectPoolConfig?: KeystonePoolConfig;
|
|
106
|
+
/**
|
|
107
|
+
* Pool config for the session keystone's per-turn signing pool (`sync`).
|
|
108
|
+
* Required when {@link senderIdentity} is provided.
|
|
109
|
+
*
|
|
110
|
+
* @see {@link POOL_ID_SYNC}
|
|
111
|
+
*/
|
|
112
|
+
sessionSyncPoolConfig?: KeystonePoolConfig;
|
|
113
|
+
/**
|
|
114
|
+
* Addresses of the synced domains (ibgibs).
|
|
115
|
+
* Used during `establishSessionIdentity` to bind the session keystone (S)
|
|
116
|
+
* strictly to these domains, preventing S from acting as a "blank check"
|
|
117
|
+
* for unauthorized domains.
|
|
118
|
+
*/
|
|
119
|
+
targetAddrs?: string[];
|
|
65
120
|
}
|
|
66
121
|
|
|
67
122
|
/**
|
|
@@ -107,6 +162,20 @@ export interface SyncPeerWitness<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
107
162
|
*/
|
|
108
163
|
payloadIbGibsDomainReceived$: SubjectWitness<IbGib_V1>;
|
|
109
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Pre-connect phase: creates the session keystone (S) locally, evolves
|
|
167
|
+
* `senderIdentity` (I → I1) with a `sync` claim targeting S, and posts
|
|
168
|
+
* both to the receiver's domain registry.
|
|
169
|
+
*
|
|
170
|
+
* Must be called before `connect()`. No-op if `senderIdentity` was not
|
|
171
|
+
* provided in {@link InitializeSyncPeerOpts}.
|
|
172
|
+
*
|
|
173
|
+
* @returns The session keystone genesis (S^Stjp). The coordinator holds
|
|
174
|
+
* this reference for the remainder of the saga. The name `newSenderIdentity`
|
|
175
|
+
* (I1) is intentionally scoped only within this method to avoid confusion.
|
|
176
|
+
*/
|
|
177
|
+
establishSessionIdentity(): Promise<KeystoneIbGib_V1 | undefined>;
|
|
178
|
+
|
|
110
179
|
/**
|
|
111
180
|
* Establishes the connection context.
|
|
112
181
|
*
|