@ibgib/core-gib 0.1.59 → 0.1.61
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/CHANGELOG.md +12 -1
- package/dist/common/other/graph-helper.d.mts.map +1 -1
- package/dist/common/other/graph-helper.mjs +7 -6
- package/dist/common/other/graph-helper.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.d.mts +1 -2
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +4 -19
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +2 -0
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +2 -0
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +5 -15
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +59 -73
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-policy-types.d.mts +6 -4
- package/dist/keystone/keystone-policy-types.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +4 -8
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +182 -33
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +4 -11
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/policy/keystone-profile-builder.d.mts +25 -0
- package/dist/keystone/policy/keystone-profile-builder.d.mts.map +1 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs +117 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs.map +1 -0
- package/dist/keystone/policy/profiles/profile-high.json +84 -0
- package/dist/keystone/policy/profiles/profile-low.json +84 -0
- package/dist/keystone/policy/profiles/profile-medium.json +84 -0
- package/dist/keystone/policy/profiles/profile-session.json +84 -0
- package/dist/keystone/policy/profiles/profile-test.json +84 -0
- package/dist/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/dist/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs +582 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs +274 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs +322 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs +307 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs +225 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs +235 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs +211 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs +260 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +1 -1
- 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 +12 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts +7 -0
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +43 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +2 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +28 -9
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +5 -3
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts +16 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +223 -79
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +41 -2
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +4 -0
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +6 -0
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +213 -137
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-withid.pingpong.respec.mjs +70 -2
- package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -1
- package/dist/timeline/timeline-api.d.mts.map +1 -1
- package/dist/timeline/timeline-api.mjs +1 -14
- package/dist/timeline/timeline-api.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs +0 -40
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs +6 -6
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs.map +1 -1
- package/ibgib-foundations.md +2 -1
- package/package.json +1 -1
- package/src/common/other/graph-helper.mts +7 -6
- package/src/keystone/README.md +19 -15
- package/src/keystone/docs/CRYPTANALYSIS.md +185 -0
- package/src/keystone/docs/architecture.md +24 -1
- package/src/keystone/docs/profiles.md +124 -0
- package/src/keystone/keystone-config-builder.mts +3 -21
- package/src/keystone/keystone-constants.mts +2 -0
- package/src/keystone/keystone-helpers.mts +74 -77
- package/src/keystone/keystone-policy-types.mts +6 -4
- package/src/keystone/keystone-service-v1.mts +4 -9
- package/src/keystone/keystone-service-v1.respec.mts +214 -32
- package/src/keystone/keystone-types.mts +5 -9
- package/src/keystone/policy/IMPLEMENTATION.md +60 -0
- package/src/keystone/policy/README.md +94 -0
- package/src/keystone/policy/keystone-profile-builder.mts +131 -0
- package/src/keystone/policy/profiles/profile-high.json +84 -0
- package/src/keystone/policy/profiles/profile-low.json +84 -0
- package/src/keystone/policy/profiles/profile-medium.json +84 -0
- package/src/keystone/policy/profiles/profile-session.json +84 -0
- package/src/keystone/policy/profiles/profile-test.json +84 -0
- package/src/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/src/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/src/sync/docs/security-3b.md +92 -0
- package/src/sync/docs/security.md +139 -38
- package/src/sync/sync-conflict-adv-multitimelines.withid.respec.mts +706 -0
- package/src/sync/sync-conflict-basic-divergence.withid.respec.mts +321 -0
- package/src/sync/sync-conflict-basic-multitimelines.withid.respec.mts +374 -0
- package/src/sync/sync-conflict-text-merge.withid.respec.mts +347 -0
- package/src/sync/sync-innerspace-constants.withid.respec.mts +264 -0
- package/src/sync/sync-innerspace-deep-updates.withid.respec.mts +272 -0
- package/src/sync/sync-innerspace-dest-ahead.withid.respec.mts +266 -0
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +0 -1
- package/src/sync/sync-innerspace-multiple-timelines.withid.respec.mts +273 -0
- package/src/sync/sync-innerspace-partial-update.withid.respec.mts +249 -0
- package/src/sync/sync-innerspace.withid.respec.mts +265 -0
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +1 -1
- package/src/sync/sync-peer/sync-peer-types.mts +11 -1
- package/src/sync/sync-peer/sync-peer-v1.mts +47 -1
- package/src/sync/sync-peer/sync-peer-websocket/README.md +42 -0
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +26 -9
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +5 -3
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +242 -78
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +46 -4
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +5 -0
- package/src/sync/sync-saga-coordinator.mts +221 -137
- package/src/sync/sync-withid.pingpong.respec.mts +76 -3
- package/src/timeline/timeline-api.mts +1 -15
- package/src/timeline/timeline-api.respec.mts +3 -3
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts +0 -46
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts +6 -5
- package/tsconfig.json +6 -1
- package/src/keystone/keystone-policy.schema.json +0 -51
- package/src/sync/docs/ping_pong_plan.md +0 -147
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts.OLD.md +0 -884
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts.OLD.md +0 -125
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sync-innerspace.withid.respec
|
|
3
|
+
*
|
|
4
|
+
* Verifies SyncSagaCoordinator using InnerSpace (in-memory/local) spaces with Identity.
|
|
5
|
+
* This utilizes SyncPeerInnerspace_V1 for local-to-local synchronization simulations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
respecfully, lastOfAll, ifWe, iReckon,
|
|
10
|
+
ifWeMight
|
|
11
|
+
} from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
12
|
+
const maam = `[${import.meta.url}]`, sir = maam;
|
|
13
|
+
import { clone, delay, extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
14
|
+
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
15
|
+
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
16
|
+
|
|
17
|
+
import { GLOBAL_LOG_A_LOT } from '../core-constants.mjs';
|
|
18
|
+
import { SyncSagaCoordinator } from './sync-saga-coordinator.mjs';
|
|
19
|
+
import { getFromSpace } from '../witness/space/space-helper.mjs';
|
|
20
|
+
import { Metaspace_Innerspace } from '../witness/space/metaspace/metaspace-innerspace/metaspace-innerspace.mjs';
|
|
21
|
+
import { getDependencyGraph } from '../common/other/graph-helper.mjs';
|
|
22
|
+
import { InnerSpace_V1 } from '../witness/space/inner-space/inner-space-v1.mjs';
|
|
23
|
+
import { createTimelineRootTestHelper, } from '../test-helpers.mjs';
|
|
24
|
+
import { mut8Timeline, } from '../timeline/timeline-api.mjs';
|
|
25
|
+
import { DEFAULT_INNER_SPACE_DATA_V1 } from '../witness/space/inner-space/inner-space-types.mjs';
|
|
26
|
+
import { toDto } from '../common/other/ibgib-helper.mjs';
|
|
27
|
+
import { fnObs } from '../common/pubsub/observer/observer-helper.mjs';
|
|
28
|
+
import { SyncPeerInnerspace_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
|
|
29
|
+
import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
|
|
30
|
+
|
|
31
|
+
import { KeystoneService_V1 } from '../keystone/keystone-service-v1.mjs';
|
|
32
|
+
import {
|
|
33
|
+
KEYSTONE_VERB_SYNC, POOL_ID_SYNC,
|
|
34
|
+
} from '../keystone/keystone-constants.mjs';
|
|
35
|
+
import { createStandardPoolConfig } from '../keystone/keystone-config-builder.mjs';
|
|
36
|
+
import { KeystoneReplenishStrategy } from '../keystone/keystone-types.mjs';
|
|
37
|
+
import { SyncConflictStrategy } from './sync-constants.mjs';
|
|
38
|
+
|
|
39
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
40
|
+
const lc = `[sync-innerspace.withid.respec]`;
|
|
41
|
+
|
|
42
|
+
const SENDER_SECRET = 'test-sender-secret-innerspace-withid';
|
|
43
|
+
|
|
44
|
+
const SENDER_IDENTITY_SYNC_POOL_CONFIG = createStandardPoolConfig({
|
|
45
|
+
id: POOL_ID_SYNC,
|
|
46
|
+
salt: 'senderidentitysyncsaltinnerspacewithid',
|
|
47
|
+
verbs: [KEYSTONE_VERB_SYNC],
|
|
48
|
+
size: 200,
|
|
49
|
+
sequential: 1,
|
|
50
|
+
random: 1,
|
|
51
|
+
targetBinding: 2,
|
|
52
|
+
replenishStrategy: KeystoneReplenishStrategy.topUp,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await respecfully(sir, `Sync InnerSpaces with Identity`, async () => {
|
|
56
|
+
|
|
57
|
+
let metaspace: Metaspace_Innerspace;
|
|
58
|
+
let sourceSpace: InnerSpace_V1;
|
|
59
|
+
let destSpace: InnerSpace_V1;
|
|
60
|
+
|
|
61
|
+
// #region Round 1 - Push timeline
|
|
62
|
+
await respecfully(sir, `Basic Push Sync with Identity (Source -> Dest)`, async () => {
|
|
63
|
+
// 1. Setup Spaces
|
|
64
|
+
metaspace = new Metaspace_Innerspace(undefined);
|
|
65
|
+
await metaspace.initialize({
|
|
66
|
+
getFnAlert: () => async ({ title, msg }) => { console.log(`[Alert] ${title}: ${msg}`); },
|
|
67
|
+
getFnPrompt: () => async ({ title, msg }) => { console.log(`[Prompt] ${title}: ${msg}`); return ''; },
|
|
68
|
+
getFnPromptPassword: () => async (title, msg) => { console.log(`[PromptPwd] ${title}: ${msg}`); return null; },
|
|
69
|
+
});
|
|
70
|
+
while (!metaspace.initialized) { await delay(10); }
|
|
71
|
+
|
|
72
|
+
const defaultLocalUserSpace = await metaspace.getLocalUserSpace({ lock: false });
|
|
73
|
+
if (!defaultLocalUserSpace) { throw new Error(`(UNEXPECTED) defaultLocalUserSpace falsy? (E: 87da738ca09e8fcabde916298126)`); }
|
|
74
|
+
await defaultLocalUserSpace.initialized;
|
|
75
|
+
if (logalot) { console.log(`defaultLocalUserSpace: ${pretty(toDto({ ibGib: defaultLocalUserSpace }))}`); }
|
|
76
|
+
|
|
77
|
+
sourceSpace = new InnerSpace_V1({
|
|
78
|
+
...DEFAULT_INNER_SPACE_DATA_V1,
|
|
79
|
+
name: 'source',
|
|
80
|
+
uuid: 'source_uuid',
|
|
81
|
+
description: 'source test space',
|
|
82
|
+
});
|
|
83
|
+
await sourceSpace.initialized;
|
|
84
|
+
if (logalot) { console.log(`sourceSpace: ${pretty(toDto({ ibGib: sourceSpace }))}`); }
|
|
85
|
+
|
|
86
|
+
destSpace = new InnerSpace_V1({
|
|
87
|
+
...DEFAULT_INNER_SPACE_DATA_V1,
|
|
88
|
+
name: 'dest',
|
|
89
|
+
uuid: 'dest_uuid',
|
|
90
|
+
description: 'dest test space',
|
|
91
|
+
});
|
|
92
|
+
await destSpace.initialized;
|
|
93
|
+
if (logalot) { console.log(`destSpace: ${pretty(toDto({ ibGib: destSpace }))}`); }
|
|
94
|
+
|
|
95
|
+
const keystoneSvc = new KeystoneService_V1();
|
|
96
|
+
const senderIdentity = await keystoneSvc.genesis({
|
|
97
|
+
masterSecret: SENDER_SECRET,
|
|
98
|
+
configs: [SENDER_IDENTITY_SYNC_POOL_CONFIG],
|
|
99
|
+
metaspace,
|
|
100
|
+
space: sourceSpace,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// post the senderIdentity to receiver
|
|
104
|
+
await metaspace.put({ ibGib: senderIdentity, space: destSpace });
|
|
105
|
+
await metaspace.registerNewIbGib({ ibGib: senderIdentity, space: destSpace });
|
|
106
|
+
|
|
107
|
+
// #region r1 setup
|
|
108
|
+
// 2. Seed Source Data
|
|
109
|
+
if (logalot) { console.log(`${lc} Creating data in Source...`); }
|
|
110
|
+
const r1_alpha_v0_source = await createTimelineRootTestHelper({
|
|
111
|
+
ib: 'timeline_root',
|
|
112
|
+
data: { type: 'root', },
|
|
113
|
+
space: sourceSpace,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const r1_alpha_v1_source = await mut8Timeline({
|
|
117
|
+
timeline: r1_alpha_v0_source,
|
|
118
|
+
mut8Opts: {
|
|
119
|
+
dataToAddOrPatch: { type: 'child', },
|
|
120
|
+
},
|
|
121
|
+
metaspace,
|
|
122
|
+
space: sourceSpace,
|
|
123
|
+
});
|
|
124
|
+
const r1_alpha_v1_source_addr = getIbGibAddr({ ibGib: r1_alpha_v1_source });
|
|
125
|
+
// #endregion r1 setup
|
|
126
|
+
|
|
127
|
+
// 3. Setup Coordinators & Peer
|
|
128
|
+
if (logalot) { console.log(`${lc} Setting up Coordinators...`); }
|
|
129
|
+
|
|
130
|
+
// Sender Coordinator
|
|
131
|
+
const senderCoordinator = new SyncSagaCoordinator();
|
|
132
|
+
|
|
133
|
+
// Receiver Coordinator
|
|
134
|
+
const receiverCoordinator = new SyncSagaCoordinator();
|
|
135
|
+
|
|
136
|
+
// Peer (The "Network")
|
|
137
|
+
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
138
|
+
await peer.initialized;
|
|
139
|
+
await peer.initializeOpts({
|
|
140
|
+
sagaId: '',
|
|
141
|
+
localMetaspace: metaspace,
|
|
142
|
+
localSpace: sourceSpace, // "Client"
|
|
143
|
+
receiverSpace: destSpace, // "Server"
|
|
144
|
+
receiverCoordinator,
|
|
145
|
+
receiverMetaspace: metaspace,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// 4. Run Sync
|
|
149
|
+
if (logalot) { console.log(`${lc} Running Sync...`); }
|
|
150
|
+
const resSync = await senderCoordinator.sync({
|
|
151
|
+
peer: peer,
|
|
152
|
+
localSpace: sourceSpace,
|
|
153
|
+
metaspace: metaspace,
|
|
154
|
+
domainIbGibs: [r1_alpha_v1_source], // Sync the child
|
|
155
|
+
senderIdentity,
|
|
156
|
+
fnSenderSecret: async () => SENDER_SECRET,
|
|
157
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
if (logalot) { console.log(`${lc} resSync: ${pretty(resSync)}`); }
|
|
161
|
+
|
|
162
|
+
const sublc = `${lc}[updates$]`;
|
|
163
|
+
const subscription = await resSync.updates$.subscribe(fnObs({
|
|
164
|
+
next: async (ctxIbGib) => {
|
|
165
|
+
if (logalot) { console.log(`${sublc} next fired`); }
|
|
166
|
+
},
|
|
167
|
+
error: async (e) => {
|
|
168
|
+
if (logalot) { console.log(`${sublc} error fired`); }
|
|
169
|
+
},
|
|
170
|
+
complete: async () => {
|
|
171
|
+
if (logalot) { console.log(`${sublc} complete fired`); }
|
|
172
|
+
},
|
|
173
|
+
}));
|
|
174
|
+
|
|
175
|
+
if (logalot) { console.log(`${lc} awaiting resSync.done`) }
|
|
176
|
+
await resSync.done;
|
|
177
|
+
|
|
178
|
+
// #region r1 verify post
|
|
179
|
+
// 5. Verify Dest
|
|
180
|
+
if (logalot) { console.log(`${lc} Verifying Destination...`); }
|
|
181
|
+
try {
|
|
182
|
+
const getChildInDest = await getFromSpace({ space: destSpace, addr: r1_alpha_v1_source_addr });
|
|
183
|
+
|
|
184
|
+
await ifWe(sir, `verify success getChildInDest`, async () => {
|
|
185
|
+
iReckon(sir, getChildInDest.success).asTo('Child present in Dest').isGonnaBeTrue();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await ifWe(sir, `verify getChildInDest.ibGibs`, async () => {
|
|
189
|
+
const firstChild = getChildInDest.ibGibs?.[0];
|
|
190
|
+
if (logalot) { console.log(`${lc} firstChild: ${pretty(firstChild)}`); }
|
|
191
|
+
iReckon(sir, firstChild?.data?.n).asTo('Child content matches').isGonnaBe(2);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
await ifWe(sir, 'sessionIdentity evolved the expected number of times', async () => {
|
|
195
|
+
const latestS = peer.currentSessionIdentity;
|
|
196
|
+
iReckon(sir, latestS).asTo('latest session identity exists on peer').isGonnaBeTruthy();
|
|
197
|
+
if (latestS) {
|
|
198
|
+
iReckon(sir, latestS.data?.n).asTo('session identity data.n').isGonnaBe(2);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await ifWe(sir, 'sender durable space has I (evolved frame)', async () => {
|
|
203
|
+
const latestSenderIdentityAddr = await metaspace.getLatestAddr({
|
|
204
|
+
addr: getIbGibAddr({ ibGib: senderIdentity }),
|
|
205
|
+
space: sourceSpace,
|
|
206
|
+
});
|
|
207
|
+
iReckon(sir, latestSenderIdentityAddr).asTo('latestSenderIdentityAddr exists').isGonnaBeTruthy();
|
|
208
|
+
if (latestSenderIdentityAddr) {
|
|
209
|
+
const resGetSourceI = await getFromSpace({ space: sourceSpace, addr: latestSenderIdentityAddr });
|
|
210
|
+
iReckon(sir, resGetSourceI.success && resGetSourceI.ibGibs?.length === 1).asTo('evolved I exists in sourceSpace').isGonnaBeTrue();
|
|
211
|
+
if (resGetSourceI.success && resGetSourceI.ibGibs?.[0]) {
|
|
212
|
+
const evolvedI = resGetSourceI.ibGibs[0];
|
|
213
|
+
iReckon(sir, evolvedI.data?.n).asTo('evolved I data.n').isGonnaBe(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await ifWe(sir, 'receiver durable space has I (evolved frame)', async () => {
|
|
219
|
+
const latestSenderIdentityAddr = await metaspace.getLatestAddr({
|
|
220
|
+
addr: getIbGibAddr({ ibGib: senderIdentity }),
|
|
221
|
+
space: sourceSpace,
|
|
222
|
+
});
|
|
223
|
+
iReckon(sir, latestSenderIdentityAddr).asTo('latestSenderIdentityAddr exists').isGonnaBeTruthy();
|
|
224
|
+
if (latestSenderIdentityAddr) {
|
|
225
|
+
const resGetDestI = await getFromSpace({ space: destSpace, addr: latestSenderIdentityAddr });
|
|
226
|
+
iReckon(sir, resGetDestI.success && resGetDestI.ibGibs?.length === 1).asTo('evolved I exists in destSpace').isGonnaBeTrue();
|
|
227
|
+
if (resGetDestI.success && resGetDestI.ibGibs?.[0]) {
|
|
228
|
+
const evolvedI = resGetDestI.ibGibs[0];
|
|
229
|
+
iReckon(sir, evolvedI.data?.n).asTo('evolved I data.n').isGonnaBe(1);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
await ifWe(sir, 'sender durable space has full S dep graph', async () => {
|
|
235
|
+
const latestS = peer.currentSessionIdentity;
|
|
236
|
+
iReckon(sir, latestS).asTo('latestS exists').isGonnaBeTruthy();
|
|
237
|
+
if (latestS) {
|
|
238
|
+
const depGraphS = await getDependencyGraph({ ibGib: latestS, space: sourceSpace });
|
|
239
|
+
const addrs = Object.keys(depGraphS);
|
|
240
|
+
iReckon(sir, addrs.length > 2).asTo('number of nodes in S graph > 2').isGonnaBeTrue();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
await ifWe(sir, 'receiver durable space has full S dep graph', async () => {
|
|
245
|
+
const latestS = peer.currentSessionIdentity;
|
|
246
|
+
iReckon(sir, latestS).asTo('latestS exists').isGonnaBeTruthy();
|
|
247
|
+
if (latestS) {
|
|
248
|
+
const depGraphS = await getDependencyGraph({ ibGib: latestS, space: destSpace });
|
|
249
|
+
const addrs = Object.keys(depGraphS);
|
|
250
|
+
iReckon(sir, addrs.length > 2).asTo('number of nodes in S graph in destSpace > 2').isGonnaBeTrue();
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
} catch (error) {
|
|
255
|
+
await ifWe(sir, `doh`, async () => {
|
|
256
|
+
iReckon(sir, true).asTo(`error: ${extractErrorMsg(error)}`).isGonnaBeFalse();
|
|
257
|
+
});
|
|
258
|
+
} finally {
|
|
259
|
+
if (logalot) { console.log(`${lc} Test complete.`); }
|
|
260
|
+
}
|
|
261
|
+
// #endregion r1 verify post
|
|
262
|
+
});
|
|
263
|
+
// #endregion Round 1 - Push timeline
|
|
264
|
+
|
|
265
|
+
});
|
|
@@ -325,7 +325,7 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
325
325
|
if (!msgResponse.data) { throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`); }
|
|
326
326
|
|
|
327
327
|
const responsePayloadIbGibsControl = [
|
|
328
|
-
msgResponse, responseCtx.sagaFrame,
|
|
328
|
+
msgResponse, responseCtx.sagaFrame, responseCtx
|
|
329
329
|
].map(x => toDto({ ibGib: x }));
|
|
330
330
|
// ...put into sender's durable space
|
|
331
331
|
await putInSpace({
|
|
@@ -198,7 +198,17 @@ export interface SyncPeerWitness<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
198
198
|
// getSenderIdentity(): KeystoneIbGib_V1 | undefined;
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
* Evolves the session identity (S_n -> S_n+1) and signs targeting
|
|
201
|
+
* Evolves the session identity (S_n -> S_n+1) and signs targeting
|
|
202
|
+
* contextAddr for the **sync** verb. This is in contrast to signing for
|
|
203
|
+
* the "connect" verb, for which you use {@link signContextConnect}
|
|
202
204
|
*/
|
|
203
205
|
signContext(opts: { contextAddr: IbGibAddr }): Promise<KeystoneIbGib_V1 | undefined>;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Evolves the session identity (S_n -> S_n+1) solving the demanded connect
|
|
209
|
+
* challenges. This is NOT for signing session when doing the ping pong of
|
|
210
|
+
* sync protocol. For that, you use {@link signContext}
|
|
211
|
+
*/
|
|
212
|
+
signContextConnect(opts: { challengeUuid: string, demandedIds: string[] }): Promise<KeystoneIbGib_V1 | undefined>;
|
|
213
|
+
|
|
204
214
|
}
|
|
@@ -23,7 +23,7 @@ import { getFullSyncSagaHistory, deriveSessionSecret } from '../sync-helpers.mjs
|
|
|
23
23
|
import { SessionGenesisFrameDetails, SyncSagaFrameDependencyGraph } from '../sync-types.mjs';
|
|
24
24
|
import { KeystoneService_V1 } from '../../keystone/keystone-service-v1.mjs';
|
|
25
25
|
import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
|
|
26
|
-
import { KEYSTONE_VERB_SYNC, } from '../../keystone/keystone-constants.mjs';
|
|
26
|
+
import { KEYSTONE_VERB_CONNECT, KEYSTONE_VERB_SYNC, POOL_ID_CONNECT, } from '../../keystone/keystone-constants.mjs';
|
|
27
27
|
import { getTjpAddr } from '../../common/other/ibgib-helper.mjs';
|
|
28
28
|
import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
|
|
29
29
|
|
|
@@ -99,6 +99,52 @@ export abstract class SyncPeer_V1<
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Evolves the session identity (S_n -> S_n+1) solving the demanded connect challenges.
|
|
104
|
+
*/
|
|
105
|
+
public async signContextConnect({
|
|
106
|
+
challengeUuid,
|
|
107
|
+
demandedIds,
|
|
108
|
+
}: {
|
|
109
|
+
challengeUuid: string;
|
|
110
|
+
demandedIds: string[];
|
|
111
|
+
}): Promise<KeystoneIbGib_V1 | undefined> {
|
|
112
|
+
const lc = `${this.lc}[${this.signContextConnect.name}]`;
|
|
113
|
+
try {
|
|
114
|
+
if (!this.currentSessionIdentity) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
if (!this.opts) { throw new Error(`opts not initialized. (E: bcf5978aed789b0ebcbdc51971ebe826)`); }
|
|
118
|
+
const { fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
|
|
119
|
+
if (!fnSenderSecret) { throw new Error(`fnSenderSecret not initialized. (E: 207fd292a2e8c53c05fd0a74a4ae6d26)`); }
|
|
120
|
+
if (!sagaId) { throw new Error(`sagaId not initialized. (E: f2e35cc13ed873b638116188119d1826)`); }
|
|
121
|
+
|
|
122
|
+
const senderSecret = await fnSenderSecret();
|
|
123
|
+
const sessionSecret = await deriveSessionSecret({ senderSecret, sagaId });
|
|
124
|
+
|
|
125
|
+
const keystoneSvc = new KeystoneService_V1();
|
|
126
|
+
const evolved = await keystoneSvc.sign({
|
|
127
|
+
latestKeystone: this.currentSessionIdentity,
|
|
128
|
+
masterSecret: sessionSecret,
|
|
129
|
+
poolId: POOL_ID_CONNECT,
|
|
130
|
+
requiredChallengeIds: demandedIds,
|
|
131
|
+
claim: {
|
|
132
|
+
verb: KEYSTONE_VERB_CONNECT,
|
|
133
|
+
target: challengeUuid,
|
|
134
|
+
},
|
|
135
|
+
metaspace: localMetaspace,
|
|
136
|
+
space: localSpace,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
this.currentSessionIdentity = evolved;
|
|
140
|
+
return evolved;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
102
148
|
get classname(): string {
|
|
103
149
|
if (!this.data) { throw new Error(`(UNEXPECTED) this.data falsy? (E: 1ab1841e9338b54f3aa615fa37024826)`); }
|
|
104
150
|
if (!this.data.classname) { throw new Error(`invalid peer. this.data.classname is falsy (E: b0ee28a0abb84a06588d9de7afcef826)`); }
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# WebSocket Sync Peers
|
|
2
|
+
|
|
3
|
+
This directory contains the WebSocket client (sender) and server (receiver) peer implementations.
|
|
4
|
+
|
|
5
|
+
## WebSocket Resource Management & Teardown
|
|
6
|
+
|
|
7
|
+
Since WebSockets manage active OS-level TCP connections, they must be cleanly closed to prevent socket descriptor leaks on the client and resource exhaustion (DoS) on the server.
|
|
8
|
+
|
|
9
|
+
### Analysis (2026-06-12T09:45:21-05:00)
|
|
10
|
+
|
|
11
|
+
Our analysis highlights several areas where WebSocket connections are currently left open:
|
|
12
|
+
|
|
13
|
+
1. **Sender Connect Failures**: If connection handshake fails or times out, the client rejects the promise but does not close the socket.
|
|
14
|
+
2. **Sender Runtime Failures**: If runtime message validation fails, we throw an error but leave the socket open.
|
|
15
|
+
3. **Sender Saga Completion**: When the sync loop finishes successfully, the socket is left open indefinitely because there is no `disconnect` method.
|
|
16
|
+
4. **Receiver Message Handling Failures**: If incoming messages fail validation/authentication, the server sends a `sync_error` or `auth_fail` frame, but relies on the client to close the connection. A buggy/malicious client can leave it open forever.
|
|
17
|
+
|
|
18
|
+
#### Design Questions & Ideas
|
|
19
|
+
* **Idempotent `disconnect()`**: The disconnect method on the sender should clear `this.handshakeMessageListener` and set it to `undefined` so that multiple calls to `disconnect()` are safe.
|
|
20
|
+
* **Reuse `disconnect()`**: In connection failure handlers (like `handleHandshakeAuthFail`), we can call `this.disconnect()` to ensure uniform cleanup.
|
|
21
|
+
* **Server-side Close on Error (best-effort `send`)**: If a message fails, we want to notify the client first and then close the connection. If the `send()` itself throws, we want a safe cleanup. In JavaScript, we can nest `try..catch..finally` inside a `catch` block, or use a short `setTimeout` to push the socket close operation to the next event loop tick, ensuring the outgoing frame is written before the socket is terminated.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
### Implementation TODOs
|
|
26
|
+
|
|
27
|
+
- [x] **Implement `disconnect` method on `SyncPeerWebSocketSender_V1`**
|
|
28
|
+
- Implement a synchronous or asynchronous `disconnect()` method.
|
|
29
|
+
- Safely remove the message event listener `this.handshakeMessageListener`.
|
|
30
|
+
- Set `this.handshakeMessageListener = undefined` to make it idempotent.
|
|
31
|
+
- Close the WebSocket `this.ws.close()`.
|
|
32
|
+
|
|
33
|
+
- [x] **Clean up socket on Sender connection failures**
|
|
34
|
+
- Call `this.disconnect()` inside `handleHandshakeAuthFail`.
|
|
35
|
+
- Call `this.disconnect()` inside `handleHandshakeSyncError`.
|
|
36
|
+
|
|
37
|
+
- [x] **Close socket on Sender runtime message validation failures**
|
|
38
|
+
- In `handleRuntimeMessage` and `handleRuntimeSyncFrameResponse`, catch validation errors, trigger `this.disconnect()`, and rethrow.
|
|
39
|
+
|
|
40
|
+
- [x] **Close socket on Receiver message handling failures**
|
|
41
|
+
- In the catch block of `handleIncomingMessage`, call `this.socketWrapper?.close()` (or equivalent wrapper cleanup) to force-close connections after sending error frames.
|
|
42
|
+
- Wrap the `send()` call in a nested try/catch or use `setTimeout` to ensure best-effort message transmission before terminating the socket wrapper.
|
|
@@ -34,6 +34,7 @@ export interface IWebSocketWrapper {
|
|
|
34
34
|
send(data: string): void;
|
|
35
35
|
onMessage(callback: (data: string) => void): void;
|
|
36
36
|
onClose(callback: () => void): void;
|
|
37
|
+
close(): void;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -67,6 +68,7 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
67
68
|
protected pendingContext?: SyncSagaContextIbGib_V1;
|
|
68
69
|
protected pendingPayloadAddrs?: Set<string>;
|
|
69
70
|
protected pendingResponsePayloadsToSend: IbGib_V1[] = [];
|
|
71
|
+
protected receivedPayloads: IbGib_V1[] = [];
|
|
70
72
|
|
|
71
73
|
constructor(
|
|
72
74
|
initialData: SyncPeerWebSocketReceiverData_V1,
|
|
@@ -188,16 +190,20 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
188
190
|
throw new Error(`controlIbGibs invalid intrinsically. validationErrors: ${validationErrors.join('|')} (E: 5ee1787d4cc53d3d2c55f3d4f2865226)`);
|
|
189
191
|
}
|
|
190
192
|
|
|
191
|
-
|
|
193
|
+
const pendingPayloadAddrs = this.pendingPayloadAddrs;
|
|
194
|
+
if (this.pendingContext && pendingPayloadAddrs) {
|
|
192
195
|
const addr = getIbGibAddr({ ibGib });
|
|
193
|
-
if (
|
|
196
|
+
if (pendingPayloadAddrs.has(addr)) {
|
|
194
197
|
const tempSpace = await this.ensureLocalTempSpace();
|
|
195
198
|
await putInSpace({ space: tempSpace, ibGibs: [ibGib] });
|
|
196
|
-
this.
|
|
199
|
+
this.receivedPayloads.push(ibGib);
|
|
200
|
+
pendingPayloadAddrs.delete(addr);
|
|
197
201
|
|
|
198
202
|
// If all expected payloads for the pending context are received
|
|
199
|
-
if (
|
|
203
|
+
if (pendingPayloadAddrs.size === 0 && this.pendingPayloadAddrs !== undefined) {
|
|
200
204
|
const context = this.pendingContext;
|
|
205
|
+
context.payloadIbGibsDomain = this.receivedPayloads;
|
|
206
|
+
this.receivedPayloads = [];
|
|
201
207
|
this.pendingContext = undefined;
|
|
202
208
|
this.pendingPayloadAddrs = undefined;
|
|
203
209
|
|
|
@@ -213,7 +219,8 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
213
219
|
// First, validate and authenticate the context
|
|
214
220
|
const allControlIbGibs: IbGib_V1[] = [
|
|
215
221
|
toDto({ ibGib: context }),
|
|
216
|
-
context.sagaFrame
|
|
222
|
+
context.sagaFrame,
|
|
223
|
+
context.sagaFrameMsg
|
|
217
224
|
];
|
|
218
225
|
if (context.signedSessionIdentity) {
|
|
219
226
|
allControlIbGibs.push(context.signedSessionIdentity);
|
|
@@ -241,6 +248,7 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
241
248
|
// Set up wait state and request payloads
|
|
242
249
|
this.pendingContext = context;
|
|
243
250
|
this.pendingPayloadAddrs = new Set(expectedPayloadAddrs);
|
|
251
|
+
this.receivedPayloads = [];
|
|
244
252
|
this.socketWrapper.send(JSON.stringify({
|
|
245
253
|
type: SyncWebSocketMsgType.sync_frame_authenticated,
|
|
246
254
|
contextAddr: getIbGibAddr({ ibGib: context })
|
|
@@ -259,13 +267,21 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
259
267
|
ibGib
|
|
260
268
|
}));
|
|
261
269
|
}
|
|
270
|
+
} else {
|
|
271
|
+
throw new Error(`(UNEXPECTED) msg.type is ${msg.type}? not expected at this time (E: bad7c4fa1958b1976904cb884e624826)`);
|
|
262
272
|
}
|
|
263
273
|
} catch (error) {
|
|
264
274
|
console.error(`${lc} message frame handling failed: ${extractErrorMsg(error)}`);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
275
|
+
try {
|
|
276
|
+
this.socketWrapper?.send(JSON.stringify({
|
|
277
|
+
type: this.isAuthenticated ? SyncWebSocketMsgType.sync_error : SyncWebSocketMsgType.auth_fail,
|
|
278
|
+
message: extractErrorMsg(error)
|
|
279
|
+
}));
|
|
280
|
+
} catch (nestedError) {
|
|
281
|
+
console.error(`${lc}[nested catch] failed to send error frame: ${extractErrorMsg(nestedError)}`);
|
|
282
|
+
} finally {
|
|
283
|
+
this.socketWrapper?.close();
|
|
284
|
+
}
|
|
269
285
|
}
|
|
270
286
|
}
|
|
271
287
|
|
|
@@ -327,6 +343,7 @@ export class SyncPeerWebSocketReceiver_V1
|
|
|
327
343
|
|
|
328
344
|
// Persist the newly validated evolved session keystone tip
|
|
329
345
|
await metaspace.put({ ibGibs: [proofFrame], space });
|
|
346
|
+
await metaspace.registerNewIbGib({ ibGib: proofFrame, space });
|
|
330
347
|
|
|
331
348
|
if (logalot) { console.log(`${lc} connect validation successful! Connection upgraded to active sync session.`); }
|
|
332
349
|
this.isAuthenticated = true;
|
|
@@ -41,7 +41,7 @@ export const SESSION_KEYSTONE_POLICY = {
|
|
|
41
41
|
SIZE: 10,
|
|
42
42
|
SELECT_SEQUENTIALLY: 2,
|
|
43
43
|
SELECT_RANDOMLY: 2,
|
|
44
|
-
|
|
44
|
+
TARGET_BINDING_COUNT: 0,
|
|
45
45
|
SERVER_DEMAND_COUNT: 3,
|
|
46
46
|
}
|
|
47
47
|
} as const;
|
|
@@ -298,8 +298,10 @@ export async function validateAndRegisterEvolveKeystone({
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
// 2. Verify URL :domainAddr matches the keystone's tjp
|
|
301
|
-
const
|
|
302
|
-
const
|
|
301
|
+
const infoAddr = getGibInfo({ ibGibAddr: addr });
|
|
302
|
+
const tjpGib = infoAddr.tjpGib ?? infoAddr.punctiliarHash;
|
|
303
|
+
const infoDomain = getGibInfo({ ibGibAddr: domainAddr });
|
|
304
|
+
const expectedTjpGib = infoDomain.tjpGib ?? infoDomain.punctiliarHash;
|
|
303
305
|
if (tjpGib !== expectedTjpGib) {
|
|
304
306
|
throw new Error(`Keystone tjpGib (${tjpGib}) does not match URL domainAddr tjpGib (${expectedTjpGib})`);
|
|
305
307
|
}
|