@ibgib/core-gib 0.1.62 → 0.1.63

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 (86) hide show
  1. package/dist/keystone/keystone-service-v1.d.mts +2 -1
  2. package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
  3. package/dist/keystone/keystone-service-v1.mjs +3 -1
  4. package/dist/keystone/keystone-service-v1.mjs.map +1 -1
  5. package/dist/keystone/keystone-service-v1.respec.mjs +63 -45
  6. package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
  7. package/dist/keystone/keystone-types.d.mts +5 -0
  8. package/dist/keystone/keystone-types.d.mts.map +1 -1
  9. package/dist/keystone/policy/keystone-profile-builder.d.mts +1 -1
  10. package/dist/keystone/policy/keystone-profile-builder.d.mts.map +1 -1
  11. package/dist/keystone/policy/keystone-profile-builder.mjs +8 -0
  12. package/dist/keystone/policy/keystone-profile-builder.mjs.map +1 -1
  13. package/dist/keystone/policy/profiles/profile-domain.json +84 -0
  14. package/dist/keystone/policy/profiles/profile-sync.json +84 -0
  15. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts +8 -0
  16. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts.map +1 -1
  17. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs +15 -1
  18. package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs.map +1 -1
  19. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs +16 -4
  20. package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs.map +1 -1
  21. package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs +4 -1
  22. package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs.map +1 -1
  23. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs +4 -1
  24. package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs.map +1 -1
  25. package/dist/sync/sync-conflict-text-merge.withid.respec.mjs +10 -4
  26. package/dist/sync/sync-conflict-text-merge.withid.respec.mjs.map +1 -1
  27. package/dist/sync/sync-innerspace-constants.withid.respec.mjs +12 -3
  28. package/dist/sync/sync-innerspace-constants.withid.respec.mjs.map +1 -1
  29. package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs +4 -1
  30. package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs.map +1 -1
  31. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs +4 -1
  32. package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs.map +1 -1
  33. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs +4 -1
  34. package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs.map +1 -1
  35. package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs +4 -1
  36. package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs.map +1 -1
  37. package/dist/sync/sync-innerspace.withid.respec.mjs +4 -1
  38. package/dist/sync/sync-innerspace.withid.respec.mjs.map +1 -1
  39. package/dist/sync/sync-peer/sync-peer-types.d.mts +4 -0
  40. package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
  41. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  42. package/dist/sync/sync-peer/sync-peer-v1.mjs +4 -1
  43. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  44. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -1
  45. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +90 -22
  46. package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -1
  47. package/dist/sync/sync-saga-coordinator.d.mts +7 -10
  48. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  49. package/dist/sync/sync-saga-coordinator.mjs +14 -5
  50. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  51. package/dist/sync/sync-types.d.mts +5 -0
  52. package/dist/sync/sync-types.d.mts.map +1 -1
  53. package/dist/sync/sync-types.mjs.map +1 -1
  54. package/dist/sync/sync-withid.connect.respec.mjs +4 -1
  55. package/dist/sync/sync-withid.connect.respec.mjs.map +1 -1
  56. package/dist/sync/sync-withid.establish.respec.mjs +4 -1
  57. package/dist/sync/sync-withid.establish.respec.mjs.map +1 -1
  58. package/dist/sync/sync-withid.pingpong.respec.mjs +4 -1
  59. package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -1
  60. package/package.json +1 -1
  61. package/src/keystone/keystone-service-v1.mts +5 -1
  62. package/src/keystone/keystone-service-v1.respec.mts +67 -46
  63. package/src/keystone/keystone-types.mts +5 -0
  64. package/src/keystone/policy/keystone-profile-builder.mts +9 -1
  65. package/src/keystone/policy/profiles/profile-domain.json +84 -0
  66. package/src/keystone/policy/profiles/profile-sync.json +84 -0
  67. package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +20 -1
  68. package/src/sync/sync-conflict-adv-multitimelines.withid.respec.mts +16 -4
  69. package/src/sync/sync-conflict-basic-divergence.withid.respec.mts +4 -1
  70. package/src/sync/sync-conflict-basic-multitimelines.withid.respec.mts +4 -1
  71. package/src/sync/sync-conflict-text-merge.withid.respec.mts +10 -4
  72. package/src/sync/sync-innerspace-constants.withid.respec.mts +12 -3
  73. package/src/sync/sync-innerspace-deep-updates.withid.respec.mts +4 -1
  74. package/src/sync/sync-innerspace-dest-ahead.withid.respec.mts +4 -1
  75. package/src/sync/sync-innerspace-multiple-timelines.withid.respec.mts +4 -1
  76. package/src/sync/sync-innerspace-partial-update.withid.respec.mts +4 -1
  77. package/src/sync/sync-innerspace.withid.respec.mts +4 -1
  78. package/src/sync/sync-peer/sync-peer-types.mts +4 -0
  79. package/src/sync/sync-peer/sync-peer-v1.mts +5 -1
  80. package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +96 -22
  81. package/src/sync/sync-saga-coordinator.mts +17 -12
  82. package/src/sync/sync-types.mts +6 -0
  83. package/src/sync/sync-withid.connect.respec.mts +5 -2
  84. package/src/sync/sync-withid.establish.respec.mts +4 -1
  85. package/src/sync/sync-withid.pingpong.respec.mts +4 -1
  86. package/src/sync/unused-identity-backup.mts.md +0 -311
