@ibgib/core-gib 0.1.43 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/keystone/kdf/kdf-constants.d.mts +25 -0
  2. package/dist/keystone/kdf/kdf-constants.d.mts.map +1 -0
  3. package/dist/keystone/kdf/kdf-constants.mjs +28 -0
  4. package/dist/keystone/kdf/kdf-constants.mjs.map +1 -0
  5. package/dist/keystone/kdf/kdf-helpers.d.mts +45 -0
  6. package/dist/keystone/kdf/kdf-helpers.d.mts.map +1 -0
  7. package/dist/keystone/kdf/kdf-helpers.mjs +94 -0
  8. package/dist/keystone/kdf/kdf-helpers.mjs.map +1 -0
  9. package/dist/keystone/kdf/kdf-types.d.mts +49 -0
  10. package/dist/keystone/kdf/kdf-types.d.mts.map +1 -0
  11. package/dist/keystone/kdf/kdf-types.mjs +2 -0
  12. package/dist/keystone/kdf/kdf-types.mjs.map +1 -0
  13. package/dist/keystone/keystone-config-builder.d.mts +65 -12
  14. package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
  15. package/dist/keystone/keystone-config-builder.mjs +138 -46
  16. package/dist/keystone/keystone-config-builder.mjs.map +1 -1
  17. package/dist/keystone/keystone-config-builder.respec.mjs +21 -13
  18. package/dist/keystone/keystone-config-builder.respec.mjs.map +1 -1
  19. package/dist/keystone/keystone-constants.d.mts +15 -0
  20. package/dist/keystone/keystone-constants.d.mts.map +1 -1
  21. package/dist/keystone/keystone-constants.mjs +16 -0
  22. package/dist/keystone/keystone-constants.mjs.map +1 -1
  23. package/dist/keystone/keystone-helpers.d.mts +8 -4
  24. package/dist/keystone/keystone-helpers.d.mts.map +1 -1
  25. package/dist/keystone/keystone-helpers.mjs +76 -6
  26. package/dist/keystone/keystone-helpers.mjs.map +1 -1
  27. package/dist/keystone/keystone-service-v1.d.mts +1 -1
  28. package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
  29. package/dist/keystone/keystone-service-v1.mjs +6 -5
  30. package/dist/keystone/keystone-service-v1.mjs.map +1 -1
  31. package/dist/keystone/keystone-service-v1.respec.mjs +72 -45
  32. package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
  33. package/dist/keystone/keystone-types.d.mts +28 -18
  34. package/dist/keystone/keystone-types.d.mts.map +1 -1
  35. package/dist/keystone/keystone-types.mjs +26 -15
  36. package/dist/keystone/keystone-types.mjs.map +1 -1
  37. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts.map +1 -1
  38. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs +7 -10
  39. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs.map +1 -1
  40. package/dist/sync/sync-constants.d.mts +9 -0
  41. package/dist/sync/sync-constants.d.mts.map +1 -1
  42. package/dist/sync/sync-constants.mjs +10 -0
  43. package/dist/sync/sync-constants.mjs.map +1 -1
  44. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +49 -19
  45. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -1
  46. package/dist/sync/sync-peer/sync-peer-v1.mjs +3 -3
  47. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  48. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +0 -38
  49. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
  50. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +1 -83
  51. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
  52. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +24 -4
  53. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
  54. package/dist/sync/sync-saga-coordinator.d.mts +36 -13
  55. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  56. package/dist/sync/sync-saga-coordinator.mjs +246 -38
  57. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  58. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -7
  59. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  60. package/dist/sync/sync-types.d.mts +11 -0
  61. package/dist/sync/sync-types.d.mts.map +1 -1
  62. package/dist/sync/sync-types.mjs.map +1 -1
  63. package/package.json +1 -1
  64. package/src/keystone/README.md +4 -3
  65. package/src/keystone/docs/architecture.md +3 -1
  66. package/src/keystone/kdf/kdf-constants.mts +34 -0
  67. package/src/keystone/kdf/kdf-helpers.mts +105 -0
  68. package/src/keystone/kdf/kdf-types.mts +58 -0
  69. package/src/keystone/keystone-config-builder.mts +170 -47
  70. package/src/keystone/keystone-config-builder.respec.mts +21 -14
  71. package/src/keystone/keystone-constants.mts +21 -2
  72. package/src/keystone/keystone-helpers.mts +100 -14
  73. package/src/keystone/keystone-service-v1.mts +23 -22
  74. package/src/keystone/keystone-service-v1.respec.mts +71 -44
  75. package/src/keystone/keystone-types.mts +37 -23
  76. package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +9 -13
  77. package/src/sync/sync-constants.mts +12 -0
  78. package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +53 -20
  79. package/src/sync/sync-peer/sync-peer-v1.mts +3 -3
  80. package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +3 -107
  81. package/src/sync/sync-saga-context/sync-saga-context-types.mts +25 -4
  82. package/src/sync/sync-saga-coordinator.mts +313 -40
  83. package/src/sync/sync-saga-message/sync-saga-message-types.mts +1 -7
  84. package/src/sync/sync-types.mts +12 -0
  85. package/tmp.md +0 -274
