@ibgib/core-gib 0.1.43 → 0.1.44

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 (74) 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 +4 -4
  24. package/dist/keystone/keystone-helpers.d.mts.map +1 -1
  25. package/dist/keystone/keystone-helpers.mjs +8 -5
  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-saga-coordinator.d.mts +22 -11
  47. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  48. package/dist/sync/sync-saga-coordinator.mjs +120 -27
  49. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  50. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -7
  51. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  52. package/dist/sync/sync-types.d.mts +11 -0
  53. package/dist/sync/sync-types.d.mts.map +1 -1
  54. package/dist/sync/sync-types.mjs.map +1 -1
  55. package/package.json +1 -1
  56. package/src/keystone/README.md +4 -3
  57. package/src/keystone/docs/architecture.md +3 -1
  58. package/src/keystone/kdf/kdf-constants.mts +34 -0
  59. package/src/keystone/kdf/kdf-helpers.mts +105 -0
  60. package/src/keystone/kdf/kdf-types.mts +58 -0
  61. package/src/keystone/keystone-config-builder.mts +170 -47
  62. package/src/keystone/keystone-config-builder.respec.mts +21 -14
  63. package/src/keystone/keystone-constants.mts +21 -2
  64. package/src/keystone/keystone-helpers.mts +19 -14
  65. package/src/keystone/keystone-service-v1.mts +23 -22
  66. package/src/keystone/keystone-service-v1.respec.mts +71 -44
  67. package/src/keystone/keystone-types.mts +37 -23
  68. package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +9 -13
  69. package/src/sync/sync-constants.mts +12 -0
  70. package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +53 -20
  71. package/src/sync/sync-saga-coordinator.mts +156 -31
  72. package/src/sync/sync-saga-message/sync-saga-message-types.mts +1 -7
  73. package/src/sync/sync-types.mts +12 -0
  74. package/tmp.md +0 -274
@@ -16,13 +16,16 @@ import { IbGibAddr } from "@ibgib/ts-gib/dist/types.mjs";
16
16
  import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
17
17
  import { IbGibSpaceAny } from "../witness/space/space-base-v1.mjs";
18
18
  import { putInSpace, getLatestAddrs, getFromSpace, registerNewIbGib } from "../witness/space/space-helper.mjs";
19
- import { KeystoneIbGib_V1 } from "../keystone/keystone-types.mjs";
19
+ import { KeystoneIbGib_V1, KeystonePoolConfig_HashV1 } from "../keystone/keystone-types.mjs";
20
20
  import { KeystoneService_V1 } from "../keystone/keystone-service-v1.mjs";
21
+ import { deriveKey } from "../keystone/kdf/kdf-helpers.mjs";
22
+ import { KdfStrategy } from "../keystone/kdf/kdf-constants.mjs";
21
23
  import { MetaspaceService } from "../witness/space/metaspace/metaspace-types.mjs";
22
24
  import {
23
25
  SyncStage, SYNC_ATOM, SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN,
24
26
  SyncConflictStrategy,
25
27
  SYNC_CONFLICT_STRATEGY_VALID_VALUES,
28
+ DEFAULT_SESSION_IDENTITY_INITIAL_DELEGATE_SECRET,
26
29
  } from "./sync-constants.mjs";