@@ -0,0 +1,84 @@
1
+ {
2
+ "$schema": "../schemas/keystone.high.schema.json",
3
+ "metadata": {
4
+ "name": "Domain Identity Profile",
5
+ "securityLevel": "high"
6
+ },
7
+ "pools": {
8
+ "sync": {
9
+ "id": "sync",
10
+ "allowedVerbs": [
11
+ "sync"
12
+ ],
13
+ "algo": "SHA-512",
14
+ "rounds": 4,
15
+ "behavior": {
16
+ "size": 2000,
17
+ "replenish": "top-up",
18
+ "selectSequentially": 10,
19
+ "selectRandomly": 10,
20
+ "targetBindingCount": 16
21
+ }
22
+ },
23
+ "manage": {
24
+ "id": "manage",
25
+ "allowedVerbs": [
26
+ "manage"
27
+ ],
28
+ "algo": "SHA-512",
29
+ "rounds": 6,
30
+ "behavior": {
31
+ "size": 2000,
32
+ "replenish": "replace-all",
33
+ "selectSequentially": 12,
34
+ "selectRandomly": 12,
35
+ "targetBindingCount": 16
36
+ }
37
+ },
38
+ "revoke": {
39
+ "id": "revoke",
40
+ "allowedVerbs": [
41
+ "revoke"
42
+ ],
43
+ "algo": "SHA-512",
44
+ "rounds": 20,
45
+ "behavior": {
46
+ "size": 2000,
47
+ "replenish": "delete-all",
48
+ "selectSequentially": 50,
49
+ "selectRandomly": 50,
50
+ "targetBindingCount": 0
51
+ }
52
+ },
53
+ "connect": {
54
+ "id": "connect",
55
+ "allowedVerbs": [
56
+ "connect"
57
+ ],
58
+ "algo": "SHA-512",
59
+ "rounds": 4,
60
+ "behavior": {
61
+ "size": 2000,
62
+ "replenish": "top-up",
63
+ "selectSequentially": 10,
64
+ "selectRandomly": 10,
65
+ "targetBindingCount": 16
66
+ }
67
+ },
68
+ "sign": {
69
+ "id": "default",
70
+ "allowedVerbs": [
71
+ "sign"
72
+ ],
73
+ "algo": "SHA-512",
74
+ "rounds": 4,
75
+ "behavior": {
76
+ "size": 2000,
77
+ "replenish": "top-up",
78
+ "selectSequentially": 10,
79
+ "selectRandomly": 10,
80
+ "targetBindingCount": 16
81
+ }
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "$schema": "../schemas/keystone.low.schema.json",
3
+ "metadata": {
4
+ "name": "Sync Delegate Profile",
5
+ "securityLevel": "low"
6
+ },
7
+ "pools": {
8
+ "sync": {
9
+ "id": "sync",
10
+ "allowedVerbs": [
11
+ "sync"
12
+ ],
13
+ "algo": "SHA-256",
14
+ "rounds": 1,
15
+ "behavior": {
16
+ "size": 100,
17
+ "replenish": "top-up",
18
+ "selectSequentially": 3,
19
+ "selectRandomly": 3,
20
+ "targetBindingCount": 8
21
+ }
22
+ },
23
+ "manage": {
24
+ "id": "manage",
25
+ "allowedVerbs": [
26
+ "manage"
27
+ ],
28
+ "algo": "SHA-256",
29
+ "rounds": 2,
30
+ "behavior": {
31
+ "size": 100,
32
+ "replenish": "replace-all",
33
+ "selectSequentially": 3,
34
+ "selectRandomly": 3,
35
+ "targetBindingCount": 8
36
+ }
37
+ },
38
+ "revoke": {
39
+ "id": "revoke",
40
+ "allowedVerbs": [
41
+ "revoke"
42
+ ],
43
+ "algo": "SHA-256",
44
+ "rounds": 5,
45
+ "behavior": {
46
+ "size": 100,
47
+ "replenish": "delete-all",
48
+ "selectSequentially": 3,
49
+ "selectRandomly": 3,
50
+ "targetBindingCount": 0
51
+ }
52
+ },
53
+ "connect": {
54
+ "id": "connect",
55
+ "allowedVerbs": [
56
+ "connect"
57
+ ],
58
+ "algo": "SHA-256",
59
+ "rounds": 1,
60
+ "behavior": {
61
+ "size": 100,
62
+ "replenish": "top-up",
63
+ "selectSequentially": 3,
64
+ "selectRandomly": 3,
65
+ "targetBindingCount": 8
66
+ }
67
+ },
68
+ "sign": {
69
+ "id": "default",
70
+ "allowedVerbs": [
71
+ "sign"
72
+ ],
73
+ "algo": "SHA-256",
74
+ "rounds": 2,
75
+ "behavior": {
76
+ "size": 100,
77
+ "replenish": "top-up",
78
+ "selectSequentially": 3,
79
+ "selectRandomly": 3,
80
+ "targetBindingCount": 8
81
+ }
82
+ }
83
+ }
84
+ }
@@ -1,4 +1,4 @@
1
- import { hash } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
1
+ import { hash, HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
2
 
3
3
  import { KeystoneStrategy } from '../keystone-strategy.mjs';
4
4
  import {
@@ -140,3 +140,22 @@ export class KeystoneStrategy_HashRevealV1 extends KeystoneStrategy<
140
140
  }
141
141
  }
142
142
  }
143
+
144
+ /**
145
+ * Derives a delegate secret from the parent's masterSecret using KDF.
146
+ * Salt is the sha512 hash of the masterSecret.
147
+ * Number of rounds is hardcoded to 1000.
148
+ */
149
+ export async function deriveDelegateSecret({
150
+ masterSecret,
151
+ }: {
152
+ masterSecret: string;
153
+ }): Promise<string> {
154
+ const salt = await hash({ s: masterSecret, algorithm: HashAlgorithm.sha_512 });
155
+ return await kdf_recursiveSaltWrap({
156
+ masterSecret,
157
+ salt,
158
+ rounds: 1000,
159
+ algorithm: HashAlgorithm.sha_512
160
+ });
161
+ }
@@ -178,7 +178,10 @@ await respecfully(sir, `Multi-round/timeline permutations with Identity`, async
178
178
  metaspace,
179
179
  domainIbGibs: [r1_alpha_v1_source_common.ibGib],
180
180
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
181
- senderIdentity: senderIdentityLatestSource,
181
+ senderIdentityInfo: {
182
+ senderIdentity: senderIdentityLatestSource,
183
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
184
+ },
182
185
  fnSenderSecret: async () => SENDER_SECRET,
183
186
  });
