@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
@@ -1,3 +1,6 @@
1
+ import { HashAlgorithm } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
2
+ import { KeystoneReplenishStrategy } from "./keystone-types.mjs";
3
+
1
4
  export const KEYSTONE_ATOM = "keystone";
2
5
 
3
6
  // #region KeystoneVerb enum
@@ -25,9 +28,9 @@ export const KeystoneVerb = {
25
28
  /**
26
29
  * The meta-verb used to authorize structural changes to the Keystone,
27
30
  * specifically adding or removing challenge pools.
28
- *
31
+ *
29
32
  * "Root access" to the identity.
30
- *
33
+ *
31
34
  * Basically, this is the verb for the "admin" pool.
32
35
  */
33
36
  MANAGE: KEYSTONE_VERB_MANAGE,
@@ -44,3 +47,19 @@ export function isKeystoneVerb(value: string): value is KeystoneVerb {
44
47
  export const POOL_ID_REVOKE = KEYSTONE_VERB_REVOKE;
45
48
  export const POOL_ID_MANAGE = KEYSTONE_VERB_MANAGE;
46
49
  export const POOL_ID_DEFAULT = "default";
50
+
51
+ export const KEYSTONE_CONFIG_DEFAULT_SIZE = 200;
52
+ export const KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL = 2;
53
+ export const KEYSTONE_CONFIG_DEFAULT_RANDOM = 2;
54
+ export const KEYSTONE_CONFIG_DEFAULT_BINDING = 5;
55
+ export const KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY = KeystoneReplenishStrategy.topUp;
56
+ export const KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM = HashAlgorithm.sha_256;
57
+ export const KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS = 1;
58
+
59
+ export const KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY = 2000;
60
+ export const KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL_HIGHSECURITY = 5;
61
+ export const KEYSTONE_CONFIG_DEFAULT_RANDOM_HIGHSECURITY = 5;
62
+ export const KEYSTONE_CONFIG_DEFAULT_BINDING_HIGHSECURITY = 16;
63
+ export const KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY_HIGHSECURITY = KeystoneReplenishStrategy.replaceAll;
64
+ export const KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM_HIGHSECURITY = HashAlgorithm.sha_256;
65
+ export const KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS_HIGHSECURITY = 10;
@@ -8,10 +8,11 @@ import { getGib } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
8
8
 
9
9
  import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
10
10
  import { KEYSTONE_ATOM } from "./keystone-constants.mjs";
11
- import { KeystoneData_V1, KeystoneIbGib_V1, KeystoneIbInfo_V1, KeystoneChallengePool, DeterministicResult, KeystoneProof, KeystonePoolConfig, KeystoneReplenishStrategy, KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES, KeystoneClaim, KeystoneSolution } from "./keystone-types.mjs";
11
+ import { KeystoneData_V1, KeystoneIbGib_V1, KeystoneIb_V1, KeystoneChallengePool, DeterministicResult, KeystoneProof, KeystonePoolConfig, KeystoneReplenishStrategy, KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES, KeystoneClaim, KeystoneSolution } from "./keystone-types.mjs";
12
12
  import { MetaspaceService } from "../witness/space/metaspace/metaspace-types.mjs";
13
13
  import { IbGibSpaceAny } from "../witness/space/space-base-v1.mjs";
14
14
  import { KeystoneStrategyFactory } from "./strategy/keystone-strategy-factory.mjs";
15
+ import { GIB } from "@ibgib/ts-gib/dist/V1/constants.mjs";
15
16
 
16
17
  const logalot = GLOBAL_LOG_A_LOT;
17
18
 
@@ -19,7 +20,7 @@ const logalot = GLOBAL_LOG_A_LOT;
19
20
  * space-delimited keystone ib containing select keystone metadata.
20
21
  *
21
22
  * NOTE: This must match {@link parseKeystoneIb}
22
- * @see {@link KeystoneIbInfo_V1}
23
+ * @see {@link KeystoneIb_V1}
23
24
  */
24
25
  export async function getKeystoneIb({
25
26
  keystoneData,
@@ -47,13 +48,13 @@ export async function getKeystoneIb({
47
48
 
48
49
  /**
49
50
  * NOTE: This must match {@link getKeystoneIb}
50
- * @see {@link KeystoneIbInfo_V1}
51
+ * @see {@link KeystoneIb_V1}
51
52
  */
52
53
  export async function parseKeystoneIb({
53
54
  ib,
54
55
  }: {
55
56
  ib: Ib,
56
- }): Promise<KeystoneIbInfo_V1> {
57
+ }): Promise<KeystoneIb_V1> {
57
58
  const lc = `[${parseKeystoneIb.name}]`;
58
59
  try {
59
60
  if (logalot) { console.log(`${lc} starting... (I: 73cb6832984255ed48b2f44db6a21e25)`); }
@@ -123,7 +124,9 @@ export function getDeterministicRequirements({
123
124
  const { gib } = getIbAndGib({ ibGibAddr: targetAddr });
124
125
  if (gib) {
125
126
  // Get required hex prefixes (e.g. 'a', 'b', 'c', '1')
126
- const prefixes = gib.substring(0, behavior.targetBindingChars).toLowerCase();
127
+ const prefixes = gib !== GIB ?
128
+ gib.substring(0, behavior.targetBindingChars).toLowerCase() :
129
+ 'abc'; // arbitrary for primitive binding target ibgib
127
130
 
128
131
  for (const char of prefixes) {
129
132
  // Look in the Explicit Bucket
@@ -200,7 +203,7 @@ export function removeFromBindingMap(
200
203
 
201
204
  /**
202
205
  * Selects the specific pool to use for an operation based on ID, filter criteria, or verb authorization.
203
- *
206
+ *
204
207
  * @returns The matching KeystoneChallengePool
205
208
  * @throws If no pool matches or if multiple pools match but one was expected.
206
209
  */
@@ -216,7 +219,7 @@ export function resolveTargetPool({
216
219
  */
217
220
  poolId?: string;
218
221
  /**
219
- * Optional predicate to find a pool.
222
+ * Optional predicate to find a pool.
220
223
  * Useful for finding delegates via metadata.
221
224
  */
222
225
  poolFilter?: (pool: KeystoneChallengePool) => boolean;
@@ -276,7 +279,7 @@ export function resolveTargetPool({
276
279
  /**
277
280
  * Calculates the complete list of Challenge IDs to solve for a given operation.
278
281
  * Combines Deterministic requirements (Mandatory/Binding/FIFO) with Stochastic requirements.
279
- *
282
+ *
280
283
  * @returns Array of unique challenge IDs.
281
284
  */
282
285
  export function selectChallengeIds({
@@ -312,7 +315,7 @@ export function selectChallengeIds({
312
315
  throw new Error(`Insufficient challenges for random requirement. Need ${randomCount}, have ${availableIds.length} (E: 9f7a67428515c1e82813158581898125)`);
313
316
  }
314
317
  // Shuffle & Pick
315
- // Note: simple Math.random sort is sufficient for V1 stochastic selection
318
+ // Note: simple Math.random sort is sufficient for V1 stochastic selection
316
319
  // as we are just picking from valid available options.
317
320
  const shuffled = [...availableIds].sort(() => 0.5 - Math.random());
318
321
  randomIds.push(...shuffled.slice(0, randomCount));
@@ -347,7 +350,7 @@ export async function generateOpaqueChallengeId({
347
350
  /**
348
351
  * Calculates the NEXT state of the Challenge Pools given a specific consumption event.
349
352
  * Handles TopUp, ReplaceAll, Consume, and ScorchedEarth strategies.
350
- *
353
+ *
351
354
  * @returns The new array of KeystoneChallengePools (including the modified one).
352
355
  */
353
356
  export async function applyReplenishmentStrategy({
@@ -420,7 +423,7 @@ export async function applyReplenishmentStrategy({
420
423
  }
421
424
  } else if (strategyType === KeystoneReplenishStrategy.consume) {
422
425
  consumedIds.forEach(id => delete pool.challenges[id]);
423
- } else if (strategyType === KeystoneReplenishStrategy.scorchedEarth) {
426
+ } else if (strategyType === KeystoneReplenishStrategy.deleteAll) {
424
427
  pool.challenges = {};
425
428
  pool.bindingMap = {};
426
429
  } else {
@@ -441,7 +444,7 @@ export async function applyReplenishmentStrategy({
441
444
  * 3. Solves Challenges (Generates Solutions).
442
445
  * 4. Replenishes Pool (Calculates the next state of ALL pools).
443
446
  * 5. Constructs Proof.
444
- *
447
+ *
445
448
  * @returns The resulting Proof and the full list of Next Pools.
446
449
  */
447
450
  export async function solveAndReplenish({
@@ -512,7 +515,7 @@ export async function solveAndReplenish({
512
515
  /**
513
516
  * Validates the transition from Prev -> Curr.
514
517
  * Enforces Cryptography AND Behavioral Policy.
515
- *
518
+ *
516
519
  * @returns Array of validation error strings. Empty array means Valid.
517
520
  */
518
521
  export async function validateKeystoneTransition({
@@ -525,7 +528,9 @@ export async function validateKeystoneTransition({
525
528
  const lc = `[${validateKeystoneTransition.name}]`;
526
529
  const errors: string[] = [];
527
530
  try {
528
- if (!currentIbGib) { throw new Error(`(UNEXPECTED) currentIbGib falsy? (E: 3c0f02655fa8279e386a079ebb604b25)`); }
531
+ if (!currentIbGib) {
532
+ throw new Error(`(UNEXPECTED) currentIbGib falsy? (E: 3c0f02655fa8279e386a079ebb604b25)`);
533
+ }
529
534
  if (!prevIbGib) { throw new Error(`(UNEXPECTED) prevIbGib falsy? (E: 0d07c812634d839c784f31b8848ba825)`); }
530
535
 
531
536
  // intrinsic validation
@@ -20,7 +20,7 @@ const logalot = GLOBAL_LOG_A_LOT || true;
20
20
 
21
21
  /**
22
22
  * Facade for managing Keystone Identities.
23
- *
23
+ *
24
24
  * Handles Genesis, Authorized Evolution (Signing), and Validation.
25
25
  */
26
26
  export class KeystoneService_V1 {
@@ -93,9 +93,9 @@ export class KeystoneService_V1 {
93
93
 
94
94
  /**
95
95
  * Signs a claim by solving challenges from a specific pool and evolving the Keystone timeline.
96
- *
96
+ *
97
97
  * Uses a hybrid selection strategy: Mandatory IDs (Alice) + Sequential (FIFO) + Random (Stochastic).
98
- *
98
+ *
99
99
  * Supports Delegation via `poolFilter` to find specific foreign pools.
100
100
  */
101
101
  async sign({
@@ -122,7 +122,7 @@ export class KeystoneService_V1 {
122
122
  */
123
123
  poolId?: string;
124
124
  /**
125
- * Optional predicate to find a pool.
125
+ * Optional predicate to find a pool.
126
126
  * Useful for finding delegates via metadata without knowing the exact ID.
127
127
  * e.g. (p) => p.metadata?.delegate === 'Bob'
128
128
  */
@@ -158,7 +158,7 @@ export class KeystoneService_V1 {
158
158
  });
159
159
 
160
160
  // 3. Pay the Cost (Solve & Replenish)
161
- // This helper handles the Strategy creation, Secret derivation, Solving,
161
+ // This helper handles the Strategy creation, Secret derivation, Solving,
162
162
  // and the calculation of the Next state for ALL pools.
163
163
  const { proof, nextPools } = await solveAndReplenish({
164
164
  targetPoolId: pool.id,
@@ -196,13 +196,13 @@ export class KeystoneService_V1 {
196
196
 
197
197
  /**
198
198
  * Validates a keystone.
199
- *
199
+ *
200
200
  * ## NOTES
201
- *
201
+ *
202
202
  * Atow (12/22/2025) this only validates the transition from Prev -> Curr.
203
- *
203
+ *
204
204
  * @returns Array of validation error strings. Empty array means Valid.
205
- *
205
+ *
206
206
  * @see {@link validateKeystoneTransition}
207
207
  */
208
208
  async validate({
@@ -220,11 +220,11 @@ export class KeystoneService_V1 {
220
220
 
221
221
  /**
222
222
  * Permanently revokes the Identity.
223
- *
223
+ *
224
224
  * Logic:
225
225
  * 1. Locates the 'revoke' pool.
226
226
  * 2. Solves required challenges to prove ownership.
227
- * 3. Wipes the pool (via 'scorched-earth' strategy in solveAndReplenish).
227
+ * 3. Wipes the pool (via the delete all strategy in solveAndReplenish).
228
228
  * 4. Sets the revocationInfo on the new frame.
229
229
  */
230
230
  async revoke({
@@ -270,8 +270,9 @@ export class KeystoneService_V1 {
270
270
  if (idsToSolve.length === 0) { throw new Error(`Revocation policy selected 0 challenges? Check config for pool ${pool.id}. Revocation requires proof. (E: 97e5a8356d241ae7b882db791cb1f825)`); }
271
271
 
272
272
  // 4. Pay the Cost & Scorched Earth
273
- // The revoke pool config should have 'replenish: scorched-earth',
274
- // causing solveAndReplenish to return an empty pool in nextPools.
273
+ // The revoke pool config should have 'replenishStrategy:
274
+ // KeystoneReplenishStrategy.deleteAll', causing solveAndReplenish
275
+ // to return an empty pool in nextPools.
275
276
  const { proof, nextPools } = await solveAndReplenish({
276
277
  targetPoolId: pool.id,
277
278
  prevPools: prevData.challengePools,
@@ -283,7 +284,7 @@ export class KeystoneService_V1 {
283
284
  // warn if nextPools contains pool.id that isn't empty (we were
284
285
  // supposed to do "scorched earth" which empties the pool)
285
286
  if (nextPools.find(p => p.id === pool.id && Object.keys(p.challenges).length > 0)) {
286
- console.warn(`${lc} revocation pool ${pool.id} is not empty after revocation. Is the revocation pool replenish strategy set to ${KeystoneReplenishStrategy.scorchedEarth}? (W: 300c28bc8b98fc3e3c0b0d988344f825)`);
287
+ console.warn(`${lc} revocation pool ${pool.id} is not empty after revocation. Is the revocation pool replenish strategy set to ${KeystoneReplenishStrategy.deleteAll}? (W: 300c28bc8b98fc3e3c0b0d988344f825)`);
287
288
  }
288
289
 
289
290
  // 5. Construct Revocation Info
@@ -316,11 +317,11 @@ export class KeystoneService_V1 {
316
317
 
317
318
  /**
318
319
  * Structural evolution: Adds new challenge pools to the keystone.
319
- *
320
- * Use Case: Adding a delegate (Server) for SSO, adding a recovery key,
320
+ *
321
+ * Use Case: Adding a delegate (Server) for SSO, adding a recovery key,
321
322
  * or rotating to a new set of pools.
322
- *
323
- * Requires the Master Secret to authorize the change via a pool containing
323
+ *
324
+ * Requires the Master Secret to authorize the change via a pool containing
324
325
  * the 'manage' verb.
325
326
  */
326
327
  async addPools({
@@ -332,14 +333,14 @@ export class KeystoneService_V1 {
332
333
  }: {
333
334
  latestKeystone: KeystoneIbGib_V1;
334
335
  /**
335
- * Alice's Master Secret.
336
+ * Alice's Master Secret.
336
337
  * Required to solve challenges from the Admin/Manage pool to authorize this change.
337
338
  */
338
339
  masterSecret: string;
339
340
  /**
340
- * The pools to add.
341
- * NOTE: These are fully constructed Pool objects.
342
- * If they are foreign (Bob's), Alice must have constructed them
341
+ * The pools to add.
342
+ * NOTE: These are fully constructed Pool objects.
343
+ * If they are foreign (Bob's), Alice must have constructed them
343
344
  * using Bob's challenges + Her config restrictions + isForeign=true.
344
345
  */
345
346
  newPools: KeystoneChallengePool[];
@@ -195,12 +195,15 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
195
195
 
196
196
  firstOfAll(sir, async () => {
197
197
  // Use our standard builder to get a valid config object
198
- config = createStandardPoolConfig(salt) as KeystonePoolConfig_HashV1;
198
+ config = createStandardPoolConfig({
199
+ id: salt,
200
+ salt,
201
+ }) as KeystonePoolConfig_HashV1;
199
202
  });
200
203
 
201
204
  await respecfully(sir, 'Derivation Logic', async () => {
202
205
 
203
- await ifWe(sir, 'derivePoolSecret with same inputs returns same output', async () => {
206
+ await ifWeMight(sir, 'derivePoolSecret with same inputs returns same output', async () => {
204
207
  const strategy = KeystoneStrategyFactory.create({ config });
205
208
 
206
209
  const secretA = await strategy.derivePoolSecret({ masterSecret });
@@ -210,7 +213,7 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
210
213
  iReckon(sir, secretA).asTo('secret length').isGonnaBeTruthy();
211
214
  });
212
215
 
213
- await ifWe(sir, 'derivePoolSecret with different master secret returns different output', async () => {
216
+ await ifWeMight(sir, 'derivePoolSecret with different master secret returns different output', async () => {
214
217
  const strategy = KeystoneStrategyFactory.create({ config });
215
218
 
216
219
  const secretA = await strategy.derivePoolSecret({ masterSecret });
@@ -219,7 +222,7 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
219
222
  iReckon(sir, secretA).asTo('secrets differ').not.willEqual(secretB);
220
223
  });
221
224
 
222
- await ifWe(sir, 'derivePoolSecret with different salt returns different output', async () => {
225
+ await ifWeMight(sir, 'derivePoolSecret with different salt returns different output', async () => {
223
226
  // Modify salt in a copy of config
224
227
  const configB = { ...config, salt: "OtherPool" };
225
228
  const strategyA = KeystoneStrategyFactory.create({ config });
@@ -234,7 +237,7 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
234
237
 
235
238
  await respecfully(sir, 'Challenge/Solution Logic', async () => {
236
239
 
237
- await ifWe(sir, 'generateSolution -> generateChallenge -> validateSolution loop works', async () => {
240
+ await ifWeMight(sir, 'generateSolution -> generateChallenge -> validateSolution loop works', async () => {
238
241
  const strategy = KeystoneStrategyFactory.create({ config });
239
242
  const poolSecret = await strategy.derivePoolSecret({ masterSecret });
240
243
  const challengeId = "a3ff7843552870fc28bef2b"; // arbitrary random challengeId
@@ -253,7 +256,7 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
253
256
  iReckon(sir, isValid).asTo('valid pair should pass').isGonnaBeTrue();
254
257
  });
255
258
 
256
- await ifWe(sir, 'validateSolution fails for mismatched values', async () => {
259
+ await ifWeMight(sir, 'validateSolution fails for mismatched values', async () => {
257
260
  const strategy = KeystoneStrategyFactory.create({ config });
258
261
  const poolSecret = await strategy.derivePoolSecret({ masterSecret });
259
262
  const challengeId = "8c994f3ed598f150e25513"; // arbitrary random challengeId
@@ -269,7 +272,7 @@ await respecfully(sir, 'Suite A: Strategy Vectors (HashRevealV1)', async () => {
269
272
  iReckon(sir, isValid).asTo('tampered solution should fail').isGonnaBeFalse();
270
273
  });
271
274
 
272
- await ifWe(sir, 'validateSolution fails for mismatched challenge hashes', async () => {
275
+ await ifWeMight(sir, 'validateSolution fails for mismatched challenge hashes', async () => {
273
276
  const strategy = KeystoneStrategyFactory.create({ config });
274
277
  const poolSecret = await strategy.derivePoolSecret({ masterSecret });
275
278
 
@@ -310,8 +313,11 @@ await respecfully(sir, 'Suite B: Service Lifecycle', async () => {
310
313
  });
311
314
 
312
315
  await respecfully(sir, 'Genesis', async () => {
313
- await ifWe(sir, 'creates a valid genesis frame and persists it', async () => {
314
- const config = createStandardPoolConfig(POOL_ID_DEFAULT);
316
+ await ifWeMight(sir, 'creates a valid genesis frame and persists it', async () => {
317
+ const config = createStandardPoolConfig({
318
+ id: POOL_ID_DEFAULT,
319
+ salt: POOL_ID_DEFAULT,
320
+ });
315
321
 
316
322
  genesisKeystone = await service.genesis({
317
323
  masterSecret,
@@ -338,7 +344,7 @@ await respecfully(sir, 'Suite B: Service Lifecycle', async () => {
338
344
  });
339
345
 
340
346
  await respecfully(sir, 'Signing (Evolution)', async () => {
341
- await ifWe(sir, 'evolves the keystone with a valid proof', async () => {
347
+ await ifWeMight(sir, 'evolves the keystone with a valid proof', async () => {
342
348
  const claim: Partial<KeystoneClaim> = {
343
349
  target: "comment 123^gib",
344
350
  verb: "post"
@@ -368,7 +374,7 @@ await respecfully(sir, 'Suite B: Service Lifecycle', async () => {
368
374
  });
369
375
 
370
376
  await respecfully(sir, 'Validation', async () => {
371
- await ifWe(sir, 'validates the genesis->signed transition', async () => {
377
+ await ifWeMight(sir, 'validates the genesis->signed transition', async () => {
372
378
  const errors = await service.validate({
373
379
  prevIbGib: genesisKeystone,
374
380
  currentIbGib: signedKeystone,
@@ -400,8 +406,13 @@ await respecfully(sir, 'Suite C: Security Vectors', async () => {
400
406
  mockMetaspace = new MockMetaspaceService(mockSpace);
401
407
 
402
408
  // Setup Alice's Identity
403
- const config = createStandardPoolConfig(POOL_ID_DEFAULT);
404
- config.behavior.size = 10;
409
+ const config = createStandardPoolConfig({
410
+ id: POOL_ID_DEFAULT,
411
+ salt: POOL_ID_DEFAULT,
412
+ targetBinding: 0,
413
+ size: 10,
414
+ });
415
+ // config.behavior.size = 10;
405
416
  genesisKeystone = await service.genesis({
406
417
  masterSecret: aliceSecret,
407
418
  configs: [config],
@@ -411,7 +422,7 @@ await respecfully(sir, 'Suite C: Security Vectors', async () => {
411
422
  });
412
423
 
413
424
  await respecfully(sir, 'Wrong Secret (Forgery)', async () => {
414
- await ifWe(sir, 'prevents creation of forged frames', async () => {
425
+ await ifWeMight(sir, 'prevents creation of forged frames', async () => {
415
426
  const claim: Partial<KeystoneClaim> = { target: "comment 123^gib", verb: "post" };
416
427
 
417
428
  let errorCaught = false;
@@ -440,10 +451,13 @@ await respecfully(sir, 'Suite C: Security Vectors', async () => {
440
451
  });
441
452
 
442
453
  await respecfully(sir, 'Policy Violation (Restricted Verbs)', async () => {
443
- await ifWe(sir, 'throws error if signing forbidden verb with restricted pool', async () => {
454
+ await ifWeMight(sir, 'throws error if signing forbidden verb with restricted pool', async () => {
444
455
  // Create a specific restricted pool config manually
445
456
  const restrictedPoolId = "read_only_pool";
446
- const restrictedConfig = createStandardPoolConfig(restrictedPoolId);
457
+ const restrictedConfig = createStandardPoolConfig({
458
+ id: restrictedPoolId,
459
+ salt: restrictedPoolId,
460
+ });
447
461
  // Manually restrict it (since Builder defaults to undefined/allow-all)
448
462
  restrictedConfig.allowedVerbs = ['read'];
449
463
 
@@ -495,8 +509,14 @@ await respecfully(sir, 'Suite D: Revocation', async () => {
495
509
  mockMetaspace = new MockMetaspaceService(mockSpace);
496
510
 
497
511
  // Setup Identity WITH a Revocation Pool
498
- const stdConfig = createStandardPoolConfig(POOL_ID_DEFAULT);
499
- const revokeConfig = createRevocationPoolConfig(POOL_ID_REVOKE); // Special Config
512
+ const stdConfig = createStandardPoolConfig({
513
+ id: POOL_ID_DEFAULT,
514
+ salt: POOL_ID_DEFAULT,
515
+ });
516
+ const revokeConfig = createRevocationPoolConfig({
517
+ id: POOL_ID_REVOKE,
518
+ salt: POOL_ID_REVOKE,
519
+ }); // Special Config
500
520
 
501
521
  genesisKeystone = await service.genesis({
502
522
  masterSecret,
@@ -509,7 +529,7 @@ await respecfully(sir, 'Suite D: Revocation', async () => {
509
529
  await respecfully(sir, 'Revoke Lifecycle', async () => {
510
530
  let revokedKeystone: KeystoneIbGib_V1;
511
531
 
512
- await ifWe(sir, 'successfully creates a revocation frame', async () => {
532
+ await ifWeMight(sir, 'successfully creates a revocation frame', async () => {
513
533
  revokedKeystone = await service.revoke({
514
534
  latestKeystone: genesisKeystone,
515
535
  masterSecret,
@@ -527,7 +547,7 @@ await respecfully(sir, 'Suite D: Revocation', async () => {
527
547
  iReckon(sir, data.revocationInfo!.proof.claim.verb).willEqual(KEYSTONE_VERB_REVOKE);
528
548
  });
529
549
 
530
- await ifWe(sir, 'validates the revocation frame', async () => {
550
+ await ifWeMight(sir, 'validates the revocation frame', async () => {
531
551
  const errors = await service.validate({
532
552
  prevIbGib: genesisKeystone,
533
553
  currentIbGib: revokedKeystone!,
@@ -538,7 +558,7 @@ await respecfully(sir, 'Suite D: Revocation', async () => {
538
558
  iReckon(sir, errors.length).asTo('no validation errors').willEqual(0);
539
559
  });
540
560
 
541
- await ifWe(sir, 'consumed the revocation pool (Scorched Earth)', async () => {
561
+ await ifWeMight(sir, 'consumed the revocation pool (Scorched Earth)', async () => {
542
562
  const data = revokedKeystone!.data!;
543
563
  const revokePool = data.challengePools.find(p => p.id === POOL_ID_REVOKE);
544
564
 
@@ -568,7 +588,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
568
588
 
569
589
  // Helper to generate a "Foreign" pool (e.g. from Bob)
570
590
  const createForeignPool = async (id: string, verbs: string[] = []): Promise<KeystoneChallengePool> => {
571
- const config = createStandardPoolConfig(id);
591
+ const config = createStandardPoolConfig({ id, salt: id });
572
592
  config.allowedVerbs = verbs;
573
593
 
574
594
  // We use the factory manually here to simulate Bob doing this offline
@@ -605,7 +625,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
605
625
  mockMetaspace = new MockMetaspaceService(mockSpace);
606
626
 
607
627
  // Alice Genesis: Standard pool (allows all verbs, including 'manage')
608
- const config = createStandardPoolConfig(POOL_ID_DEFAULT);
628
+ const config = createStandardPoolConfig({ id: POOL_ID_DEFAULT, salt: POOL_ID_DEFAULT });
609
629
  aliceKeystone = await service.genesis({
610
630
  masterSecret: aliceSecret,
611
631
  configs: [config],
@@ -615,7 +635,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
615
635
  });
616
636
 
617
637
  await respecfully(sir, 'Happy Path', async () => {
618
- await ifWe(sir, 'authorizes and adds a foreign pool', async () => {
638
+ await ifWeMight(sir, 'authorizes and adds a foreign pool', async () => {
619
639
  const bobPool = await createForeignPool("pool_bob", ["post"]);
620
640
 
621
641
  const updatedKeystone = await service.addPools({
@@ -654,9 +674,10 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
654
674
  });
655
675
 
656
676
  await respecfully(sir, 'Permissions & Logic', async () => {
657
- await ifWe(sir, 'fails if no pool allows "manage" verb', async () => {
677
+ await ifWeMight(sir, 'fails if no pool allows "manage" verb', async () => {
658
678
  // 1. Create a restricted keystone
659
- const restrictedConfig = createStandardPoolConfig("read_only");
679
+ let id = "read_only";
680
+ const restrictedConfig = createStandardPoolConfig({ id, salt: id });
660
681
  restrictedConfig.allowedVerbs = ['read']; // No 'manage'
661
682
 
662
683
  const restrictedKeystone = await service.genesis({
@@ -686,7 +707,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
686
707
  iReckon(sir, errorCaught).asTo('permission denied').isGonnaBeTrue();
687
708
  });
688
709
 
689
- await ifWe(sir, 'fails on ID collision', async () => {
710
+ await ifWeMight(sir, 'fails on ID collision', async () => {
690
711
  // Try to add "pool_bob" again (it was added in Happy Path)
691
712
  const duplicatePool = await createForeignPool("pool_bob");
692
713
 
@@ -725,7 +746,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
725
746
 
726
747
  // Helper to simulate Bob creating a pool "offline" to give to Alice
727
748
  const createForeignPool = async (id: string, verbs: string[] = []): Promise<KeystoneChallengePool> => {
728
- const config = createStandardPoolConfig(id);
749
+ const config = createStandardPoolConfig({ id, salt: id });
729
750
  config.allowedVerbs = verbs;
730
751
 
731
752
  // We use the factory manually here to simulate Bob doing this on his own machine
@@ -762,7 +783,10 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
762
783
  mockMetaspace = new MockMetaspaceService(mockSpace);
763
784
 
764
785
  // Alice Genesis: Standard pool (allows all verbs, including 'manage')
765
- const config = createStandardPoolConfig(POOL_ID_DEFAULT);
786
+ const config = createStandardPoolConfig({
787
+ id: POOL_ID_DEFAULT,
788
+ salt: POOL_ID_DEFAULT,
789
+ });
766
790
  aliceKeystone = await service.genesis({
767
791
  masterSecret: aliceSecret,
768
792
  configs: [config],
@@ -772,7 +796,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
772
796
  });
773
797
 
774
798
  await respecfully(sir, 'Happy Path', async () => {
775
- await ifWe(sir, 'authorizes and adds a foreign pool', async () => {
799
+ await ifWeMight(sir, 'authorizes and adds a foreign pool', async () => {
776
800
  const bobPool = await createForeignPool("pool_bob", ["post"]);
777
801
 
778
802
  const updatedKeystone = await service.addPools({
@@ -811,9 +835,10 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
811
835
  });
812
836
 
813
837
  await respecfully(sir, 'Permissions & Logic', async () => {
814
- await ifWe(sir, 'fails if no pool allows "manage" verb', async () => {
838
+ await ifWeMight(sir, 'fails if no pool allows "manage" verb', async () => {
815
839
  // 1. Create a restricted keystone (read-only)
816
- const restrictedConfig = createStandardPoolConfig("read_only");
840
+ let id = "read_only";
841
+ const restrictedConfig = createStandardPoolConfig({ id, salt: id });
817
842
  restrictedConfig.allowedVerbs = ['read']; // No 'manage'
818
843
 
819
844
  const restrictedKeystone = await service.genesis({
@@ -843,7 +868,7 @@ await respecfully(sir, 'Suite E: Structural Evolution (addPools)', async () => {
843
868
  iReckon(sir, errorCaught).asTo('permission denied').isGonnaBeTrue();
844
869
  });
845
870
 
846
- await ifWe(sir, 'fails on ID collision', async () => {
871
+ await ifWeMight(sir, 'fails on ID collision', async () => {
847
872
  // Try to add "pool_bob" again (it was added in Happy Path)
848
873
  const duplicatePool = await createForeignPool("pool_bob");
849
874
 
@@ -883,11 +908,13 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
883
908
  let signedKeystone: KeystoneIbGib_V1;
884
909
 
885
910
  // We use a specific hybrid config to test exact selection logic
886
- const hybridConfig = createStandardPoolConfig(salt) as KeystonePoolConfig_HashV1;
887
- // 2 FIFO + 2 Random = 4 Total per sign
888
- hybridConfig.behavior.selectSequentially = 2;
889
- hybridConfig.behavior.selectRandomly = 2;
890
- hybridConfig.behavior.size = 20; // Small enough to track, large enough to be random
911
+ const hybridConfig = createStandardPoolConfig({
912
+ id: salt,
913
+ salt,
914
+ // 2 FIFO + 2 Random = 4 Total per sign
915
+ sequential: 2, random: 2, targetBinding: 0,
916
+ size: 20, // Small enough to track, large enough to be random
917
+ }) as KeystonePoolConfig_HashV1;
891
918
 
892
919
  firstOfAll(sir, async () => {
893
920
  mockSpace = new MockIbGibSpace();
@@ -903,7 +930,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
903
930
 
904
931
  await respecfully(sir, 'Proof Granularity & Math', async () => {
905
932
 
906
- await ifWe(sir, 'generates exactly the expected number of solutions', async () => {
933
+ await ifWeMight(sir, 'generates exactly the expected number of solutions', async () => {
907
934
  signedKeystone = await service.sign({
908
935
  latestKeystone: genesisKeystone,
909
936
  masterSecret: aliceSecret,
@@ -920,7 +947,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
920
947
  iReckon(sir, solutions.length).asTo('solution count').willEqual(4);
921
948
  });
922
949
 
923
- await ifWe(sir, 'verifies the math manually (White-box Crypto Check)', async () => {
950
+ await ifWeMight(sir, 'verifies the math manually (White-box Crypto Check)', async () => {
924
951
  const proof = signedKeystone.data!.proofs[0];
925
952
  const poolSnapshot = genesisKeystone.data!.challengePools.find(p => p.id === salt)!;
926
953
 
@@ -949,7 +976,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
949
976
  }
950
977
  });
951
978
 
952
- await ifWe(sir, 'verifies FIFO logic (Deterministic Selection)', async () => {
979
+ await ifWeMight(sir, 'verifies FIFO logic (Deterministic Selection)', async () => {
953
980
  const proof = signedKeystone.data!.proofs[0];
954
981
  const poolSnapshot = genesisKeystone.data!.challengePools.find(p => p.id === salt)!;
955
982
 
@@ -971,7 +998,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
971
998
 
972
999
  await respecfully(sir, 'DTO & Serialization', async () => {
973
1000
 
974
- await ifWe(sir, 'survives a clone/JSON-cycle without corruption', async () => {
1001
+ await ifWeMight(sir, 'survives a clone/JSON-cycle without corruption', async () => {
975
1002
  // 1. Create a DTO (simulate network transmission/storage)
976
1003
  // 'clone' does a JSON stringify/parse under the hood (usually) or structured clone.
977
1004
  const dto = clone(signedKeystone);
@@ -991,7 +1018,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
991
1018
  iReckon(sir, errors.length).asTo('DTO validation errors').willEqual(0);
992
1019
  });
993
1020
 
994
- await ifWe(sir, 'ensures data contains no functions or circular refs', async () => {
1021
+ await ifWeMight(sir, 'ensures data contains no functions or circular refs', async () => {
995
1022
  // A crude but effective test: ensure JSON.stringify doesn't throw
996
1023
  // and the result is equal to the object (if we parsed it back).
997
1024
 
@@ -1005,7 +1032,7 @@ await respecfully(sir, 'Suite F: Deep Inspection', async () => {
1005
1032
  iReckon(sir, parsedSolution).asTo('deep property survives stringify').willEqual(originalSolution);
1006
1033
 
1007
1034
  // Ensure no extra properties were lost
1008
- // FIX: JSON.stringify removes keys with 'undefined' values.
1035
+ // FIX: JSON.stringify removes keys with 'undefined' values.
1009
1036
  // We must filter the original keys to match this behavior for a fair comparison.
1010
1037
  const origKeys = Object.keys(signedKeystone.data!)
1011
1038
  .filter(k => (signedKeystone.data as any)[k] !== undefined);