27
30
  import {
28
31
  appendToTimeline, createTimeline, getHistory, getHistoryAddrs, Rel8nInfo, Rel8nRemovalInfo
@@ -60,6 +63,7 @@ import { graftTimelines, } from "./graft-info/graft-info-helpers.mjs";
60
63
  import { GRAFT_INFO_REL8N_NAME } from "./graft-info/graft-info-constants.mjs";
61
64
  import { GraftInfoIbGib_V1 } from "./graft-info/graft-info-types.mjs";
62
65
  import { validateIbGibIntrinsically } from "@ibgib/ts-gib/dist/V1/validate-helper.mjs";
66
+ import { KEYSTONE_VERB_MANAGE } from "../keystone/keystone-constants.mjs";
63
67
 
64
68
 
65
69
  const logalot = GLOBAL_LOG_A_LOT;
@@ -94,18 +98,14 @@ export class SyncSagaCoordinator {
94
98
  * @remarks
95
99
  * **Execution Context**: **Sender (Local)**.
96
100
  * This method is the entry point for starting a sync session.
97
- *
98
- * @param opts.peer - The remote peer witness to communicate with.
99
- * @param opts.localSpace - The local space that will be read from and written to.
100
- * @param opts.metaspace - Service for creating temp spaces and managing ibgibs.
101
- * @param opts.domainIbGibs - The root ibgibs defining the scope of the sync.
102
- * @param opts.useSessionIdentity - (Optional) Whether to create an ephemeral session identity. Default: true.
103
101
  */
104
102
  public async sync({
105
103
  peer,
106
104
  domainIbGibs,
107
105
  conflictStrategy = SyncConflictStrategy.abort,
108
106
  useSessionIdentity = true,
107
+ identity,
108
+ identitySecret,
109
109
  metaspace,
110
110
  localSpace,
111
111
  }: {
@@ -121,7 +121,8 @@ export class SyncSagaCoordinator {
121
121
  */
122
122
  domainIbGibs: IbGib_V1[],
123
123
  /**
124
- * The space containing the {@link domainIbGibs} we want to sync.
124
+ * The space containing the {@link domainIbGibs} we want to sync. If
125
+ * sync is successful, any updates to timelines will be stored here.
125
126
  */
126
127
  localSpace: IbGibSpaceAny;
127
128
  /**
@@ -129,11 +130,17 @@ export class SyncSagaCoordinator {
129
130
  */
130
131
  metaspace: MetaspaceService;
131
132
  /**
132
- * The identity authorizing this sync.
133
+ * The primary (i.e. non-session) identity authorizing this sync.
134
+ *
135
+ * If this is truthy, then {@link identitySecret} must also be provided.
133
136
  */
134
137
  identity?: KeystoneIbGib_V1;
135
138
  /**
136
139
  * The secret for the identity (to sign the commit).
140
+ *
141
+ * If provided, this will drive both signing {@link identity} keystone
142
+ * (if provided) AND session keystone (if {@link useSessionIdentity} is
143
+ * true).
137
144
  */
138
145
  identitySecret?: string;
139
146
  /**
@@ -144,8 +151,10 @@ export class SyncSagaCoordinator {
144
151
  */
145
152
  conflictStrategy?: SyncConflictStrategy;
146
153
  /**
147
- * If true, creates an ephemeral session identity for the sync process to
148
- * secure the sync transaction itself.
154
+ * If true, creates an ephemeral session identity for the sync process
155
+ * to secure the sync transaction itself.
156
+ *
157
+ * If this is true, {@link identitySecret} must also be provided.
149
158
  *
150
159
  * @default true
151
160
  */
@@ -196,9 +205,13 @@ export class SyncSagaCoordinator {
196
205
  try {
197
206
 
198
207
  // BOOTSTRAP IDENTITY (Session Keystone)
199
- const sessionIdentity = useSessionIdentity
200
- ? await this.getSessionIdentity({ sagaId, metaspace, localSpace })
201
- : undefined;
208
+ let sessionIdentity: KeystoneIbGib_V1 | undefined = undefined;
209
+
210
+ if (useSessionIdentity) {
211
+ if (!identitySecret) { throw new Error(`useSessionIdentity is true, but identitySecret is falsy. Must provide a secret if you want to use a session identity. (E: 81915860c4dd3ea4dfd81825fa74c126)`); }
212
+ sessionIdentity = await this.getSessionIdentity({ sagaId, identitySecret, metaspace, localSpace });
213
+ }
214
+
202
215
  // if (logalot) { console.log(`${lc} sessionIdentity: ${sessionIdentity ? pretty(sessionIdentity) : 'undefined'} (I: abc01872800b3a66b819a05898bba826)`); }
203
216
 
204
217
  // CREATE INITIAL FRAME (Stage.init)
@@ -214,6 +227,7 @@ export class SyncSagaCoordinator {
214
227
  await this.executeSagaLoop({
215
228
  initFrame, initDomainGraph,
216
229
  peer,
230
+ identitySecret,
217
231
  sessionIdentity,
218
232
  updates$,
219
233
  localSpace,
@@ -266,7 +280,13 @@ export class SyncSagaCoordinator {
266
280
  * Local temp space relative to the execution context's POV
267
281
  */
268
282
  myTempSpace: IbGibSpaceAny,
283
+ /**
284
+ * @see {@link sync} `identity` param.
285
+ */
269
286
  identity?: KeystoneIbGib_V1,
287
+ /**
288
+ * @see {@link sync} `identitySecret` param.
289
+ */
270
290
  identitySecret?: string,
271
291
  metaspace: MetaspaceService,
272
292
  }): Promise<SyncSagaContextIbGib_V1 | null> {
@@ -279,7 +299,6 @@ export class SyncSagaCoordinator {
279
299
  mySpace,
280
300
  myTempSpace,
281
301
  identity,
282
- identitySecret,
283
302
  metaspace,
284
303
  });
285
304
 
@@ -325,12 +344,74 @@ export class SyncSagaCoordinator {
325
344
  }
326
345
  }
327
346
 
347
+ private async getSessionSecret({
348
+ sagaId,
349
+ identitySecret,
350
+ }: {
351
+ sagaId: string,
352
+ identitySecret: string,
353
+ }): Promise<string> {
354
+ const lc = `${this.lc}[${this.getSessionSecret.name}]`;
355
+ try {
356
+ if (logalot) { console.log(`${lc} starting... (I: 0de03f8dcd3e32f1fca244e8f2a8a826)`); }
357
+
358
+ // Derive session-specific secret using KDF
359
+ const sessionSecret = await deriveKey({
360
+ masterSecret: identitySecret,
361
+ kdfOpts: {
362
+ strategy: KdfStrategy.recursive_salt_wrap,
363
+ salt: sagaId,
364
+ rounds: 10000,
365
+ algorithm: 'SHA-256'
366
+ }
367
+ });
368
+
369
+ return sessionSecret;
370
+ } catch (error) {
371
+ console.error(`${lc} ${extractErrorMsg(error)}`);
372
+ throw error;
373
+ } finally {
374
+ if (logalot) { console.log(`${lc} complete.`); }
375
+ }
376
+ }
377
+
378
+ private async getInitialWeakDelegateSessionSecret({
379
+ sagaId,
380
+ }: {
381
+ sagaId: string,
382
+ }): Promise<string> {
383
+ const lc = `${this.lc}[${this.getInitialWeakDelegateSessionSecret.name}]`;
384
+ try {
385
+ if (logalot) { console.log(`${lc} starting... (I: 872ab81a78827b9f2822b78459203226)`); }
386
+
387
+ // Create delegate pool bootstrap secret (publicly derivable)
388
+ const initialDelegateSecret = await deriveKey({
389
+ masterSecret: DEFAULT_SESSION_IDENTITY_INITIAL_DELEGATE_SECRET, // Weak, publicly derivable secret
390
+ kdfOpts: {
391
+ strategy: KdfStrategy.recursive_salt_wrap,
392
+ salt: sagaId,
393
+ rounds: 1, // Minimal rounds - this is meant to be weak
394
+ algorithm: 'SHA-256'
395
+ }
396
+ });
397
+
398
+ return initialDelegateSecret;
399
+ } catch (error) {
400
+ console.error(`${lc} ${extractErrorMsg(error)}`);
401
+ throw error;
402
+ } finally {
403
+ if (logalot) { console.log(`${lc} complete.`); }
404
+ }
405
+ }
406
+
328
407
  private async getSessionIdentity({
329
408
  sagaId,
409
+ identitySecret,
330
410
  metaspace,
331
411
  localSpace,
332
412
  }: {
333
413
  sagaId: string,
414
+ identitySecret: string,
334
415
  metaspace: MetaspaceService,
335
416
  localSpace: IbGibSpaceAny,
336
417
  }): Promise<KeystoneIbGib_V1> {
@@ -338,20 +419,59 @@ export class SyncSagaCoordinator {
338
419
  try {
339
420
  if (logalot) { console.log(`${lc} starting... (I: 428392a4ee636b7bd8f7d5d89a87e826)`); }
340
421
 
341
- const config: any = {
342
- id: 'default',
422
+ if (!identitySecret) { throw new Error(`(UNEXPECTED) identitySecret falsy? This is expected to be truthy by this point. (E: 8ce053fe59825a6678713128953b9d26)`); }
423
+
424
+ const sessionSecret = await this.getSessionSecret({ sagaId, identitySecret });
425
+
426
+ const init = await this.getInitialWeakDelegateSessionSecret({ sagaId });
427
+
428
+
429
+ // Create TWO pool configs: Primary (strong) + Delegate (weak bootstrap)
430
+ const primaryPoolConfig: KeystonePoolConfig_HashV1 = {
431
+ allowedVerbs: [KEYSTONE_VERB_MANAGE],
432
+ id: 'primary',
433
+ type: 'hash-reveal-v1',
434
+ salt: sagaId,
435
+ behavior: {
436
+ size: 100, // Large pool for many signatures
437
+ replenish: 'top-up',
438
+ selectSequentially: 2,
439
+ selectRandomly: 2,
440
+ targetBindingChars: 10
441
+ },
442
+ algo: 'SHA-256',
443
+ rounds: 1
444
+ };
445
+
446
+ const delegatePoolConfig: any = {
447
+ id: 'delegate',
343
448
  type: 'hash-reveal-v1',
344
449
  salt: sagaId,
345
- behavior: { size: 10, replenish: 'top-up', selectSequentially: 1, selectRandomly: 1, targetBindingChars: 0 },
346
- algo: 'SHA-256', rounds: 1
450
+ behavior: {
451
+ size: 10, // Small pool - only for initial handshake
452
+ replenish: 'top-up',
453
+ selectSequentially: 1,
454
+ selectRandomly: 1,
455
+ targetBindingChars: 0
456
+ },
457
+ algo: 'SHA-256',
458
+ rounds: 1
347
459
  };
460
+
461
+ // Generate keystone with DUAL pools. We have to first genesis with
462
+ // one and then add the other, because we have two distinct
463
+ // secrets.
348
464
  const sessionIdentity = await this.keystone.genesis({
349
- masterSecret: sagaId,
350
- configs: [config],
465
+ masterSecret: sessionSecret,
466
+ configs: [primaryPoolConfig],
351
467
  metaspace,
352
- space: localSpace // ✅ FIXED: Use durable space, not temp space
468
+ space: localSpace
353
469
  });
354
470
 
471
+ // TODO: Store delegate pool separate challenges derived from bootstrap secret
472
+ // This allows receiver to verify/evolve the delegate pool
473
+ // For now, the keystone genesis with multiple configs handles this
474
+
355
475
  return sessionIdentity;
356
476
  } catch (error) {
357
477
  console.error(`${lc} ${extractErrorMsg(error)}`);
@@ -381,6 +501,7 @@ export class SyncSagaCoordinator {
381
501
  initDomainGraph,
382
502
  peer,
383
503
  sessionIdentity,
504
+ identitySecret,
384
505
  updates$,
385
506
  localSpace,
386
507
  tempSpace,
@@ -396,6 +517,10 @@ export class SyncSagaCoordinator {
396
517
  initDomainGraph: FlatIbGibGraph,
397
518
  peer: SyncPeerWitness,
398
519
  sessionIdentity?: KeystoneIbGib_V1,
520
+ /**
521
+ * if {@link sessionIdentity} provided, this must also be truthy
522
+ */
523
+ identitySecret?: string,
399
524
  updates$: SubjectWitness<SyncSagaContextIbGib_V1>,
400
525
  metaspace: MetaspaceService
401
526
  localSpace: IbGibSpaceAny,
@@ -755,7 +880,7 @@ export class SyncSagaCoordinator {
755
880
  const sagaFrame = await this.evolveSyncSagaIbGib({
756
881
  msgStones: [initStone],
757
882
  conflictStrategy,
758
- sessionIdentity: sessionIdentity,
883
+ sessionIdentity,
759
884
  metaspace,
760
885
  localSpace,
761
886
  });
@@ -873,7 +998,6 @@ export class SyncSagaCoordinator {
873
998
  mySpace,
874
999
  myTempSpace,
875
1000
  identity,
876
- identitySecret,
877
1001
  metaspace,
878
1002
  }: {
879
1003
  sagaContext: SyncSagaContextIbGib_V1,
@@ -893,7 +1017,6 @@ export class SyncSagaCoordinator {
893
1017
  */
894
1018
  myTempSpace: IbGibSpaceAny,
895
1019
  identity?: KeystoneIbGib_V1,
896
- identitySecret?: string,
897
1020
  metaspace: MetaspaceService,
898
1021
  }): Promise<HandleSagaResponseContextResult> {
899
1022
  const lc = `${this.lc}[${this.handleResponseSagaContext.name}]`;
@@ -916,7 +1039,7 @@ export class SyncSagaCoordinator {
916
1039
  sagaIbGib,
917
1040
  messageData: messageData as SyncSagaMessageInitData_V1,
918
1041
  metaspace, mySpace, myTempSpace,
919
- identity, identitySecret
1042
+ identity,
920
1043
  });
921
1044
  break;
922
1045
 
@@ -987,7 +1110,6 @@ export class SyncSagaCoordinator {
987
1110
  myTempSpace,
988
1111
  metaspace,
989
1112
  identity,
990
- // identitySecret,
991
1113
  }: {
992
1114
  sagaIbGib: SyncIbGib_V1,
993
1115
  messageData: SyncSagaMessageInitData_V1,
@@ -1004,7 +1126,6 @@ export class SyncSagaCoordinator {
1004
1126
  myTempSpace: IbGibSpaceAny,
1005
1127
  metaspace: MetaspaceService,
1006
1128
  identity?: KeystoneIbGib_V1,
1007
- identitySecret?: string,
1008
1129
  }): Promise<NextSagaFrameInfo> {
1009
1130
  const lc = `${this.lc}[${this.handleInitFrame.name}]`;
1010
1131
  try {
@@ -2530,10 +2651,9 @@ export class SyncSagaCoordinator {
2530
2651
  localSpace: IbGibSpaceAny,
2531
2652
  metaspace: MetaspaceService,
2532
2653
  /**
2533
- * does NOT evolve the keystone. this should be done by the caller.
2534
- * (NOT IMPLEMENTED YET ANYWAY)
2654
+ * does NOT evolve the keystone.
2535
2655
  */
2536
- sessionIdentity?: KeystoneIbGib_V1,
2656
+ sessionIdentity: KeystoneIbGib_V1 | undefined,
2537
2657
  }): Promise<SyncIbGib_V1> {
2538
2658
  const lc = `${this.lc}[${this.evolveSyncSagaIbGib.name}]`;
2539
2659
  try {
@@ -2617,6 +2737,11 @@ export class SyncSagaCoordinator {
2617
2737
  const rel8ns: SyncRel8ns_V1 = { [SYNC_MSG_REL8N_NAME]: stoneAddrs, };
2618
2738
  if (identityAddr) { rel8ns.identity = [identityAddr]; }
2619
2739
 
2740
+ // Attach session keystone to saga frame via hard rel8n
2741
+ if (sessionIdentity) {
2742
+ rel8ns.sessionKeystones = [getIbGibAddr({ ibGib: sessionIdentity })];
2743
+ }
2744
+
2620
2745
  const resNew = await createTimeline({
2621
2746
  space: localSpace,
2622
2747
  metaspace,
@@ -55,7 +55,7 @@ export interface SyncSagaMessageIbGib_V1 extends IbGib_V1<SyncSagaMessageData_V1
55
55
  /**
56
56
  * The "Hello" of the sync protocol.
57
57
  *
58
- * Exchanges knowledge maps (what I have) and identity (who I am).
58
+ * Exchanges knowledge maps (what I have).
59
59
  */
60
60
  export interface SyncSagaMessageInitData_V1 extends SyncSagaMessageData_V1 {
61
61
  stage: typeof SyncStage.init;
@@ -68,12 +68,6 @@ export interface SyncSagaMessageInitData_V1 extends SyncSagaMessageData_V1 {
68
68
  */
69
69
  knowledgeMap: { [tjp: string]: IbGibAddr };
70
70
 
71
- /**
72
- * The Keystone Identity of the sender.
73
- * Required for the first handshake or if the receiver doesn't know the sender.
74
- */
75
- identity?: KeystoneIbGib_V1;
76
-
77
71
  /**
78
72
  * What the sender wants to do.
79
73
  * e.g. "push" (I have data for you) or "pull" (Give me data).
@@ -195,6 +195,18 @@ export interface SyncRel8ns_V1 extends IbGibRel8ns_V1 {
195
195
  */
196
196
  identity?: string[];
197
197
 
198
+ /**
199
+ * Session keystones used for signing saga frames.
200
+ *
201
+ * Array contains addresses of keystone evolution chain:
202
+ * - Index 0: Genesis keystone (dual-pool architecture)
203
+ * - Index N: Latest evolved keystone after signing operations
204
+ *
205
+ * Each sync endpoint retrieves the session keystone from this rel8n
206
+ * rather than searching spaces. Keystones are stored in durable spaces.
207
+ */
208
+ sessionKeystones?: IbGibAddr[];
209
+
198
210
  /**
199
211
  * The message stone that contains the information about the particular
200
212
  * stage of the sync process we are in.