184
187
 
@@ -300,7 +303,10 @@ await respecfully(sir, `Multi-round/timeline permutations with Identity`, async
300
303
  metaspace,
301
304
  domainIbGibs: [r2_alpha_v3_source_rel8dBeta.ibGib],
302
305
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
303
- senderIdentity: senderIdentityLatestSource,
306
+ senderIdentityInfo: {
307
+ senderIdentity: senderIdentityLatestSource,
308
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
309
+ },
304
310
  fnSenderSecret: async () => SENDER_SECRET,
305
311
  });
306
312
  await r2_syncSaga.done;
@@ -449,7 +455,10 @@ await respecfully(sir, `Multi-round/timeline permutations with Identity`, async
449
455
  metaspace,
450
456
  domainIbGibs: [r3_alpha_v4_source_mut8fieldC.ibGib, r3_beta_v1_source.ibGib],
451
457
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
452
- senderIdentity: senderIdentityLatestSource,
458
+ senderIdentityInfo: {
459
+ senderIdentity: senderIdentityLatestSource,
460
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
461
+ },
453
462
  fnSenderSecret: async () => SENDER_SECRET,
454
463
  });
455
464
  await r3_syncSaga.done;
@@ -625,7 +634,10 @@ await respecfully(sir, `Multi-round/timeline permutations with Identity`, async
625
634
  metaspace,
626
635
  domainIbGibs: [r4_alpha_v7_source.ibGib, r4_gamma_v0_source.ibGib, r4_beta_v2_source.ibGib],
627
636
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
628
- senderIdentity: senderIdentityLatestSource,
637
+ senderIdentityInfo: {
638
+ senderIdentity: senderIdentityLatestSource,
639
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
640
+ },
629
641
  fnSenderSecret: async () => SENDER_SECRET,
630
642
  });
631
643
  await r4_syncSaga.done;
