@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
@@ -0,0 +1,58 @@
1
+ import { HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
+ import { KdfStrategy } from './kdf-constants.mjs';
3
+
4
+ /**
5
+ * Base options for all KDF strategies
6
+ */
7
+ export interface KdfOptionsBase {
8
+ /**
9
+ * Name of the KDF strategy to use
10
+ */
11
+ strategy: KdfStrategy;
12
+ }
13
+
14
+ /**
15
+ * Options for recursive-salt-wrap KDF strategy
16
+ *
17
+ * Derives key by recursively applying: Hash(salt + current + salt) for N rounds
18
+ */
19
+ export interface KdfOptions_RecursiveSaltWrap extends KdfOptionsBase {
20
+ strategy: typeof import('./kdf-constants.mjs').KDF_STRATEGY_RECURSIVE_SALT_WRAP;
21
+
22
+ /**
23
+ * Salt value to wrap around the secret during each iteration
24
+ */
25
+ salt: string;
26
+
27
+ /**
28
+ * Number of hash iterations for key stretching
29
+ */
30
+ rounds: number;
31
+
32
+ /**
33
+ * Hash algorithm to use (default: SHA-256)
34
+ */
35
+ algorithm?: HashAlgorithm;
36
+ }
37
+
38
+ /**
39
+ * Union of all KDF option types
40
+ */
41
+ export type KdfOptions =
42
+ | KdfOptions_RecursiveSaltWrap
43
+ ;
44
+
45
+ /**
46
+ * Parameters for deriving a key using KDF
47
+ */
48
+ export interface DeriveKeyParams {
49
+ /**
50
+ * The initial secret/password to derive from
51
+ */
52
+ masterSecret: string;
53
+
54
+ /**
55
+ * KDF options specifying strategy and strategy-specific parameters
56
+ */
57
+ kdfOpts: KdfOptions;
58
+ }
@@ -1,11 +1,13 @@
1
+ import { extractErrorMsg, HashAlgorithm } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
+
3
+ import { GLOBAL_LOG_A_LOT } from '../core-constants.mjs';
1
4
  import {
2
- KeystonePoolConfig,
3
- KeystonePoolConfig_HashV1,
4
- KeystonePoolBehavior,
5
- KeystoneReplenishStrategy,
6
- KeystonePoolConfigBase
5
+ KeystonePoolConfig, KeystonePoolConfig_HashV1, KeystonePoolBehavior,
6
+ KeystoneReplenishStrategy, KeystonePoolConfigBase, KeystoneChallengeType,
7
7
  } from './keystone-types.mjs';
8
- import { POOL_ID_DEFAULT, POOL_ID_REVOKE, KEYSTONE_VERB_REVOKE } from './keystone-constants.mjs';
8
+ import { POOL_ID_REVOKE, KEYSTONE_VERB_REVOKE, KEYSTONE_CONFIG_DEFAULT_SIZE, KEYSTONE_CONFIG_DEFAULT_BINDING, KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY, KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL, KEYSTONE_CONFIG_DEFAULT_RANDOM, KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_RANDOM_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_BINDING_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY_HIGHSECURITY, KeystoneVerb, KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM, KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS, KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS_HIGHSECURITY } from './keystone-constants.mjs';
9
+
10
+ const logalot = GLOBAL_LOG_A_LOT;
9
11
 
10
12
  /**
11
13
  * Abstract Base Builder.
@@ -14,17 +16,25 @@ import { POOL_ID_DEFAULT, POOL_ID_REVOKE, KEYSTONE_VERB_REVOKE } from './keyston
14
16
  * @template TConfig The concrete config type being built.
15
17
  */
16
18
  export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConfigBase> {
17
- protected _salt: string = 'default';
18
- protected _size: number = 100;
19
- protected _replenish: KeystoneReplenishStrategy = 'top-up';
20
- protected _seq: number = 0;
21
- protected _rand: number = 0;
19
+ protected _id: string | undefined;
20
+ protected _salt: string | undefined;
21
+ protected _size: number | undefined;
22
+ protected _replenish: KeystoneReplenishStrategy | undefined;
23
+ protected _seq: number | undefined;
24
+ protected _rand: number | undefined;
22
25
  protected _verbs: string[] = [];
23
- protected _targetBinding: number = 0; // Default 0
26
+ protected _targetBinding: number | undefined;
24
27
 
28
+ /**
29
+ * Sets the unique id for this pool.
30
+ */
31
+ withId(id: string): this {
32
+ this._id = id;
33
+ return this;
34
+ }
25
35
 
26
36
  /**
27
- * Sets the unique salt/ID for this pool.
37
+ * Sets the unique salt for this pool.
28
38
  */
29
39
  withSalt(salt: string): this {
30
40
  this._salt = salt;
@@ -71,7 +81,7 @@ export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConf
71
81
  /**
72
82
  * Configures the pool to use Hybrid (Both FIFO and Random) selection.
73
83
  */
74
- withHybrid(seqCount: number, randCount: number): this {
84
+ withHybrid({ seqCount, randCount }: { seqCount: number, randCount: number }): this {
75
85
  this._seq = seqCount;
76
86
  this._rand = randCount;
77
87
  return this;
@@ -90,6 +100,11 @@ export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConf
90
100
  * Helper for subclasses.
91
101
  */
92
102
  protected buildBehavior(): KeystonePoolBehavior {
103
+ if (this._size === undefined) { throw new Error(`size required (E: 68320865d9adb8477836485b20b08826)`); }
104
+ if (this._replenish === undefined) { throw new Error(`replenish strategy required (E: 9f8798d1a568763a282e53c89185b826)`); }
105
+ if (this._seq === undefined) { throw new Error(`sequential required (E: e0da08a24e9790d0a8c1a9322f8eb826)`); }
106
+ if (this._rand === undefined) { throw new Error(`selectRandomly required (E: 7721d84d1a8b7d020d0ab33c3f811426)`); }
107
+ if (this._targetBinding === undefined) { throw new Error(`targetBinding required (E: 9add64d7e8e8cba01d901727a8e9b826)`); }
93
108
  return {
94
109
  size: this._size,
95
110
  replenish: this._replenish,
@@ -108,14 +123,14 @@ export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConf
108
123
  return this;
109
124
  }
110
125
 
111
- protected buildBase(): KeystonePoolConfigBase {
112
- // Helper to keep the concrete build() clean
113
- return {
114
- type: 'hash-reveal-v1', // This is overridden by concrete/interface usually, but needed for base shape
115
- salt: this._salt,
116
- allowedVerbs: this._verbs
117
- } as any;
118
- }
126
+ // protected buildBase(): KeystonePoolConfigBase {
127
+ // // Helper to keep the concrete build() clean
128
+ // return {
129
+ // type: KeystoneChallengeType.hash_reveal_v1, // This is overridden by concrete/interface usually, but needed for base shape
130
+ // salt: this._salt,
131
+ // allowedVerbs: this._verbs
132
+ // } as any;
133
+ // }
119
134
 
120
135
  abstract build(): TConfig;
121
136
  }
@@ -124,28 +139,56 @@ export abstract class KeystoneConfigBuilderBase<TConfig extends KeystonePoolConf
124
139
  * Concrete Builder for Hash-Reveal V1 Strategy.
125
140
  */
126
141
  export class KeystoneConfigBuilder_HashV1 extends KeystoneConfigBuilderBase<KeystonePoolConfig_HashV1> {
127
- private _algo: 'SHA-256' | 'SHA-512' = 'SHA-256';
128
- private _rounds: number = 1;
142
+ protected lc: string = `[${KeystoneConfigBuilder_HashV1}]`;
143
+ private _algo: HashAlgorithm | undefined;
144
+ private _rounds: number | undefined;
129
145
 
130
146
  /**
131
147
  * Sets the hashing strength.
132
148
  */
133
- withHash(algo: 'SHA-256' | 'SHA-512', rounds: number = 1): this {
134
- this._algo = algo;
135
- this._rounds = rounds;
136
- return this;
149
+ withHash({ algo, rounds }: { algo: HashAlgorithm, rounds: number }): this {
150
+ const lc = `${this.lc}[${this.withHash.name}]`;
151
+ try {
152
+ if (logalot) { console.log(`${lc} starting... (I: 15d1b3bd2e98bba33fc6c78228755826)`); }
153
+
154
+ this._algo = algo;
155
+ this._rounds = rounds;
156
+ return this;
157
+ } catch (error) {
158
+ console.error(`${lc} ${extractErrorMsg(error)}`);
159
+ throw error;
160
+ } finally {
161
+ if (logalot) { console.log(`${lc} complete.`); }
162
+ }
137
163
  }
138
164
 
139
165
  build(): KeystonePoolConfig_HashV1 {
140
- return {
141
- id: this._salt, // Using salt as the unique ID for the pool config
142
- type: 'hash-reveal-v1',
143
- salt: this._salt,
144
- allowedVerbs: this._verbs, // <--- Mapped here
145
- behavior: this.buildBehavior(),
146
- algo: this._algo,
147
- rounds: this._rounds,
148
- };
166
+ const lc = `${this.lc}[${this.build.name}]`;
167
+ try {
168
+ if (logalot) { console.log(`${lc} starting... (I: 5df568c63c4993bb98df0a319ee16826)`); }
169
+
170
+ if (!this._id) { throw new Error(`id required (E: b50d082adf38bcbf463552f80d2c3226)`); }
171
+ if (!this._salt) { throw new Error(`salt required (E: b0f1926657b8d7d3a88fb9385ead5826)`); }
172
+ if (!this._algo) { throw new Error(`algorithm required (E: cff228f9898fd6383ef752088dae6826)`); }
173
+ if (this._rounds === undefined) { throw new Error(`rounds required (E: eb72580f3b014cda18cba3e399683c26)`); }
174
+
175
+ const result: KeystonePoolConfig_HashV1 = {
176
+ id: this._id,
177
+ type: KeystoneChallengeType.hash_reveal_v1,
178
+ salt: this._salt,
179
+ allowedVerbs: this._verbs,
180
+ behavior: this.buildBehavior(),
181
+ algo: this._algo,
182
+ rounds: this._rounds,
183
+ };
184
+
185
+ return result;
186
+ } catch (error) {
187
+ console.error(`${lc} ${extractErrorMsg(error)}`);
188
+ throw error;
189
+ } finally {
190
+ if (logalot) { console.log(`${lc} complete.`); }
191
+ }
149
192
  }
150
193
  }
151
194
 
@@ -166,22 +209,102 @@ export class KeystoneConfig {
166
209
  // FACTORY FUNCTIONS (Presets)
167
210
  // ===========================================================================
168
211
 
169
- export function createStandardPoolConfig(salt: string = POOL_ID_DEFAULT): KeystonePoolConfig {
212
+ interface KeystoneConfigFactoryOptions_Standard {
213
+ /**
214
+ * id for pool that this config pertains to
215
+ */
216
+ id: string;
217
+ /**
218
+ * should be a unique string
219
+ */
220
+ salt: string;
221
+ /**
222
+ * number of challenges in the pool
223
+ * @see {@link KeystonePoolConfig}
224
+ */
225
+ size?: number;
226
+ /**
227
+ * number of sequential challenges required for solution per action
228
+ */
229
+ sequential?: number;
230
+ /**
231
+ * number of random challenges required for solution per action
232
+ */
233
+ random?: number;
234
+ /**
235
+ * number of target binding characters required for solution per action
236
+ * @see {@link KeystonePoolBehavior.targetBindingChars}
237
+ */
238
+ targetBinding?: number;
239
+ /**
240
+ * @see {@link KeystonePoolBehavior.replenish}
241
+ */
242
+ replenishStrategy?: KeystoneReplenishStrategy;
243
+ /**
244
+ * verbs for the pool
245
+ */
246
+ verbs?: string[];
247
+ hashAlgorithm?: HashAlgorithm;
248
+ hashRounds?: number;
249
+ }
250
+
251
+ export function createStandardPoolConfig(opts: KeystoneConfigFactoryOptions_Standard): KeystonePoolConfig {
252
+ let {
253
+ salt, id, size, sequential, random, targetBinding, replenishStrategy,
254
+ verbs, hashAlgorithm, hashRounds,
255
+ } = opts;
170
256
  return KeystoneConfig.hash()
257
+ .withId(id)
171
258
  .withSalt(salt)
172
- .withSize(100)
173
- .withHybrid(2, 2)
174
- .withReplenishStrategy('top-up')
259
+ .withSize(size ?? KEYSTONE_CONFIG_DEFAULT_SIZE)
260
+ .withHybrid({
261
+ seqCount: sequential ?? KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL,
262
+ randCount: random ?? KEYSTONE_CONFIG_DEFAULT_RANDOM,
263
+ })
264
+ .withTargetBinding(targetBinding ?? KEYSTONE_CONFIG_DEFAULT_BINDING)
265
+ .withReplenishStrategy(replenishStrategy ?? KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY)
266
+ .withHash({
267
+ algo: hashAlgorithm ?? KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM,
268
+ rounds: hashRounds ?? KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS
269
+ })
270
+ .forVerbs(verbs ?? [])
175
271
  .build();
176
272
  }
177
273
 
178
- export function createRevocationPoolConfig(salt: string = POOL_ID_REVOKE): KeystonePoolConfig {
274
+ export function createHighSecurityPoolConfig(opts: KeystoneConfigFactoryOptions_Standard): KeystonePoolConfig {
275
+ let {
276
+ salt, id, size, sequential, random, targetBinding, replenishStrategy,
277
+ verbs, hashAlgorithm, hashRounds,
278
+ } = opts;
179
279
  return KeystoneConfig.hash()
280
+ .withId(id)
180
281
  .withSalt(salt)
181
- .withHash('SHA-256', 10)
182
- .withSize(500)
183
- .withHybrid(10, 10)
184
- .withReplenishStrategy(KeystoneReplenishStrategy.scorchedEarth)
185
- .forVerbs([KEYSTONE_VERB_REVOKE])
282
+ .withSize(size ?? KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY)
283
+ .withHybrid({
284
+ seqCount: sequential ?? KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL_HIGHSECURITY,
285
+ randCount: random ?? KEYSTONE_CONFIG_DEFAULT_RANDOM_HIGHSECURITY,
286
+ })
287
+ .withTargetBinding(targetBinding ?? KEYSTONE_CONFIG_DEFAULT_BINDING_HIGHSECURITY)
288
+ .withReplenishStrategy(replenishStrategy ?? KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY_HIGHSECURITY)
289
+ .withHash({
290
+ algo: hashAlgorithm ?? KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM_HIGHSECURITY,
291
+ rounds: hashRounds ?? KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS_HIGHSECURITY
292
+ })
293
+ .forVerbs(verbs ?? [])
186
294
  .build();
187
295
  }
296
+
297
+ export function createManagePoolConfig(opts: KeystoneConfigFactoryOptions_Standard): KeystonePoolConfig {
298
+ return createHighSecurityPoolConfig({
299
+ ...opts,
300
+ verbs: [KeystoneVerb.MANAGE],
301
+ });
302
+ }
303
+
304
+ export function createRevocationPoolConfig(opts: KeystoneConfigFactoryOptions_Standard): KeystonePoolConfig {
305
+ return createHighSecurityPoolConfig({
306
+ ...opts,
307
+ verbs: [KeystoneVerb.REVOKE],
308
+ replenishStrategy: KeystoneReplenishStrategy.deleteAll,
309
+ });
310
+ }
@@ -5,9 +5,9 @@ const maam = `[${import.meta.url}]`, sir = maam;
5
5
  import { } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
6
 
7
7
  import { GLOBAL_LOG_A_LOT } from '../core-constants.mjs';
8
- import { KeystonePoolConfig_HashV1 } from './keystone-types.mjs';
8
+ import { KEYSTONE_REPLENISH_STRATEGY_DELETE_ALL, KeystoneChallengeType, KeystonePoolConfig_HashV1, KeystoneReplenishStrategy } from './keystone-types.mjs';
9
9
  import { createRevocationPoolConfig, createStandardPoolConfig } from './keystone-config-builder.mjs';
10
- import { KEYSTONE_VERB_REVOKE, } from './keystone-constants.mjs';
10
+ import { KEYSTONE_CONFIG_DEFAULT_RANDOM, KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY, KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL, KEYSTONE_CONFIG_DEFAULT_SIZE, KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY, KEYSTONE_VERB_REVOKE, POOL_ID_REVOKE, } from './keystone-constants.mjs';
11
11
 
12
12
  const logalot = GLOBAL_LOG_A_LOT;
13
13
 
@@ -15,32 +15,39 @@ const logalot = GLOBAL_LOG_A_LOT;
15
15
  await respecfully(sir, 'Config Builders', async () => {
16
16
 
17
17
  await ifWe(sir, 'createStandardPoolConfig defaults are correct', async () => {
18
- const config = createStandardPoolConfig("test_salt") as KeystonePoolConfig_HashV1;
18
+ const id = "test_id";
19
+ const salt = "test_salt";
20
+ const config = createStandardPoolConfig({ id, salt }) as KeystonePoolConfig_HashV1;
19
21
 
20
- iReckon(sir, config.salt).willEqual("test_salt");
21
- iReckon(sir, config.id).willEqual("test_salt");
22
- iReckon(sir, config.type).willEqual("hash-reveal-v1");
22
+ iReckon(sir, config.id).willEqual(id);
23
+ iReckon(sir, config.salt).willEqual(salt);
24
+ iReckon(sir, config.type).willEqual(KeystoneChallengeType.hash_reveal_v1);
23
25
 
24
26
  // Behavior check
25
27
  const b = config.behavior;
26
- iReckon(sir, b.size).willEqual(100);
27
- iReckon(sir, b.selectSequentially).willEqual(2);
28
- iReckon(sir, b.selectRandomly).willEqual(2);
29
- iReckon(sir, b.replenish).willEqual("top-up");
28
+ iReckon(sir, b.size).willEqual(KEYSTONE_CONFIG_DEFAULT_SIZE);
29
+ iReckon(sir, b.selectSequentially).willEqual(KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL);
30
+ iReckon(sir, b.selectRandomly).willEqual(KEYSTONE_CONFIG_DEFAULT_RANDOM);
31
+ iReckon(sir, b.replenish).willEqual(KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY);
30
32
 
31
33
  // Verbs should be empty/undefined (permissive)
32
34
  iReckon(sir, config.allowedVerbs.length).willEqual(0);
33
35
  });
34
36
 
35
37
  await ifWe(sir, 'createRevocationPoolConfig defaults are correct', async () => {
36
- const config = createRevocationPoolConfig("revoke_salt") as KeystonePoolConfig_HashV1;
38
+ const salt = "revoke_salt";
39
+ const config = createRevocationPoolConfig({
40
+ id: POOL_ID_REVOKE,
41
+ salt,
42
+ }) as KeystonePoolConfig_HashV1;
37
43
 
38
- iReckon(sir, config.salt).willEqual("revoke_salt");
44
+ iReckon(sir, config.id).willEqual(POOL_ID_REVOKE);
45
+ iReckon(sir, config.salt).willEqual(salt);
39
46
 
40
47
  // Behavior check
41
48
  const b = config.behavior;
42
- iReckon(sir, b.size).willEqual(500); // Higher security
43
- iReckon(sir, b.replenish).willEqual("scorched-earth");
49
+ iReckon(sir, b.size).willEqual(KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY); // Higher security
50
+ iReckon(sir, b.replenish).willEqual(KeystoneReplenishStrategy.deleteAll);
44
51
 
45
52
  // Verbs should be restricted
46
53
  iReckon(sir, config.allowedVerbs).includes(KEYSTONE_VERB_REVOKE);
@@ -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;
@@ -1,4 +1,5 @@
1
1
  import { extractErrorMsg, hash, pretty } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
2
+ import { GIB } from "@ibgib/ts-gib/dist/V1/constants.mjs";
2
3
  import { Ib, TransformResult } from "@ibgib/ts-gib/dist/types.mjs";
3
4
  import { getIbAndGib, getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
4
5
  import { validateIbGibIntrinsically } from "@ibgib/ts-gib/dist/V1/validate-helper.mjs";
@@ -8,10 +9,17 @@ import { getGib } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
8
9
 
9
10
  import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
10
11
  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";
12
+ import {
13
+ KeystoneData_V1, KeystoneIbGib_V1, KeystoneIb_V1, KeystoneChallengePool,
14
+ DeterministicResult, KeystoneProof, KeystonePoolConfig,
15
+ KeystoneReplenishStrategy, KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES,
16
+ KeystoneClaim, KeystoneSolution,
17
+ } from "./keystone-types.mjs";
12
18
  import { MetaspaceService } from "../witness/space/metaspace/metaspace-types.mjs";
13
19
  import { IbGibSpaceAny } from "../witness/space/space-base-v1.mjs";
14
20
  import { KeystoneStrategyFactory } from "./strategy/keystone-strategy-factory.mjs";
21
+ import { getDependencyGraph } from "../common/other/graph-helper.mjs";
22
+ import { getTimelinesGroupedByTjp, splitPerTjpAndOrDna } from "../common/other/ibgib-helper.mjs";
15
23
 
16
24
  const logalot = GLOBAL_LOG_A_LOT;
17
25
 
@@ -19,7 +27,7 @@ const logalot = GLOBAL_LOG_A_LOT;
19
27
  * space-delimited keystone ib containing select keystone metadata.
20
28
  *
21
29
  * NOTE: This must match {@link parseKeystoneIb}
22
- * @see {@link KeystoneIbInfo_V1}
30
+ * @see {@link KeystoneIb_V1}
23
31
  */
24
32
  export async function getKeystoneIb({
25
33
  keystoneData,
@@ -47,13 +55,13 @@ export async function getKeystoneIb({
47
55
 
48
56
  /**
49
57
  * NOTE: This must match {@link getKeystoneIb}
50
- * @see {@link KeystoneIbInfo_V1}
58
+ * @see {@link KeystoneIb_V1}
51
59
  */
52
60
  export async function parseKeystoneIb({
53
61
  ib,
54
62
  }: {
55
63
  ib: Ib,
56
- }): Promise<KeystoneIbInfo_V1> {
64
+ }): Promise<KeystoneIb_V1> {
57
65
  const lc = `[${parseKeystoneIb.name}]`;
58
66
  try {
59
67
  if (logalot) { console.log(`${lc} starting... (I: 73cb6832984255ed48b2f44db6a21e25)`); }
@@ -123,7 +131,9 @@ export function getDeterministicRequirements({
123
131
  const { gib } = getIbAndGib({ ibGibAddr: targetAddr });
124
132
  if (gib) {
125
133
  // Get required hex prefixes (e.g. 'a', 'b', 'c', '1')
126
- const prefixes = gib.substring(0, behavior.targetBindingChars).toLowerCase();
134
+ const prefixes = gib !== GIB ?
135
+ gib.substring(0, behavior.targetBindingChars).toLowerCase() :
136
+ 'abc'; // arbitrary for primitive binding target ibgib
127
137
 
128
138
  for (const char of prefixes) {
129
139
  // Look in the Explicit Bucket
@@ -200,7 +210,7 @@ export function removeFromBindingMap(
200
210
 
201
211
  /**
202
212
  * Selects the specific pool to use for an operation based on ID, filter criteria, or verb authorization.
203
- *
213
+ *
204
214
  * @returns The matching KeystoneChallengePool
205
215
  * @throws If no pool matches or if multiple pools match but one was expected.
206
216
  */
@@ -216,7 +226,7 @@ export function resolveTargetPool({
216
226
  */
217
227
  poolId?: string;
218
228
  /**
219
- * Optional predicate to find a pool.
229
+ * Optional predicate to find a pool.
220
230
  * Useful for finding delegates via metadata.
221
231
  */
222
232
  poolFilter?: (pool: KeystoneChallengePool) => boolean;
@@ -276,7 +286,7 @@ export function resolveTargetPool({
276
286
  /**
277
287
  * Calculates the complete list of Challenge IDs to solve for a given operation.
278
288
  * Combines Deterministic requirements (Mandatory/Binding/FIFO) with Stochastic requirements.
279
- *
289
+ *
280
290
  * @returns Array of unique challenge IDs.
281
291
  */
282
292
  export function selectChallengeIds({
@@ -312,7 +322,7 @@ export function selectChallengeIds({
312
322
  throw new Error(`Insufficient challenges for random requirement. Need ${randomCount}, have ${availableIds.length} (E: 9f7a67428515c1e82813158581898125)`);
313
323
  }
314
324
  // Shuffle & Pick
315
- // Note: simple Math.random sort is sufficient for V1 stochastic selection
325
+ // Note: simple Math.random sort is sufficient for V1 stochastic selection
316
326
  // as we are just picking from valid available options.
317
327
  const shuffled = [...availableIds].sort(() => 0.5 - Math.random());
318
328
  randomIds.push(...shuffled.slice(0, randomCount));
@@ -347,7 +357,7 @@ export async function generateOpaqueChallengeId({
347
357
  /**
348
358
  * Calculates the NEXT state of the Challenge Pools given a specific consumption event.
349
359
  * Handles TopUp, ReplaceAll, Consume, and ScorchedEarth strategies.
350
- *
360
+ *
351
361
  * @returns The new array of KeystoneChallengePools (including the modified one).
352
362
  */
353
363
  export async function applyReplenishmentStrategy({
@@ -420,7 +430,7 @@ export async function applyReplenishmentStrategy({
420
430
  }
421
431
  } else if (strategyType === KeystoneReplenishStrategy.consume) {
422
432
  consumedIds.forEach(id => delete pool.challenges[id]);
423
- } else if (strategyType === KeystoneReplenishStrategy.scorchedEarth) {
433
+ } else if (strategyType === KeystoneReplenishStrategy.deleteAll) {
424
434
  pool.challenges = {};
425
435
  pool.bindingMap = {};
426
436
  } else {
@@ -441,7 +451,7 @@ export async function applyReplenishmentStrategy({
441
451
  * 3. Solves Challenges (Generates Solutions).
442
452
  * 4. Replenishes Pool (Calculates the next state of ALL pools).
443
453
  * 5. Constructs Proof.
444
- *
454
+ *
445
455
  * @returns The resulting Proof and the full list of Next Pools.
446
456
  */
447
457
  export async function solveAndReplenish({
@@ -512,7 +522,7 @@ export async function solveAndReplenish({
512
522
  /**
513
523
  * Validates the transition from Prev -> Curr.
514
524
  * Enforces Cryptography AND Behavioral Policy.
515
- *
525
+ *
516
526
  * @returns Array of validation error strings. Empty array means Valid.
517
527
  */
518
528
  export async function validateKeystoneTransition({
@@ -525,7 +535,9 @@ export async function validateKeystoneTransition({
525
535
  const lc = `[${validateKeystoneTransition.name}]`;
526
536
  const errors: string[] = [];
527
537
  try {
528
- if (!currentIbGib) { throw new Error(`(UNEXPECTED) currentIbGib falsy? (E: 3c0f02655fa8279e386a079ebb604b25)`); }
538
+ if (!currentIbGib) {
539
+ throw new Error(`(UNEXPECTED) currentIbGib falsy? (E: 3c0f02655fa8279e386a079ebb604b25)`);
540
+ }
529
541
  if (!prevIbGib) { throw new Error(`(UNEXPECTED) prevIbGib falsy? (E: 0d07c812634d839c784f31b8848ba825)`); }
530
542
 
531
543
  // intrinsic validation
@@ -777,4 +789,78 @@ export async function createKeystoneIbGibImpl({
777
789
  } finally {
778
790
  if (logalot) { console.log(`${lc} complete.`); }
779
791
  }
792
+ }
793
+
794
+ export async function validateKeystoneGraph({
795
+ keystoneIbGib,
796
+ space,
797
+ }: {
798
+ keystoneIbGib: KeystoneIbGib_V1,
799
+ space: IbGibSpaceAny,
800
+ }): Promise<string[]> {
801
+ const lc = `[${validateKeystoneGraph.name}]`;
802
+ try {
803
+ if (logalot) { console.log(`${lc} starting... (I: 22e1ca1d5a08a3f90b7fe9da95df7b26)`); }
804
+
805
+ // maybe too defensive but...
806
+ if (!keystoneIbGib) { throw new Error(`(UNEXPECTED) keystoneIbGib falsy? (E: 26482871d529fff6e8899c5d8a6c3826)`); }
807
+
808
+ const errors: string[] = [];
809
+
810
+ const dependencyGraph = await getDependencyGraph({
811
+ ibGib: keystoneIbGib,
812
+ space,
813
+ });
814
+
815
+ const depIbGibs = Object.values(dependencyGraph);
816
+ const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps, } =
817
+ splitPerTjpAndOrDna({ ibGibs: depIbGibs });
818
+
819
+
820
+ // there should be no DNA
821
+ if (Object.keys(mapWithTjp_YesDna).length > 0) {
822
+ errors.push(`${lc} DNA found. Keystones should NOT have DNA. (E: a3ec7827c4284cdea61c2372c0615826)`);
823
+ }
824
+
825
+ // is there a tjp? I think there is, so mapWithoutTjps should also be
826
+ // empty
827
+ if (Object.keys(mapWithoutTjps).length > 0) {
828
+ errors.push(`${lc} Non-tjp ibgibs found? Keystones are expected to have tjps. (E: a3ec7827c4284cdea61c2372c0615826)`);
829
+ }
830
+
831
+ if (Object.keys(mapWithTjp_NoDna).length > 0) {
832
+ // happy path here. These should be the keystone ibgibs. we will put
833
+ // them in order, then do validation on the transitions. We will
834
+ // also check other graph-scoped integrity of keystones (like do
835
+ // certain properties match among ALL keystones, etc.)
836
+
837
+ const keystoneIbGibs_unordered = Object.values(mapWithTjp_NoDna);
838
+
839
+ const orderedKeystonesMap = getTimelinesGroupedByTjp({ ibGibs: keystoneIbGibs_unordered });
840
+ const keys = Object.keys(orderedKeystonesMap);
841
+ if (keys.length === 0) {
842
+ throw new Error(`(UNEXPECTED) orderedKeystonesMap empty? (E: d437b80bef58e83a034b28af46278726)`);
843
+ } else if (keys.length > 0) {
844
+ // keys.length > 0
845
+ throw new Error(`(UNEXPECTED) more than one timeline in keystone graph? ATOW (02/19/2026) we are expecting only a single timeline. (E: 66085b14e3887a59c872afd240511f26)`);
846
+ }
847
+ // happy path: exactly one timeline
848
+ const keystoneTjpAddr = keys[0];
849
+ const keystoneIbGibs_ordered = orderedKeystonesMap[keystoneTjpAddr];
850
+
851
+ } else {
852
+ // one of the other errors regarding mapWithTjp_YesDna or
853
+ // mapWithoutTjps will exist at this point, so we don't need to add
854
+ // any more errors.
855
+ if (errors.length === 0) { throw new Error(`(UNEXPECTED) mapWithTjp_NoDna empty (which is an error) but errors.length === 0? If we get here, we expect one of the other errors to have been populated. (E: 7bca2866b6f8fca318923de8c88e8826)`); }
856
+ }
857
+
858
+ return errors;
859
+
860
+ } catch (error) {
861
+ console.error(`${lc} ${extractErrorMsg(error)}`);
862
+ throw error;
863
+ } finally {
864
+ if (logalot) { console.log(`${lc} complete.`); }
865
+ }
780
866
  }