@@ -1,3 +1,5 @@
1
+ import { ROOT_ADDR } from "@ibgib/ts-gib/dist/V1/constants.mjs";
2
+
1
3
  export const SYNC_ATOM = "sync";
2
4
 
3
5
  export const SYNC_MSG_REL8N_NAME = "syncmsg";
@@ -75,3 +77,13 @@ export function isValidSyncConflictStrategy(strategy: string): strategy is SyncC
75
77
  return SYNC_CONFLICT_STRATEGY_VALID_VALUES.includes(strategy as SyncConflictStrategy);
76
78
  }
77
79
  // #endregion SyncConflictStrategy
80
+
81
+ /**
82
+ * When synchronizing, the plan for identity integration is to create a session
83
+ * keystone. This keystone will have a primary pool, driven by the sender's
84
+ * secret, and a secondary delegated pool for use by the receiver. Initially,
85
+ * this will have a known, weak "secret" and it is the job of the receiver to
86
+ * use this to then change the keystone to use a secret chosen by the
87
+ * receiver's end.
88
+ */
89
+ export const DEFAULT_SESSION_IDENTITY_INITIAL_DELEGATE_SECRET = ROOT_ADDR;
@@ -14,18 +14,21 @@ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
14
14
  import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
15
15
 
16
16
  import { SyncSagaCoordinator } from './sync-saga-coordinator.mjs';
17
- import { putInSpace, getFromSpace, registerNewIbGib } from '../witness/space/space-helper.mjs';
17
+ import { putInSpace, getFromSpace, registerNewIbGib, getLatestAddrs } from '../witness/space/space-helper.mjs';
18
18
  import { Metaspace_Innerspace } from '../witness/space/metaspace/metaspace-innerspace/metaspace-innerspace.mjs';
19
19
  import { InnerSpace_V1 } from '../witness/space/inner-space/inner-space-v1.mjs';
20
20
  import { createTimelineRootTestHelper, getTestKeystoneServiceHelper } from '../test-helpers.mjs';
21
21
  import { mut8Timeline } from '../timeline/timeline-api.mjs';
22
22
  import { DEFAULT_INNER_SPACE_DATA_V1 } from '../witness/space/inner-space/inner-space-types.mjs';
23
- import { toDto } from '../common/other/ibgib-helper.mjs';
24
23
  import { SyncPeerInnerspace_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
25
24
  import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
26
- import { GetIbGibResult } from '../common/other/other-types.mjs';
27
25
  import { IbGibSpaceAny } from '../witness/space/space-base-v1.mjs';
28
26
  import { getDependencyGraph } from '../common/other/graph-helper.mjs';
27
+ import { fnObs } from '../common/pubsub/observer/observer-helper.mjs';
28
+ import { ErrorIbGib_V1 } from '../common/error/error-types.mjs';
29
+ import { SyncIbGib_V1 } from './sync-types.mjs';
30
+ import { getFullSyncSagaHistory } from './sync-helpers.mjs';
31
+ import { getIbGibsFromCache_fallbackToSpaces } from '../common/other/ibgib-helper.mjs';
29
32
 
30
33
  const logalot = false;
31
34
  const lc = `[sync-innerspace-dest-ahead.respec]`;
@@ -116,7 +119,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
116
119
  return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
117
120
  }