@@ -221,7 +221,10 @@ await respecfully(sir, `Sync Conflict Basic Divergence with Identity`, async ()
221
221
  metaspace,
222
222
  domainIbGibs: [v2a],
223
223
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
224
- senderIdentity: r1_senderIdentity_v0_source,
224
+ senderIdentityInfo: {
225
+ senderIdentity: r1_senderIdentity_v0_source,
226
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
227
+ },
225
228
  fnSenderSecret: async () => SENDER_SECRET,
226
229
  });
227
230
  await resSync.done;
@@ -254,7 +254,10 @@ await respecfully(sir, `Sync Conflict Basic Multitimelines with Identity`, async
254
254
  metaspace,
255
255
  domainIbGibs: [alpha_v3_source_rel8beta],
256
256
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
257
- senderIdentity: r1_senderIdentity_v0_source,
257
+ senderIdentityInfo: {
258
+ senderIdentity: r1_senderIdentity_v0_source,
259
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
260
+ },
258
261
  fnSenderSecret: async () => SENDER_SECRET,
259
262
  });
260
263
  await resSync.done;
@@ -150,9 +150,12 @@ await respecfully(sir, `Text merge (LCS) conflict resolution with Identity`, asy
150
150
  localSpace: sourceSpace,
151
151
  metaspace,
152
152
  domainIbGibs: [r1_alpha_v0_source.ibGib],
153
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
154
- senderIdentity: senderIdentityLatestSource,
153
+ senderIdentityInfo: {
154
+ senderIdentity: senderIdentityLatestSource,
155
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
156
+ },
155
157
  fnSenderSecret: async () => SENDER_SECRET,
158
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
156
159
  });
157
160
  await r1_syncSaga.done;
158
161
  if (logalot) { console.log(`${lc} R1 Sync Complete.`); }
@@ -286,9 +289,12 @@ await respecfully(sir, `Text merge (LCS) conflict resolution with Identity`, asy
286
289
  localSpace: sourceSpace,
287
290
  metaspace,
288
291
  domainIbGibs: [r2_alpha_v1_source_appendedText.ibGib],
289
- conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
290
- senderIdentity: senderIdentityLatestSource,
292
+ senderIdentityInfo: {
293
+ senderIdentity: senderIdentityLatestSource,
294
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
295
+ },
291
296
  fnSenderSecret: async () => SENDER_SECRET,
297
+ conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
292
298
  });
293
299
  await r2_syncSaga.done;
294
300
  } catch (e) {
@@ -134,7 +134,10 @@ await respecfully(sir, `Sync Constants (No TJP) with Identity`, async () => {
134
134
  localSpace: sourceSpace,
135
135
  metaspace: metaspace,
136
136
  domainIbGibs: [r1_c1_v0_source],
137
- senderIdentity: r1_senderIdentity_v0_source,
137
+ senderIdentityInfo: {
138
+ senderIdentity: r1_senderIdentity_v0_source,
139
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
140
+ },
138
141
  fnSenderSecret: async () => SENDER_SECRET,
139
142
  });
140
143
  await resSync.done;
@@ -153,7 +156,10 @@ await respecfully(sir, `Sync Constants (No TJP) with Identity`, async () => {
153
156
  localSpace: sourceSpace,
154
157
  metaspace: metaspace,
155
158
  domainIbGibs: [r1_c1_v0_source],
156
- senderIdentity: r1_senderIdentity_v1_source_postSync1,
159
+ senderIdentityInfo: {
160
+ senderIdentity: r1_senderIdentity_v1_source_postSync1,
161
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
162
+ },
157
163
  fnSenderSecret: async () => SENDER_SECRET,
158
164
  });
159
165
  await resSync.done;
@@ -183,7 +189,10 @@ await respecfully(sir, `Sync Constants (No TJP) with Identity`, async () => {
183
189
  localSpace: sourceSpace,
184
190
  metaspace: metaspace,
185
191
  domainIbGibs: [r1_c2_v0_source_rel8C1],
186
- senderIdentity: r1_senderIdentity_v2_source_postSync2,
192
+ senderIdentityInfo: {
193
+ senderIdentity: r1_senderIdentity_v2_source_postSync2,
194
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
195
+ },
187
196
  fnSenderSecret: async () => SENDER_SECRET,
188
197
  });
189
198
  await resSync.done;
@@ -162,7 +162,10 @@ await respecfully(sir, `Sync InnerSpaces (Deep Updates) with Identity`, async ()
162
162
  localSpace: sourceSpace,
163
163
  metaspace: metaspace,
164
164
  domainIbGibs: [r1_alpha_v2_source],
165
- senderIdentity: r1_senderIdentity_v0_source,
165
+ senderIdentityInfo: {
166
+ senderIdentity: r1_senderIdentity_v0_source,
167
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
168
+ },
166
169
  fnSenderSecret: async () => SENDER_SECRET,
167
170
  });
