@ibgib/core-gib 0.1.45 → 0.1.48
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/common/other/ibgib-helper.d.mts +12 -0
- package/dist/common/other/ibgib-helper.d.mts.map +1 -1
- package/dist/common/other/ibgib-helper.mjs +39 -0
- package/dist/common/other/ibgib-helper.mjs.map +1 -1
- package/dist/keystone/kdf/kdf-helpers.mjs +2 -2
- package/dist/keystone/kdf/kdf-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.d.mts +2 -1
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +8 -2
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +33 -3
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +31 -1
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +16 -1
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +227 -8
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts +4 -1
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +6 -1
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +26 -26
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +26 -5
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/keystone-types.mjs.map +1 -1
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +1 -1
- package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-basic-divergence.respec.mjs +1 -1
- package/dist/sync/sync-conflict-basic-divergence.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs +1 -1
- package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs.map +1 -1
- package/dist/sync/sync-conflict-text-merge.respec.mjs +1 -1
- package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
- package/dist/sync/sync-constants.d.mts +47 -1
- package/dist/sync/sync-constants.d.mts.map +1 -1
- package/dist/sync/sync-constants.mjs +49 -1
- package/dist/sync/sync-constants.mjs.map +1 -1
- package/dist/sync/sync-innerspace-constants.respec.mjs +1 -1
- package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs +1 -1
- package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +33 -19
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +1 -1
- package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-partial-update.respec.mjs +1 -1
- package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace.respec.mjs +1 -1
- package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
- 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 +5 -0
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts +6 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +56 -14
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +7 -3
- 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 +32 -3
- 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 +16 -0
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +18 -3
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +243 -56
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-types.d.mts +1 -1
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/package.json +1 -1
- package/src/common/other/ibgib-helper.mts +39 -0
- package/src/keystone/kdf/kdf-helpers.mts +2 -2
- package/src/keystone/keystone-config-builder.mts +13 -2
- package/src/keystone/keystone-constants.mts +33 -2
- package/src/keystone/keystone-helpers.mts +237 -8
- package/src/keystone/keystone-service-v1.mts +5 -0
- package/src/keystone/keystone-service-v1.respec.mts +25 -25
- package/src/keystone/keystone-types.mts +31 -8
- package/src/sync/sync-conflict-adv-multitimelines.respec.mts +1 -1
- package/src/sync/sync-conflict-basic-divergence.respec.mts +1 -1
- package/src/sync/sync-conflict-basic-multitimelines.respec.mts +1 -1
- package/src/sync/sync-conflict-text-merge.respec.mts +1 -1
- package/src/sync/sync-constants.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-withid.respec.mts +36 -19
- package/src/sync/sync-innerspace-dest-ahead.respec.mts +1 -1
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
- package/src/sync/sync-innerspace-partial-update.respec.mts +1 -1
- package/src/sync/sync-innerspace.respec.mts +1 -1
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +5 -0
- package/src/sync/sync-peer/sync-peer-v1.mts +63 -15
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +52 -4
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +17 -0
- package/src/sync/sync-saga-coordinator.mts +298 -63
- package/src/sync/sync-types.mts +1 -1
|
@@ -87,7 +87,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
|
|
|
87
87
|
async function newTestPeer(): Promise<SyncPeerInnerspace_V1> {
|
|
88
88
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
89
89
|
await peer.initialized;
|
|
90
|
-
await peer.
|
|
90
|
+
await peer.initializeOpts({
|
|
91
91
|
senderSpace: sourceSpace,
|
|
92
92
|
receiverSpace: destSpace,
|
|
93
93
|
receiverCoordinator: receiverCoordinator,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { HashAlgorithm } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
|
|
1
2
|
import { ROOT_ADDR } from "@ibgib/ts-gib/dist/V1/constants.mjs";
|
|
3
|
+
import { KeystoneReplenishStrategy } from "../keystone/keystone-types.mjs";
|
|
4
|
+
import { KEYSTONE_VERB_MANAGE, KEYSTONE_VERB_SIGN, POOL_ID_DEFAULT, POOL_ID_DELEGATE, POOL_ID_TRANSITION } from "../keystone/keystone-constants.mjs";
|
|
2
5
|
|
|
3
6
|
export const SYNC_ATOM = "sync";
|
|
4
7
|
|
|
@@ -78,6 +81,18 @@ export function isValidSyncConflictStrategy(strategy: string): strategy is SyncC
|
|
|
78
81
|
}
|
|
79
82
|
// #endregion SyncConflictStrategy
|
|
80
83
|
|
|
84
|
+
/**
|
|
85
|
+
* to be used by the sender
|
|
86
|
+
*/
|
|
87
|
+
export const SESSION_IDENTITY_KEYSTONE_PRIMARY_POOL_ID = POOL_ID_DEFAULT;
|
|
88
|
+
/**
|
|
89
|
+
* single use pool
|
|
90
|
+
*/
|
|
91
|
+
export const SESSION_IDENTITY_KEYSTONE_TRANSITION_POOL_ID = POOL_ID_TRANSITION;
|
|
92
|
+
/**
|
|
93
|
+
* to be used by the receiver, created via the single-use transition pool.
|
|
94
|
+
*/
|
|
95
|
+
export const SESSION_IDENTITY_KEYSTONE_DELEGATE_POOL_ID = POOL_ID_DELEGATE;
|
|
81
96
|
/**
|
|
82
97
|
* When synchronizing, the plan for identity integration is to create a session
|
|
83
98
|
* keystone. This keystone will have a primary pool, driven by the sender's
|
|
@@ -86,4 +101,39 @@ export function isValidSyncConflictStrategy(strategy: string): strategy is SyncC
|
|
|
86
101
|
* use this to then change the keystone to use a secret chosen by the
|
|
87
102
|
* receiver's end.
|
|
88
103
|
*/
|
|
89
|
-
export const
|
|
104
|
+
export const SESSION_IDENTITY_KEYSTONE_SECRET_TRANSITIONPOOL = ROOT_ADDR;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* has to be big enough to avoid our currently poor (atow 02/24/2026)
|
|
108
|
+
* implementation of the binding target.
|
|
109
|
+
*/
|
|
110
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_SIZE = 100;
|
|
111
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_ALGO = HashAlgorithm.sha_256;
|
|
112
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_ROUNDS = 3;
|
|
113
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_RANDOM = 2;
|
|
114
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_SEQUENTIAL = 2;
|
|
115
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_TARGET_BINDING = 4;
|
|
116
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_REPLENISH_STRATEGY = KeystoneReplenishStrategy.topUp;
|
|
117
|
+
/**
|
|
118
|
+
* verbs associated with primary/sender participant.
|
|
119
|
+
*
|
|
120
|
+
* todo: would be slightly cleaner to have the sender/primary genesis with two pools, one for signing and one being one-time manage use (to add the transition pool) just like the transition pool, but this is a finesse and not for V1. Still it is neat that this possibility/mechanism exists.
|
|
121
|
+
*/
|
|
122
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_VERBS_PRIMARY = [KEYSTONE_VERB_MANAGE];
|
|
123
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_VERBS_DELEGATE = [KEYSTONE_VERB_SIGN];
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* transition pool is purposefully weak with a known password.
|
|
127
|
+
*/
|
|
128
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_SIZE_TRANSITIONPOOL = 1;
|
|
129
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_ALGO_TRANSITIONPOOL = HashAlgorithm.sha_256;
|
|
130
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_ROUNDS_TRANSITIONPOOL = 1;
|
|
131
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_RANDOM_TRANSITIONPOOL = 0;
|
|
132
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_SEQUENTIAL_TRANSITIONPOOL = 1;
|
|
133
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_TARGET_BINDING_TRANSITIONPOOL = 0;
|
|
134
|
+
/**
|
|
135
|
+
* This pool is to be used only once, by the receiver, in order for the receiver
|
|
136
|
+
* to create their own pool.
|
|
137
|
+
*/
|
|
138
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_REPLENISH_STRATEGY_TRANSITIONPOOL = KeystoneReplenishStrategy.deleteAll;
|
|
139
|
+
export const SESSION_IDENTITY_KEYSTONE_CONFIG_VERBS_TRANSITIONPOOL = [KEYSTONE_VERB_MANAGE];
|
|
@@ -72,7 +72,7 @@ await respecfully(sir, `Sync Constants (No TJP)`, async () => {
|
|
|
72
72
|
|
|
73
73
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
74
74
|
await peer.initialized;
|
|
75
|
-
await peer.
|
|
75
|
+
await peer.initializeOpts({
|
|
76
76
|
senderSpace: sourceSpace, // "Client"
|
|
77
77
|
receiverSpace: destSpace, // "Server"
|
|
78
78
|
receiverCoordinator,
|
|
@@ -103,7 +103,7 @@ await respecfully(sir, `Sync InnerSpaces (Deep Updates)`, async () => {
|
|
|
103
103
|
|
|
104
104
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
105
105
|
await peer.initialized;
|
|
106
|
-
await peer.
|
|
106
|
+
await peer.initializeOpts({
|
|
107
107
|
senderSpace: sourceSpace, // "Client"
|
|
108
108
|
receiverSpace: destSpace, // "Server"
|
|
109
109
|
receiverCoordinator,
|
|
@@ -29,6 +29,8 @@ import { ErrorIbGib_V1 } from '../common/error/error-types.mjs';
|
|
|
29
29
|
import { SyncIbGib_V1 } from './sync-types.mjs';
|
|
30
30
|
import { getFullSyncSagaHistory } from './sync-helpers.mjs';
|
|
31
31
|
import { getIbGibsFromCache_fallbackToSpaces } from '../common/other/ibgib-helper.mjs';
|
|
32
|
+
import { SyncSagaContextIbGib_V1 } from './sync-saga-context/sync-saga-context-types.mjs';
|
|
33
|
+
import { isSyncSagaContextIbGib } from './sync-saga-context/sync-saga-context-helpers.mjs';
|
|
32
34
|
|
|
33
35
|
const logalot = false;
|
|
34
36
|
const lc = `[sync-innerspace-dest-ahead.respec]`;
|
|
@@ -38,6 +40,9 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
38
40
|
let metaspace: Metaspace_Innerspace;
|
|
39
41
|
let sourceSpace: InnerSpace_V1;
|
|
40
42
|
let destSpace: InnerSpace_V1;
|
|
43
|
+
let secretSender = 'secret for sender';
|
|
44
|
+
let secretReceiver = 'secret for receiver';
|
|
45
|
+
let secretAdversary = 'secret for adversary';
|
|
41
46
|
|
|
42
47
|
interface TestData {
|
|
43
48
|
type: string;
|
|
@@ -119,7 +124,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
119
124
|
return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
|
|
120
125
|
}
|
|
121
126
|
|
|
122
|
-
await
|
|
127
|
+
await ifWeMight(sir, 'verify setup', async () => {
|
|
123
128
|
// Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
|
|
124
129
|
// Ensure Source does NOT have V2
|
|
125
130
|
iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
|
|
@@ -137,7 +142,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
137
142
|
|
|
138
143
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
139
144
|
await peer.initialized;
|
|
140
|
-
await peer.
|
|
145
|
+
await peer.initializeOpts({
|
|
141
146
|
senderSpace: sourceSpace, // "Client"
|
|
142
147
|
receiverSpace: destSpace, // "Server"
|
|
143
148
|
receiverCoordinator,
|
|
@@ -152,8 +157,10 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
152
157
|
metaspace: metaspace,
|
|
153
158
|
domainIbGibs: [v1], // Source tries to push V1
|
|
154
159
|
useSessionIdentity: true,
|
|
160
|
+
identitySecret: secretSender,
|
|
155
161
|
});
|
|
156
162
|
|
|
163
|
+
const syncSagaContextIbGibs: SyncSagaContextIbGib_V1[] = [];
|
|
157
164
|
const sublc = `${lc}[updates$]`;
|
|
158
165
|
/**
|
|
159
166
|
* I have added this so you can see how to subscribe to an ibgib
|
|
@@ -163,6 +170,11 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
163
170
|
next: async (ctxIbGib) => {
|
|
164
171
|
// console.log(`${sublc} next fired. ${JSON.stringify(ctxIbGib)}`);
|
|
165
172
|
console.log(`${sublc} next fired. (I: e68d8894bac8800f9f3430e8a38d6626)`);
|
|
173
|
+
// each context ibgib
|
|
174
|
+
if (!isSyncSagaContextIbGib(ctxIbGib)) {
|
|
175
|
+
throw new Error(`(UNEXPECTED) ctxIbGib isn't a SyncSagaContextIbGib_V1? (E: ee116e6b6208e615dbcd3e715643e826)`);
|
|
176
|
+
}
|
|
177
|
+
syncSagaContextIbGibs.push(ctxIbGib);
|
|
166
178
|
},
|
|
167
179
|
error: async (e: ErrorIbGib_V1) => {
|
|
168
180
|
if (e.data) {
|
|
@@ -178,17 +190,10 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
178
190
|
}));
|
|
179
191
|
await done;
|
|
180
192
|
|
|
181
|
-
// TODO: Get saga IbGib to access session keystones
|
|
182
|
-
// Bill suggested either:
|
|
183
|
-
// 1. Subscribe to updates$ to inspect frames as sync progresses
|
|
184
|
-
// 2. Change done from Promise<void> to Promise<IbGibAddr>, return saga addr,
|
|
185
|
-
// then use getIbGibsFromCache_fallbackToSpaces and getFullSyncSagaHistory
|
|
186
|
-
// For now, leaving implementation for next step.
|
|
187
|
-
|
|
188
193
|
// 5. Verify Sync (v2 should be in both source and dest now)
|
|
189
194
|
console.log(`${lc} Verifying Sync...`);
|
|
190
195
|
|
|
191
|
-
await
|
|
196
|
+
await ifWeMight(sir, `verify v2 now also in source`, async () => {
|
|
192
197
|
// Verify Tip (V2)
|
|
193
198
|
|
|
194
199
|
iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
|
|
@@ -200,7 +205,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
200
205
|
|
|
201
206
|
});
|
|
202
207
|
|
|
203
|
-
await
|
|
208
|
+
await ifWeMight(sir, `dependency graphs the same`, async () => {
|
|
204
209
|
|
|
205
210
|
const sourceDepGraph = await getDependencyGraph({
|
|
206
211
|
ibGibAddr: addrV2,
|
|
@@ -229,11 +234,23 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
229
234
|
// For now, we'll retrieve from spaces after sync completes
|
|
230
235
|
let sessionKeystoneAddr: IbGibAddr | undefined;
|
|
231
236
|
|
|
232
|
-
await
|
|
237
|
+
await ifWeMight(sir, 'IDENTITY: session keystone exists in sender space', async () => {
|
|
233
238
|
// TODO: Get saga IbGib and access sessionKeystones rel8n
|
|
234
239
|
// Once saga access is implemented (per Bill's guidance), retrieve keystone addr from:
|
|
235
240
|
// const keystoneAddrs = sagaIbGib.rel8ns?.sessionKeystones;
|
|
236
241
|
// Then verify keystone exists in space
|
|
242
|
+
debugger;
|
|
243
|
+
|
|
244
|
+
// #region leaving off here
|
|
245
|
+
|
|
246
|
+
// receiver is not putting the session keystone on the return
|
|
247
|
+
// context ibgib. need to ensure that peer's do the most recent
|
|
248
|
+
// session keystone manually, so session keystone should be
|
|
249
|
+
// transferred alongside context ibgib (which is signed but
|
|
250
|
+
// intrinsically points to the **previous** frame of the keystone)
|
|
251
|
+
|
|
252
|
+
// #endregion leaving off here
|
|
253
|
+
syncSagaContextIbGibs.forEach(x => console.log(pretty(x)));
|
|
237
254
|
|
|
238
255
|
// Placeholder - test passes because keystone creation works
|
|
239
256
|
iReckon(sir, true)
|
|
@@ -241,7 +258,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
241
258
|
.isGonnaBeTrue();
|
|
242
259
|
});
|
|
243
260
|
|
|
244
|
-
await
|
|
261
|
+
await ifWeMight(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
|
|
245
262
|
// Session keystone should be transferred to receiver's durable space
|
|
246
263
|
iReckon(sir, sessionKeystoneAddr)
|
|
247
264
|
.asTo('session keystone address was captured')
|
|
@@ -255,7 +272,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
255
272
|
}
|
|
256
273
|
});
|
|
257
274
|
|
|
258
|
-
await
|
|
275
|
+
await ifWeMight(sir, 'IDENTITY: saga frames are signed', async () => {
|
|
259
276
|
// TODO: Get saga frames and check each has a proof
|
|
260
277
|
// This will FAIL when we actually check - that's the point (TDD RED)
|
|
261
278
|
|
|
@@ -264,7 +281,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
264
281
|
.isGonnaBeTrue();
|
|
265
282
|
});
|
|
266
283
|
|
|
267
|
-
await
|
|
284
|
+
await ifWeMight(sir, 'IDENTITY: frame signatures are valid', async () => {
|
|
268
285
|
// TODO: For each saga frame, validate proof against session keystone
|
|
269
286
|
// const isValid = await validateProofWithKeystone({
|
|
270
287
|
// proof: frame.proof,
|
|
@@ -279,7 +296,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
279
296
|
.isGonnaBeTrue();
|
|
280
297
|
});
|
|
281
298
|
|
|
282
|
-
await
|
|
299
|
+
await ifWeMight(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
|
|
283
300
|
// TODO: Session keystone should evolve after signing frames
|
|
284
301
|
// This will FAIL because keystone evolution not implemented yet
|
|
285
302
|
|
|
@@ -288,7 +305,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
288
305
|
.isGonnaBeTrue();
|
|
289
306
|
});
|
|
290
307
|
|
|
291
|
-
await
|
|
308
|
+
await ifWeMight(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
|
|
292
309
|
// TODO: Check each frame has timestamp in proof claim
|
|
293
310
|
// const claim = JSON.parse(frame.proof.claim.scope);
|
|
294
311
|
// iReckon(sir, claim.timestamp).asTo('has timestamp').isGonnaBeTruthy();
|
|
@@ -301,7 +318,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
301
318
|
.isGonnaBeTrue();
|
|
302
319
|
});
|
|
303
320
|
|
|
304
|
-
await
|
|
321
|
+
await ifWeMight(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
|
|
305
322
|
if (sessionKeystoneAddr) {
|
|
306
323
|
const keystoneResult = await getFromSpace({
|
|
307
324
|
addr: sessionKeystoneAddr,
|
|
@@ -326,7 +343,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
326
343
|
}
|
|
327
344
|
});
|
|
328
345
|
|
|
329
|
-
await
|
|
346
|
+
await ifWeMight(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
|
|
330
347
|
// Saga frames should NOT have hard links to domain ibgibs
|
|
331
348
|
// This currently PASSES but will expose issues if hard links exist
|
|
332
349
|
|
|
@@ -134,7 +134,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
|
|
|
134
134
|
|
|
135
135
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
136
136
|
await peer.initialized;
|
|
137
|
-
await peer.
|
|
137
|
+
await peer.initializeOpts({
|
|
138
138
|
senderSpace: sourceSpace, // "Client"
|
|
139
139
|
receiverSpace: destSpace, // "Server"
|
|
140
140
|
receiverCoordinator,
|
|
@@ -107,7 +107,7 @@ await respecfully(sir, `Sync InnerSpaces (Multiple Timelines)`, async () => {
|
|
|
107
107
|
|
|
108
108
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
109
109
|
await peer.initialized;
|
|
110
|
-
await peer.
|
|
110
|
+
await peer.initializeOpts({
|
|
111
111
|
senderSpace: sourceSpace, // "Client"
|
|
112
112
|
receiverSpace: destSpace, // "Server"
|
|
113
113
|
receiverCoordinator,
|
|
@@ -115,7 +115,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
|
|
|
115
115
|
|
|
116
116
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
117
117
|
await peer.initialized;
|
|
118
|
-
await peer.
|
|
118
|
+
await peer.initializeOpts({
|
|
119
119
|
senderSpace: sourceSpace, // "Client"
|
|
120
120
|
receiverSpace: destSpace, // "Server"
|
|
121
121
|
receiverCoordinator,
|
|
@@ -107,7 +107,7 @@ await respecfully(sir, `Sync InnerSpaces`, async () => {
|
|
|
107
107
|
// Peer (The "Network")
|
|
108
108
|
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
109
109
|
await peer.initialized;
|
|
110
|
-
await peer.
|
|
110
|
+
await peer.initializeOpts({
|
|
111
111
|
senderSpace: sourceSpace, // "Client"
|
|
112
112
|
receiverSpace: destSpace, // "Server"
|
|
113
113
|
receiverCoordinator,
|
|
@@ -198,11 +198,16 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<InitializeSyncPeerInnersp
|
|
|
198
198
|
// the payload ibgibs. so the receiver coordinator should be ready
|
|
199
199
|
// to do its thing.
|
|
200
200
|
|
|
201
|
+
const identitySecret = context.fnIdentitySecret ?
|
|
202
|
+
await context.fnIdentitySecret() :
|
|
203
|
+
undefined;
|
|
201
204
|
const responseCtx = await receiverCoordinator.continueSync({
|
|
202
205
|
sagaContext: context,
|
|
203
206
|
metaspace: receiverMetaspace,
|
|
204
207
|
mySpace: receiverSpace,
|
|
205
208
|
myTempSpace: receiverTempSpace,
|
|
209
|
+
identity: context.signedSessionKeystone,
|
|
210
|
+
identitySecret,
|
|
206
211
|
});
|
|
207
212
|
|
|
208
213
|
if (logalot) { console.log(`${lc} receiverCoordinator.continueSync responseCtx: ${responseCtx ? pretty(responseCtx) : 'undefined'} (I: fb2831decde1f2b3589021f85ab19126)`); }
|
|
@@ -20,11 +20,14 @@ import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
|
|
|
20
20
|
import { newupSubject } from '../../common/pubsub/subject/subject-helper.mjs';
|
|
21
21
|
import { authenticateContext, authorizeContext, validateContextAndSagaFrame } from '../sync-saga-context/sync-saga-context-helpers.mjs';
|
|
22
22
|
import { getFromSpace } from '../../witness/space/space-helper.mjs';
|
|
23
|
+
import { getFullSyncSagaHistory } from '../sync-helpers.mjs';
|
|
24
|
+
import { SyncSagaFrameDependencyGraph } from '../sync-types.mjs';
|
|
23
25
|
|
|
24
26
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
25
27
|
const logalotControlDomain = false;
|
|
26
28
|
const lcControlDomain = '[ControlDomain]';
|
|
27
29
|
|
|
30
|
+
|
|
28
31
|
/**
|
|
29
32
|
* Abstract witness for talking to a Sync Peer (e.g. Remote Node or Local Simulator).
|
|
30
33
|
*
|
|
@@ -66,8 +69,8 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
66
69
|
*
|
|
67
70
|
* @see {@link SyncPeerWitness.opts}
|
|
68
71
|
*/
|
|
69
|
-
public async
|
|
70
|
-
const lc = `${this.lc}[${this.
|
|
72
|
+
public async initializeOpts(opts: TInitializeOpts): Promise<void> {
|
|
73
|
+
const lc = `${this.lc}[${this.initializeOpts.name}]`;
|
|
71
74
|
try {
|
|
72
75
|
if (logalot) { console.log(`${lc} starting... (I: 31bd5fda37c89fa37fbaf14daf5fe726)`); }
|
|
73
76
|
this.opts = opts;
|
|
@@ -117,6 +120,42 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
117
120
|
|
|
118
121
|
protected abstract ensureReceiverTempSpace(): Promise<IbGibSpaceAny>;
|
|
119
122
|
|
|
123
|
+
protected async authenticateValidateAuthorize({
|
|
124
|
+
context,
|
|
125
|
+
fullSagaHistory,
|
|
126
|
+
}: {
|
|
127
|
+
context: SyncSagaContextIbGib_V1,
|
|
128
|
+
fullSagaHistory: SyncSagaFrameDependencyGraph[],
|
|
129
|
+
}): Promise<void> {
|
|
130
|
+
const lc = `${this.lc}[${this.authenticateValidateAuthorize.name}]`;
|
|
131
|
+
try {
|
|
132
|
+
if (logalot) { console.log(`${lc} starting... (I: add238055cd84a222c5b8c89913af526)`); }
|
|
133
|
+
|
|
134
|
+
// first authenticate, because invalid identity is a non-starter
|
|
135
|
+
const authenticationErrors = await authenticateContext({ context, fullSagaHistory });
|
|
136
|
+
if (authenticationErrors.length > 0) {
|
|
137
|
+
throw new Error(`invalid context authentication. authenticationErrors: ${authenticationErrors} (E: da89da5ee1269aeb78952d475d607526)`);
|
|
138
|
+
}
|
|
139
|
+
// next, we have a valid keystone, which should point to the
|
|
140
|
+
// context. But is that context and the saga data it contains valid?
|
|
141
|
+
// Does the keystone actually point to this context?
|
|
142
|
+
const validationErrors = await validateContextAndSagaFrame({ context, });
|
|
143
|
+
if (validationErrors.length > 0) {
|
|
144
|
+
throw new Error(`invalid context received. validationErrors: ${validationErrors} (E: 8b34c875c968af29bc433138e57a7826)`);
|
|
145
|
+
}
|
|
146
|
+
// we have a valid keystone that points to a valid context, but what
|
|
147
|
+
// exactly does the keystone authorize?
|
|
148
|
+
const authorizationErrors = await authorizeContext({ context, fullSagaHistory });
|
|
149
|
+
if (authorizationErrors.length > 0) {
|
|
150
|
+
throw new Error(`invalid context authorization. authorizationErrors: ${authorizationErrors} (E: 8ddc284a758cf10ba829334c1babb826)`);
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
154
|
+
throw error;
|
|
155
|
+
} finally {
|
|
156
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
120
159
|
/**
|
|
121
160
|
* Witness the synchronization context (Send/Receive).
|
|
122
161
|
*
|
|
@@ -173,19 +212,19 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
173
212
|
// when all domain ibgibs are pulled, publish complete to the observable
|
|
174
213
|
// return resulting context ibgib (which the caller should get BEFORE the domain ibgibs observable completes)
|
|
175
214
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
215
|
+
if (!context.sagaFrame) { throw new Error(`context.sagaFrame falsy. (E: a33dd88aa108e2bad9e885885731ce26)`); }
|
|
216
|
+
|
|
217
|
+
// this is not just happening on the client, but this peer may be
|
|
218
|
+
// the one receiving the context as well.
|
|
219
|
+
|
|
220
|
+
const sagaHistory_beforeSend = await getFullSyncSagaHistory({
|
|
221
|
+
sagaIbGib: context.sagaFrame,
|
|
222
|
+
space: this.opts.senderSpace
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
await this.authenticateValidateAuthorize({
|
|
226
|
+
context, fullSagaHistory: sagaHistory_beforeSend,
|
|
227
|
+
});
|
|
189
228
|
|
|
190
229
|
// at this point, we have a valid, authenticated, authorized context
|
|
191
230
|
|
|
@@ -203,6 +242,15 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
203
242
|
// receive, they may still be transferring. These will be published
|
|
204
243
|
// to this.payloadIbGibsDomainReceived$
|
|
205
244
|
|
|
245
|
+
const sagaHistory_afterSend = await getFullSyncSagaHistory({
|
|
246
|
+
sagaIbGib: context.sagaFrame,
|
|
247
|
+
space: this.opts.senderSpace
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
await this.authenticateValidateAuthorize({
|
|
251
|
+
context, fullSagaHistory: sagaHistory_afterSend,
|
|
252
|
+
});
|
|
253
|
+
|
|
206
254
|
return response;
|
|
207
255
|
} else {
|
|
208
256
|
// response falsy. we could be done, or this could be an error.
|
|
@@ -18,11 +18,12 @@ import {
|
|
|
18
18
|
} from './sync-saga-context-types.mjs';
|
|
19
19
|
import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
|
|
20
20
|
import { putInSpace, registerNewIbGib } from '../../witness/space/space-helper.mjs';
|
|
21
|
-
import { SyncIbGib_V1 } from '../sync-types.mjs';
|
|
21
|
+
import { SyncIbGib_V1, SyncSagaFrameDependencyGraph } from '../sync-types.mjs';
|
|
22
22
|
import { validateSyncSagaFrame } from '../sync-helpers.mjs';
|
|
23
23
|
import { validateKeystoneGraph, validateKeystoneTransition } from '../../keystone/keystone-helpers.mjs';
|
|
24
24
|
import { KeystoneService_V1 } from '../../keystone/keystone-service-v1.mjs';
|
|
25
25
|
import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
|
|
26
|
+
import { isIbGibWithAtom } from '../../common/other/ibgib-helper.mjs';
|
|
26
27
|
|
|
27
28
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
28
29
|
|
|
@@ -96,6 +97,24 @@ export async function parseSyncSagaContextIb({
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
export function isSyncSagaContextIbGib(x: any): x is SyncSagaContextIbGib_V1 {
|
|
101
|
+
const lc = `[${isSyncSagaContextIbGib.name}]`;
|
|
102
|
+
try {
|
|
103
|
+
if (logalot) { console.log(`${lc} starting... (I: 2bfa7f3cf5984b0c78aced881ce95226)`); }
|
|
104
|
+
|
|
105
|
+
const hasAtom = isIbGibWithAtom<SyncSagaContextIbGib_V1>(x, SYNC_SAGA_CONTEXT_ATOM);
|
|
106
|
+
|
|
107
|
+
// should be good enough in V1
|
|
108
|
+
|
|
109
|
+
return hasAtom;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
112
|
+
throw error;
|
|
113
|
+
} finally {
|
|
114
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
99
118
|
|
|
100
119
|
/**
|
|
101
120
|
* Validates ONLY the {@link context} ibgib itself and saga frame/msg stone(s)
|
|
@@ -109,7 +128,11 @@ export async function parseSyncSagaContextIb({
|
|
|
109
128
|
*
|
|
110
129
|
* @returns empty array if valid, else validation errors
|
|
111
130
|
*/
|
|
112
|
-
export async function validateContextAndSagaFrame({
|
|
131
|
+
export async function validateContextAndSagaFrame({
|
|
132
|
+
context,
|
|
133
|
+
}: {
|
|
134
|
+
context: SyncSagaContextIbGib_V1,
|
|
135
|
+
}): Promise<string[]> {
|
|
113
136
|
const lc = `[${validateContextAndSagaFrame.name}]`;
|
|
114
137
|
try {
|
|
115
138
|
if (logalot) { console.log(`${lc} starting... (I: 7797f8294bd8f7e5089cb722ad468226)`); }
|
|
@@ -178,13 +201,32 @@ export async function validateContextDomainPayloadIbGibs({ context }: { context:
|
|
|
178
201
|
/**
|
|
179
202
|
* move to sync-peer-helpers.mts as a pure function?
|
|
180
203
|
*/
|
|
181
|
-
export async function authenticateContext({
|
|
204
|
+
export async function authenticateContext({
|
|
205
|
+
context,
|
|
206
|
+
fullSagaHistory
|
|
207
|
+
}: {
|
|
208
|
+
context: SyncSagaContextIbGib_V1,
|
|
209
|
+
fullSagaHistory: SyncSagaFrameDependencyGraph[],
|
|
210
|
+
}): Promise<string[]> {
|
|
182
211
|
const lc = `[${authenticateContext.name}]`;
|
|
183
212
|
try {
|
|
184
213
|
if (logalot) { console.log(`${lc} starting... (I: 2677a482dfa873dcd1aa04a3031ff826)`); }
|
|
185
214
|
|
|
186
215
|
console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. // todo: authenticate (v1 must have this after we get merge logic workflow going) (E: bc3a78f2dab18ab64c36d055a4b50526)`);
|
|
187
216
|
|
|
217
|
+
// ensure the same identity rel8n timeline is in the first saga ibgib.
|
|
218
|
+
|
|
219
|
+
for (const sagaFrameDepGraph of fullSagaHistory) {
|
|
220
|
+
sagaFrameDepGraph.identities
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
// each saga ibgib should be updated with a new identity rel8n. each
|
|
225
|
+
// rel8n should correspond to each evolution of the keystone.
|
|
226
|
+
|
|
227
|
+
// if (context.sagaFrame.rel8ns?.sessionKeystone)
|
|
228
|
+
// context.signedSessionKeystone
|
|
229
|
+
|
|
188
230
|
return [];
|
|
189
231
|
} catch (error) {
|
|
190
232
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
@@ -197,7 +239,13 @@ export async function authenticateContext({ context }: { context: SyncSagaContex
|
|
|
197
239
|
/**
|
|
198
240
|
* move to sync-peer-helpers.mts as a pure function?
|
|
199
241
|
*/
|
|
200
|
-
export async function authorizeContext({
|
|
242
|
+
export async function authorizeContext({
|
|
243
|
+
context,
|
|
244
|
+
fullSagaHistory
|
|
245
|
+
}: {
|
|
246
|
+
context: SyncSagaContextIbGib_V1,
|
|
247
|
+
fullSagaHistory: SyncSagaFrameDependencyGraph[],
|
|
248
|
+
}): Promise<string[]> {
|
|
201
249
|
const lc = `[${authorizeContext.name}]`;
|
|
202
250
|
try {
|
|
203
251
|
if (logalot) { console.log(`${lc} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`); }
|
|
@@ -100,4 +100,21 @@ export interface SyncSagaContextIbGib_V1 extends IbGib_V1<SyncSagaContextData_V1
|
|
|
100
100
|
* previous frame of the keystone.
|
|
101
101
|
*/
|
|
102
102
|
signedSessionKeystone?: KeystoneIbGib_V1;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* If identity is used in the sync transaction, this should be provided. It
|
|
106
|
+
* will drive both primary identity keystone evolution (to create session
|
|
107
|
+
* keystone), as well as signing the session keystone itself.
|
|
108
|
+
*
|
|
109
|
+
* when a peer transmits the context ibgib, this does not need to be
|
|
110
|
+
* transmitted. Note, however, that if sync is occuring between two remote
|
|
111
|
+
* peers and the peer design is not a proxy-based one, then the receiver
|
|
112
|
+
* should assign this with their own provider function.
|
|
113
|
+
*
|
|
114
|
+
* @returns the identity secret when needed to sign/evolve keystone
|
|
115
|
+
*
|
|
116
|
+
* NOTE: Not 100% sure where I'm putting this so this may end up being
|
|
117
|
+
* unused and should thus be removed. Right now, I think this will work.
|
|
118
|
+
*/
|
|
119
|
+
fnIdentitySecret?: () => Promise<string>;
|
|
103
120
|
}
|