118
121
 
119
- await ifWeMight(sir, 'verify setup', async () => {
122
+ await ifWe(sir, 'verify setup', async () => {
120
123
  // Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
121
124
  // Ensure Source does NOT have V2
122
125
  iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
@@ -150,12 +153,42 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
150
153
  domainIbGibs: [v1], // Source tries to push V1
151
154
  useSessionIdentity: true,
152
155
  });
156
+
157
+ const sublc = `${lc}[updates$]`;
158
+ /**
159
+ * I have added this so you can see how to subscribe to an ibgib
160
+ * observable using {@link fnObs}.
161
+ */
162
+ const subscription = await updates$.subscribe(fnObs({
163
+ next: async (ctxIbGib) => {
164
+ // console.log(`${sublc} next fired. ${JSON.stringify(ctxIbGib)}`);
165
+ console.log(`${sublc} next fired. (I: e68d8894bac8800f9f3430e8a38d6626)`);
166
+ },
167
+ error: async (e: ErrorIbGib_V1) => {
168
+ if (e.data) {
169
+ console.error(`${sublc} error fired. error: ${JSON.stringify(e.data)} (E: eddf17f76a486b9c5a2f4ee86ed38b26)`);
170
+ } else {
171
+ console.dir(e);
172
+ console.error(`${sublc} error fired. error: ${extractErrorMsg(e)} (E: af9c3b6f1c88befeff77ca46111b3826)`);
173
+ }
174
+ },
175
+ complete: async () => {
176
+ console.log(`${sublc} complete fired`);
177
+ },
178
+ }));
153
179
  await done;
154
180
 
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
+
155
188
  // 5. Verify Sync (v2 should be in both source and dest now)
156
189
  console.log(`${lc} Verifying Sync...`);
157
190
 
158
- await ifWeMight(sir, `verify v2 now also in source`, async () => {
191
+ await ifWe(sir, `verify v2 now also in source`, async () => {
159
192
  // Verify Tip (V2)
160
193
 
161
194
  iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
@@ -167,7 +200,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
167
200
 
168
201
  });
169
202
 
170
- await ifWeMight(sir, `dependency graphs the same`, async () => {
203
+ await ifWe(sir, `dependency graphs the same`, async () => {
171
204
 
172
205
  const sourceDepGraph = await getDependencyGraph({
173
206
  ibGibAddr: addrV2,
@@ -196,19 +229,19 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
196
229
  // For now, we'll retrieve from spaces after sync completes
197
230
  let sessionKeystoneAddr: IbGibAddr | undefined;
198
231
 
199
- await ifWeMight(sir, 'IDENTITY: session keystone exists in sender space', async () => {
200
- // Session keystone should be in sender's durable space
201
- // Since we can't enumerate space easily, we verify indirectly:
202
- // The fact that sync completed means keystone was findable
232
+ await ifWe(sir, 'IDENTITY: session keystone exists in sender space', async () => {
233
+ // TODO: Get saga IbGib and access sessionKeystones rel8n
234
+ // Once saga access is implemented (per Bill's guidance), retrieve keystone addr from:
235
+ // const keystoneAddrs = sagaIbGib.rel8ns?.sessionKeystones;
236
+ // Then verify keystone exists in space
203
237
 
204
- // TODO: Capture sessionKeystoneAddr from sync() return value
205
- // For now, placeholder passes
238
+ // Placeholder - test passes because keystone creation works
206
239
  iReckon(sir, true)
207
- .asTo('sync completed (keystone must exist)')
240
+ .asTo('session keystone created (saga access TODO)')
208
241
  .isGonnaBeTrue();
209
242
  });
210
243
 
211
- await ifWeMight(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
244
+ await ifWe(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
212
245
  // Session keystone should be transferred to receiver's durable space
213
246
  iReckon(sir, sessionKeystoneAddr)
214
247
  .asTo('session keystone address was captured')
@@ -222,7 +255,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
222
255
  }
223
256
  });
224
257
 
225
- await ifWeMight(sir, 'IDENTITY: saga frames are signed', async () => {
258
+ await ifWe(sir, 'IDENTITY: saga frames are signed', async () => {
226
259
  // TODO: Get saga frames and check each has a proof
227
260
  // This will FAIL when we actually check - that's the point (TDD RED)
228
261
 
@@ -231,7 +264,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
231
264
  .isGonnaBeTrue();
232
265
  });
233
266
 
234
- await ifWeMight(sir, 'IDENTITY: frame signatures are valid', async () => {
267
+ await ifWe(sir, 'IDENTITY: frame signatures are valid', async () => {
235
268
  // TODO: For each saga frame, validate proof against session keystone
236
269
  // const isValid = await validateProofWithKeystone({
237
270
  // proof: frame.proof,
@@ -246,7 +279,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
246
279
  .isGonnaBeTrue();
247
280
  });
248
281
 
249
- await ifWeMight(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
282
+ await ifWe(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
250
283
  // TODO: Session keystone should evolve after signing frames
251
284
  // This will FAIL because keystone evolution not implemented yet
252
285
 
@@ -255,7 +288,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
255
288
  .isGonnaBeTrue();
256
289
  });
257
290
 
258
- await ifWeMight(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
291
+ await ifWe(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
259
292
  // TODO: Check each frame has timestamp in proof claim
260
293
  // const claim = JSON.parse(frame.proof.claim.scope);
261
294
  // iReckon(sir, claim.timestamp).asTo('has timestamp').isGonnaBeTruthy();
@@ -268,7 +301,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
268
301
  .isGonnaBeTrue();
269
302
  });
270
303
 
271
- await ifWeMight(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
304
+ await ifWe(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
272
305
  if (sessionKeystoneAddr) {
273
306
  const keystoneResult = await getFromSpace({
274
307
  addr: sessionKeystoneAddr,
@@ -293,7 +326,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
293
326
  }
294
327
  });
295
328
 
296
- await ifWeMight(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
329
+ await ifWe(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
297
330
  // Saga frames should NOT have hard links to domain ibgibs
298
331
  // This currently PASSES but will expose issues if hard links exist
299
332
 
@@ -133,13 +133,13 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
133
133
 
134
134
  if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? Concrete class should have initialized sender opts by now. (E: 0b9e28287318fdf8bf9f5a6886a24826)`); }
135
135
 
136
- // NOTE: There are two basic types of peers:
137
- // * local-only (peer)
136
+ // NOTE: There are three basic types of peers:
137
+ // * local-only
138
138
  // * this peer is both sender/receiver peer
139
139
  // * for local merges and relatively fast spaces
140
140
  // * proxy to remote space
141
141
  // * this peer is both sender/receiver peer
142
- // * works directly with remote/outerspaces
142
+ // * works directly with remote/outerspaces via API calls
143
143
  // * Less efficient over-the-wire xfer due to chatiness
144
144
  // * symmetric node sender/receiver peers
145
145
  // * separate sender/receiver classes
@@ -20,33 +20,12 @@ import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
20
20
  import { putInSpace, registerNewIbGib } from '../../witness/space/space-helper.mjs';
21
21
  import { SyncIbGib_V1 } from '../sync-types.mjs';
22
22
  import { validateSyncSagaFrame } from '../sync-helpers.mjs';
23
+ import { validateKeystoneGraph, validateKeystoneTransition } from '../../keystone/keystone-helpers.mjs';
24
+ import { KeystoneService_V1 } from '../../keystone/keystone-service-v1.mjs';
25
+ import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
23
26
 
24
27
  const logalot = GLOBAL_LOG_A_LOT;
25
28
 
26
- /**
27
- * Options for creating a SyncSagaContext ibgib.
28
- */
29
- export interface CreateSyncSagaContextOptions {
30
- /**
31
- * The main saga frame (Init, Ack, etc.).
32
- */
33
- sagaFrame: SyncIbGib_V1;
34
- /**
35
- * Session identity keystones.
36
- */
37
- sessionKeystones?: IbGib_V1[];
38
- /**
39
- * Domain payload ibgibs when the sync saga frame includes actual domain
40
- * payloads to send, e.g., in a Delta frame.
41
- */
42
- payloadIbGibsDomain?: IbGib_V1[];
43
- /**
44
- * we persist the context in the local/sender space (relative to our
45
- * execution POV) right when we create it.
46
- */
47
- localSpace: IbGibSpaceAny;
48
- }
49
-
50
29
  /**
51
30
  * Constructs the standard 'ib' string for a Sync Saga Context stone.
52
31
  */
@@ -117,89 +96,6 @@ export async function parseSyncSagaContextIb({
117
96
  }
118
97
  }
119
98
 
120
- /**
121
- * Creates new SyncSagaContext stone. Puts/registers in {@link localSpace}
122
- * immediately after creation.
123
- *
124
- * @returns The context ibGib.
125
- *
126
- * ## notes
127
- *
128
- * the other ibgibs that are related to this context stone should already be
129
- * put/registered in {@link localSpace}.
130
- */
131
- export async function createSyncSagaContext({
132
- sagaFrame,
133
- sessionKeystones,
134
- payloadIbGibsDomain,
135
- localSpace,
136
- }: CreateSyncSagaContextOptions): Promise<SyncSagaContextIbGib_V1> {
137
- const lc = `[${createSyncSagaContext.name}]`;
138
- try {
139
- if (logalot) { console.log(`${lc} starting... (I: 6b87bee313e811d1d2fc90e87fbec826)`); }
140
-
141
- if (!sagaFrame.data) { throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: 04c49b4cccba6842a8b52e4c6f570726)`); }
142
- if (!sagaFrame.data.n && sagaFrame.data.n !== 0) { throw new Error(`(UNEXPECTED) sagaFrame.data.n falsy and not 0? (E: 45b508da64a8b28428b11765d684b826)`); }
143
-
144
- const date = new Date();
145
- const timestamp = getTimestamp(date);
146
- const timestampMs = date.getMilliseconds();
147
-
148
- const data: SyncSagaContextData_V1 = {
149
- timestamp,
150
- timestampMs,
151
- sagaN: sagaFrame.data.n,
152
- };
153
-
154
- // Domain Payloads
155
- const payloadAddrsDomain = payloadIbGibsDomain ?
156
- payloadIbGibsDomain?.map(x => getIbGibAddr({ ibGib: x })) :
157
- undefined;
158
- if (payloadAddrsDomain && payloadAddrsDomain.length > 0) {
159
- data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] = payloadAddrsDomain;
160
- }
161
-
162
- // rel8ns should always have saga frame, sometimes have keystone
163
- const rel8ns: SyncSagaContextRel8ns_V1 = {
164
- sagaFrame: [getIbGibAddr({ ibGib: sagaFrame })],
165
- };
166
- if (sessionKeystones && sessionKeystones.length > 0) {
167
- rel8ns.sessionKeystone = sessionKeystones.map(x => getIbGibAddr({ ibGib: x }));
168
- }
169
-
170
- // Generate standard ib
171
- const ib = await getSyncSagaContextIb({ data });
172
-
173
- const contextIbGib = await Factory_V1.stone<SyncSagaContextData_V1, SyncSagaContextRel8ns_V1>({
174
- parentPrimitiveIb: SYNC_SAGA_CONTEXT_ATOM,
175
- ib,
176
- data,
177
- rel8ns,
178
- }) as SyncSagaContextIbGib_V1;
179
-
180
- // put/register immediately. Note that contextIbGib at this point is
181
- // pure DTO, i.e., only ib, gib, data, rel8ns props.
182
- await putInSpace({ ibGib: contextIbGib, space: localSpace, });
183
- await registerNewIbGib({
184
- ibGib: contextIbGib,
185
- space: localSpace,
186
- fnBroadcast: undefined,
187
- });
188
-
189
- // Attach actual ibgibs for transport (not pure DTO now)
190
- contextIbGib.sagaFrame = sagaFrame;
191
- if (payloadIbGibsDomain && payloadIbGibsDomain.length > 0) {
192
- contextIbGib.payloadIbGibsDomain = payloadIbGibsDomain;
193
- }
194
-
195
- return contextIbGib;
196
- } catch (error) {
197
- console.error(`${lc} ${extractErrorMsg(error)}`);
198
- throw error;
199
- } finally {
200
- if (logalot) { console.log(`${lc} complete.`); }
201
- }
202
- }
203
99
 
204
100
  /**
205
101
  * Validates ONLY the {@link context} ibgib itself and saga frame/msg stone(s)
@@ -8,6 +8,7 @@ import { IbGibData_V1, IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/ty
8
8
  import { SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
9
9
  import { SyncIbGib_V1 } from '../sync-types.mjs';
10
10
  import { SYNC_SAGA_CONTEXT_ATOM } from './sync-saga-context-constants.mjs';
11
+ import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
11
12
 
12
13
  export interface SyncSagaContextIb_V1 {
13
14
  atom: typeof SYNC_SAGA_CONTEXT_ATOM;
@@ -49,13 +50,21 @@ export interface SyncSagaContextRel8ns_V1 extends IbGibRel8ns_V1 {
49
50
  sagaFrame: IbGibAddr[];
50
51
 
51
52
  /**
52
- * The Ephemeral Session Keystone Identity used for this saga.
53
- * Required for validating the saga frame signature.
53
+ * The Ephemeral Session Keystone Identity used for this saga. Required for
54
+ * validating the saga frame and this context.
55
+ *
56
+ * WARNING!!!: THIS DOES NOT POINT TO THE CURRENT SESSION KEYSTONE IN
57
+ * {@link SyncSagaContextIbGib_V1.signedSessionKeystone}. This points to the
58
+ * PREVIOUS FRAME (immediate past) of that frame. That session keystone
59
+ * signs with THIS context's frame as its target, so it is logically
60
+ * impossible because the hash would be different.
54
61
  *
55
62
  * ## notes
56
63
  *
57
- * This will be different for the sender and receiver, yes? hmm...
58
- * I think I need to put "sender" or "receiver" in the session keystone ib.
64
+ * ATOW (02/18/2026), this is a single address that will have a primary pool
65
+ * for the sender and a delegated pool for the receiver.
66
+ *
67
+ * @see {@link SyncSagaContextIbGib_V1.signedSessionKeystone}
59
68
  */
60
69
  sessionKeystone?: IbGibAddr[];
61
70
  }
@@ -79,4 +88,16 @@ export interface SyncSagaContextIbGib_V1 extends IbGib_V1<SyncSagaContextData_V1
79
88
  * This frame's addr should be {@link SyncSagaContextRel8ns_V1.sagaFrame}.
80
89
  */
81
90
  sagaFrame: SyncIbGib_V1;
91
+
92
+ /**
93
+ * If session keystone is in play, then this will be populated with that
94
+ * keystone. This session keystone will point to the this context ibgib,
95
+ * BUT, this context ibgib will point to the **PREVIOUS** frame of the
96
+ * keystone.
97
+ *
98
+ * So in order to verify this context ibgib, we must verify the keystone
99
+ * points to this context ibgib AND that this context ibgib points to the
100
+ * previous frame of the keystone.
101
+ */
102
+ signedSessionKeystone?: KeystoneIbGib_V1;
82
103
  }