168
171
  await resSync.done;
@@ -184,7 +184,10 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead) with Identity`, async () =
184
184
  localSpace: sourceSpace,
185
185
  metaspace: metaspace,
186
186
  domainIbGibs: [r1_alpha_v1_source],
187
- senderIdentity: r1_senderIdentity_v0_source,
187
+ senderIdentityInfo: {
188
+ senderIdentity: r1_senderIdentity_v0_source,
189
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
190
+ },
188
191
  fnSenderSecret: async () => SENDER_SECRET,
189
192
  });
190
193
  await resSync.done;
@@ -175,7 +175,10 @@ await respecfully(sir, `Sync InnerSpaces (Multiple Timelines) with Identity`, as
175
175
  localSpace: sourceSpace,
176
176
  metaspace: metaspace,
177
177
  domainIbGibs: [r1_alpha_v1_source, r1_beta_v2_source],
178
- senderIdentity: r1_senderIdentity_v0_source,
178
+ senderIdentityInfo: {
179
+ senderIdentity: r1_senderIdentity_v0_source,
180
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
181
+ },
179
182
  fnSenderSecret: async () => SENDER_SECRET,
180
183
  });
181
184
  await resSync.done;
@@ -163,7 +163,10 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update) with Identity`, async
163
163
  localSpace: sourceSpace,
164
164
  metaspace: metaspace,
165
165
  domainIbGibs: [r1_alpha_v2_source],
166
- senderIdentity: r1_senderIdentity_v0_source,
166
+ senderIdentityInfo: {
167
+ senderIdentity: r1_senderIdentity_v0_source,
168
+ senderDomainAddr: getIbGibAddr({ ibGib: r1_senderIdentity_v0_source }),
169
+ },
167
170
  fnSenderSecret: async () => SENDER_SECRET,
168
171
  });
169
172
  await resSync.done;
@@ -152,7 +152,10 @@ await respecfully(sir, `Sync InnerSpaces with Identity`, async () => {
152
152
  localSpace: sourceSpace,
153
153
  metaspace: metaspace,
154
154
  domainIbGibs: [r1_alpha_v1_source], // Sync the child
155
- senderIdentity,
155
+ senderIdentityInfo: {
156
+ senderIdentity,
157
+ senderDomainAddr: getIbGibAddr({ ibGib: senderIdentity }),
158
+ },
156
159
  fnSenderSecret: async () => SENDER_SECRET,
157
160
  conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
158
161
  });
@@ -89,6 +89,10 @@ export interface InitializeSyncPeerOpts {
89
89
  * together or omitted together.
90
90
  */
91
91
  senderIdentity?: KeystoneIbGib_V1;
92
+ /**
93
+ * The root Domain Identity address associated with the senderIdentity delegate.
94
+ */
95
+ senderDomainAddr?: string;
92
96
  /**
93
97
  * Returns the plaintext secret corresponding to {@link senderIdentity}.
94
98
  * Wrapped in a function to avoid holding the secret in memory longer than needed.
@@ -224,13 +224,17 @@ export abstract class SyncPeer_V1<
224
224
 
225
225
  if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? Call initializeOpts first. (E: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c526)`); }
226
226
 
227
- const { senderIdentity, fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
227
+ const { senderIdentity, fnSenderSecret, senderDomainAddr, sagaId, localMetaspace, localSpace } = this.opts;
228
228
 
229
229
  // No identity provided — anonymous sync, nothing to establish.
230
230
  if (!senderIdentity || !fnSenderSecret) {
231
231
  if (logalot) { console.log(`${lc} no senderIdentity/fnSenderSecret — skipping establish (I: f29348a77d1542326d14043ea4b69126)`); }
232
232
  return undefined;
233
233
  }
234
+
235
+ if (!senderDomainAddr) {
236
+ throw new Error(`(UNEXPECTED) senderDomainAddr falsy but senderIdentity/fnSenderSecret truthy? if identity is used, senderDomainAddr must be provided. (E: c288fa8e9d3d82fc)`);
237
+ }
234
238
  const senderIdentityAddr = getIbGibAddr({ ibGib: senderIdentity });
235
239
  const senderIdentityTjpAddr = getTjpAddr({ ibGib: senderIdentity });
236
240
  if (!senderIdentityTjpAddr) { throw new Error(`(UNEXPECTED) senderIdentityTjpAddr falsy? (E: d5d8c3ab25a83a2c127904fe96de1526)`); }
@@ -21,7 +21,8 @@ import { KeystoneStrategyFactory } from '../../../../keystone/strategy/keystone-
21
21
  import { KeystoneService_V1 } from '../../../../keystone/keystone-service-v1.mjs';
22
22
  import { IbGibSpaceAny } from '../../../../witness/space/space-base-v1.mjs';
23
23
  import { MetaspaceService } from '../../../../witness/space/metaspace/metaspace-types.mjs';
24
- import { POOL_ID_CONNECT, KEYSTONE_VERB_CONNECT } from '../../../../keystone/keystone-constants.mjs';
24
+ import { POOL_ID_CONNECT, KEYSTONE_VERB_CONNECT, KEYSTONE_VERB_SYNC } from '../../../../keystone/keystone-constants.mjs';
25
+ import { getTjpAddr } from '../../../../common/other/ibgib-helper.mjs';
25
26
 
26
27
  const logalot = GLOBAL_LOG_A_LOT
27
28
 
@@ -297,35 +298,77 @@ export async function validateAndRegisterEvolveKeystone({
297
298
  throw new Error(`Intrinsic keystone validation failed: ${intrinsicErrors.join(', ')} (E: 38ea984585edc6ee88d2a698c7895826)`);
298
299
  }
299
300
 
300
- // 2. Verify URL :domainAddr matches the keystone's tjp
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;
305
- if (tjpGib !== expectedTjpGib) {
306
- throw new Error(`Keystone tjpGib (${tjpGib}) does not match URL domainAddr tjpGib (${expectedTjpGib})`);
307
- }
308
-
309
- // 3. Load previous frame (the current tip in metaspace)
301
+ // 2. Load the latest root Domain Identity tip in metaspace
310
302
  const keystoneService = new KeystoneService_V1();
311
- let prevIbGib: KeystoneIbGib_V1;
303
+ let parentKeystone: KeystoneIbGib_V1;
312
304
  try {
313
- prevIbGib = await keystoneService.getLatestKeystone({
305
+ parentKeystone = await keystoneService.getLatestKeystone({
314
306
  addr: domainAddr,
315
307
  metaspace,
316
308
  space
317
309
  });
318
310
  } catch (error) {
319
- throw new Error(`Could not retrieve previous keystone tip for ${domainAddr}: ${extractErrorMsg(error)} (E: b73ed8aeb0d837d248718b487345d326)`);
311
+ throw new Error(`Could not retrieve root Domain Identity tip for ${domainAddr}: ${extractErrorMsg(error)} (E: b73ed8aeb0d837d248718b487345d326)`);
320
312
  }
321
313
 
322
- // 4. Validate Evolution Transition
323
- const validationErrors = await keystoneService.validate({
324
- currentIbGib: keystoneIbGib,
325
- prevIbGib
326
- });
327
- if (validationErrors && validationErrors.length > 0) {
328
- throw new Error(`Keystone evolution validation failed: ${validationErrors.join(', ')} (E: 5212f8492ac839953842631834bcd826)`);
314
+ const parentTjpAddr = getTjpAddr({ ibGib: parentKeystone });
315
+ const incomingTjpAddr = getTjpAddr({ ibGib: keystoneIbGib });
316
+ if (!incomingTjpAddr) {
317
+ throw new Error(`Incoming keystone does not have a TJP address (E: d288fae39b7d825d)`);
318
+ }
319
+
320
+ const isDelegate = incomingTjpAddr !== parentTjpAddr;
321
+ let prevIbGib: KeystoneIbGib_V1 | undefined;
322
+
323
+ if (isDelegate) {
324
+ // Verify that the delegate is registered under the root Domain Identity
325
+ const delegateInfo = parentKeystone.data?.delegates?.[incomingTjpAddr];
326
+ if (!delegateInfo) {
327
+ throw new Error(`Incoming delegate keystone (${incomingTjpAddr}) is not registered under parent Domain Identity (${parentTjpAddr}) (E: c288fae39b7d82fe)`);
328
+ }
329
+
330
+ // Verify that the delegate is authorized for sync
331
+ const allowedVerbs = delegateInfo.allowedVerbs ?? [];
332
+ if (!allowedVerbs.includes(KEYSTONE_VERB_SYNC)) {
333
+ throw new Error(`Incoming delegate keystone is not authorized for sync. Allowed verbs: ${allowedVerbs.join(', ')} (E: a288fae39b7d82ff)`);
334
+ }
335
+
336
+ // Load delegate's latest frame from space (if any)
337
+ const delegateLatestAddr = await metaspace.getLatestAddr({
338
+ addr: incomingTjpAddr,
339
+ space
340
+ });
341
+ if (delegateLatestAddr) {
342
+ const resGet = await metaspace.get({ addr: delegateLatestAddr, space });
343
+ if (resGet.success && resGet.ibGibs && resGet.ibGibs.length > 0) {
344
+ prevIbGib = resGet.ibGibs[0] as KeystoneIbGib_V1;
345
+ }
346
+ }
347
+ } else {
348
+ // For root Domain Identity evolution, it must transition from the parent keystone tip
349
+ prevIbGib = parentKeystone;
350
+ }
351
+
352
+ // 3. Validate Evolution Transition or Graph
353
+ if (prevIbGib) {
354
+ const validationErrors = await keystoneService.validate({
355
+ currentIbGib: keystoneIbGib,
356
+ prevIbGib
357
+ });
358
+ if (validationErrors && validationErrors.length > 0) {
359
+ throw new Error(`Keystone evolution validation failed: ${validationErrors.join(', ')} (E: 5212f8492ac839953842631834bcd826)`);
360
+ }
361
+ } else {
362
+ // Validate delegate's genesis or entire graph if no previous tip exists
363
+ const validationErrors = await keystoneService.validateKeystoneGraph({
364
+ keystoneIbGib,
365
+ getLatest: false,
366
+ invalidIfMoreRecentKeystoneFoundInSpace: false,
367
+ space
368
+ });
369
+ if (validationErrors && validationErrors.length > 0) {
370
+ throw new Error(`Keystone graph validation failed: ${validationErrors.join(', ')} (E: 3a288fae39b7d82e)`);
371
+ }
329
372
  }
330
373
 
331
374
  // 5. Check Single Pool Restriction
@@ -352,8 +395,39 @@ export async function validateAndRegisterEvolveKeystone({
352
395
  const { verb } = claim;
353
396
  if (!verb) { throw new Error(`claim.verb is falsy (E: 92cf38af58db2cd90e7132b8940fe326)`); }
354
397
 
398
+ if (verb === 'manage') {
399
+ const prevDelegates = prevIbGib?.data?.delegates ?? {};
400
+ const currDelegates = keystoneIbGib.data?.delegates ?? {};
401
+ for (const [delegateTjpAddr, delegateInfo] of Object.entries(currDelegates)) {
402
+ if (!prevDelegates[delegateTjpAddr]) {
403
+ const delegateAddr = delegateInfo.delegateAddr;
404
+ const delegateIbGib = relatedIbGibs.find(ibGib => getIbGibAddr({ ibGib }) === delegateAddr);
405
+ if (!delegateIbGib) {
406
+ throw new Error(`Evolved delegate keystone ${delegateAddr} must be provided in relatedIbGibs (E: 1fe5a68438e288ab4e86c90d81d142826)`);
407
+ }
408
+ const delegateErrors = await keystoneService.validateGenesisKeystone({ keystoneIbGib: delegateIbGib as any });
409
+ if (delegateErrors && delegateErrors.length > 0) {
410
+ throw new Error(`Genesis validation failed for delegate keystone ${delegateAddr}: ${delegateErrors.join(', ')} (E: d8afdc1dbed48c000455b35585dc26826)`);
411
+ }
412
+ }
413
+ }
414
+
415
+ await metaspace.put({ ibGibs: [keystoneIbGib, ...relatedIbGibs], space });
416
+ await metaspace.registerNewIbGib({ ibGib: keystoneIbGib, space });
417
+ for (const related of relatedIbGibs) {
418
+ if (related.ib?.startsWith('keystone')) {
419
+ await metaspace.registerNewIbGib({ ibGib: related, space });
420
+ }
421
+ }
422
+ return;
423
+ }
424
+
355
425
  if (verb !== 'sync') {
356
- throw new Error(`non-sync keystone evolution not yet implemented (E: eca4681b05486d1f784c0cb815ef9926)`);
426
+ throw new Error(`non-sync/non-manage keystone evolution not yet implemented (E: eca4681b05486d1f784c0cb815ef9926)`);
427
+ }
428
+
429
+ if (!isDelegate) {
430
+ throw new Error(`Root Domain Identity (${parentTjpAddr}) is not allowed to sync directly. A delegate must be used. (E: 2c88fae39b7d82fd)`);
357
431
  }
358
432
 
359
433
  const sAddr = claim.target;
@@ -31,6 +31,7 @@ import {
31
31
  DomainIbGibAnalysisInfo, NextSagaFrameInfo,
32
32
  HandleSagaResponseContextResult,
33
33
  SyncSagaFrameDependencyGraph,
34
+ SyncSenderIdentityInfo,
34
35
  } from "./sync-types.mjs";
35
36
  import { getSyncSagaFrameOrigin, getFullSyncSagaHistory, getSyncIb, getTempSpaceName, isPastFrame, putInSpace_dnasThenNonDnas, validateFullSyncSagaHistory, getAllOrphanedAddresses, getFinalConflictsInfo, getSyncSagaFrameDependencyGraph } from "./sync-helpers.mjs";
36
37
  import { getDeltaDependencyGraph, getDependencyGraph, toFlatGraph } from "../common/other/graph-helper.mjs";
@@ -143,7 +144,7 @@ export class SyncSagaCoordinator {
143
144
  public async sync({
144
145
  peer,
145
146
  domainIbGibs,
146
- senderIdentity,
147
+ senderIdentityInfo,
147
148
  fnSenderSecret,
148
149
  conflictStrategy = SyncConflictStrategy.abort,
149
150
  metaspace,
@@ -161,19 +162,16 @@ export class SyncSagaCoordinator {
161
162
  */
162
163
  domainIbGibs: IbGib_V1[],
163
164
  /**
164
- * If present, this is the primary identity of the sender, i.e., who is
165
- * initiating the sync.
166
- *
167
- * This should be the most recent frame (tip) of the senderIdentity's
168
- * timeline.
165
+ * Optional structure containing both the sender's delegate identity (Alice's device key)
166
+ * and the parent root Domain Identity address (senderDomainAddr).
169
167
  *
170
168
  * NOTE: {@link fnSenderSecret} must be truthy if this is truthy, and vice versa.
171
169
  */
172
- senderIdentity?: KeystoneIbGib_V1,
170
+ senderIdentityInfo?: SyncSenderIdentityInfo,
173
171
  /**
174
- * secret corresponding to {@link senderIdentity}.
172
+ * secret corresponding to {@link senderIdentityInfo.senderIdentity}.
175
173
  *
176
- * NOTE: {@link senderIdentity} must be truthy if this is truthy, and vice versa.
174
+ * NOTE: {@link senderIdentityInfo} must be truthy if this is truthy, and vice versa.
177
175
  */
178
176
  fnSenderSecret?: () => Promise<string>;
179
177
  /**
@@ -201,11 +199,17 @@ export class SyncSagaCoordinator {
201
199
  throw new Error(`${lc} source (or localSpace) required (E: 25df3761f7686a1099a552f83c95d326)`);
202
200
  }
203
201
 
204
- if (senderIdentity || fnSenderSecret) {
205
- if (!senderIdentity) { throw new Error(`(UNEXPECTED) senderIdentity falsy but fnSenderSecret truthy? if either is used, both must be truthy. (E: e366628a4919c7d727d2cbd8e5b75e26)`); }
206
- if (!fnSenderSecret) { throw new Error(`(UNEXPECTED) fnSenderSecret falsy but senderIdentity truthy? if either is used, both must be truthy. (E: 7d55ce37ae482fec48e3398158161926)`); }
202
+ if (senderIdentityInfo || fnSenderSecret) {
203
+ if (!senderIdentityInfo) { throw new Error(`(UNEXPECTED) senderIdentityInfo falsy but fnSenderSecret truthy? if either is used, both must be truthy. (E: e366628a4919c7d727d2cbd8e5b75e26)`); }
204
+ if (!fnSenderSecret) { throw new Error(`(UNEXPECTED) fnSenderSecret falsy but senderIdentityInfo truthy? if either is used, both must be truthy. (E: 7d55ce37ae482fec48e3398158161926)`); }
205
+
206
+ const { senderIdentity, senderDomainAddr } = senderIdentityInfo;
207
+ if (!senderIdentity) { throw new Error(`(UNEXPECTED) senderIdentity falsy in senderIdentityInfo? if senderIdentityInfo is provided, both senderIdentity and senderDomainAddr must be truthy. (E: a3c17fae2978926d)`); }
208
+ if (!senderDomainAddr) { throw new Error(`(UNEXPECTED) senderDomainAddr falsy in senderIdentityInfo? if senderIdentityInfo is provided, both senderIdentity and senderDomainAddr must be truthy. (E: d288fae39b7d825c)`); }
207
209
  }
208
210
 
211
+ const { senderIdentity, senderDomainAddr } = senderIdentityInfo ?? {};
212
+
209
213
  // 1. SETUP SAGA METADATA
210
214
  const sagaId = await getUUID();
211
215
 
@@ -247,6 +251,7 @@ export class SyncSagaCoordinator {
247
251
  peer.setOptionalOpts({
248
252
  sagaId,
249
253
  senderIdentity,
254
+ senderDomainAddr,
250
255
  fnSenderSecret,
251
256
  sessionConnectPoolConfig: this.defaultSessionConnectPoolConfig(),
252
257
  sessionSyncPoolConfig: this.defaultSessionSyncPoolConfig(),