@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.
- package/dist/keystone/kdf/kdf-constants.d.mts +25 -0
- package/dist/keystone/kdf/kdf-constants.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-constants.mjs +28 -0
- package/dist/keystone/kdf/kdf-constants.mjs.map +1 -0
- package/dist/keystone/kdf/kdf-helpers.d.mts +45 -0
- package/dist/keystone/kdf/kdf-helpers.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-helpers.mjs +94 -0
- package/dist/keystone/kdf/kdf-helpers.mjs.map +1 -0
- package/dist/keystone/kdf/kdf-types.d.mts +49 -0
- package/dist/keystone/kdf/kdf-types.d.mts.map +1 -0
- package/dist/keystone/kdf/kdf-types.mjs +2 -0
- package/dist/keystone/kdf/kdf-types.mjs.map +1 -0
- package/dist/keystone/keystone-config-builder.d.mts +65 -12
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +138 -46
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.respec.mjs +21 -13
- package/dist/keystone/keystone-config-builder.respec.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +15 -0
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +16 -0
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +8 -4
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +76 -6
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts +1 -1
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +6 -5
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +72 -45
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +28 -18
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/keystone-types.mjs +26 -15
- package/dist/keystone/keystone-types.mjs.map +1 -1
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.d.mts.map +1 -1
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs +7 -10
- package/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs.map +1 -1
- package/dist/sync/sync-constants.d.mts +9 -0
- package/dist/sync/sync-constants.d.mts.map +1 -1
- package/dist/sync/sync-constants.mjs +10 -0
- package/dist/sync/sync-constants.mjs.map +1 -1
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +49 -19
- package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +3 -3
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +0 -38
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +1 -83
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +24 -4
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +36 -13
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +246 -38
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -7
- package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
- package/dist/sync/sync-types.d.mts +11 -0
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/dist/sync/sync-types.mjs.map +1 -1
- package/package.json +1 -1
- package/src/keystone/README.md +4 -3
- package/src/keystone/docs/architecture.md +3 -1
- package/src/keystone/kdf/kdf-constants.mts +34 -0
- package/src/keystone/kdf/kdf-helpers.mts +105 -0
- package/src/keystone/kdf/kdf-types.mts +58 -0
- package/src/keystone/keystone-config-builder.mts +170 -47
- package/src/keystone/keystone-config-builder.respec.mts +21 -14
- package/src/keystone/keystone-constants.mts +21 -2
- package/src/keystone/keystone-helpers.mts +100 -14
- package/src/keystone/keystone-service-v1.mts +23 -22
- package/src/keystone/keystone-service-v1.respec.mts +71 -44
- package/src/keystone/keystone-types.mts +37 -23
- package/src/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mts +9 -13
- package/src/sync/sync-constants.mts +12 -0
- package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +53 -20
- package/src/sync/sync-peer/sync-peer-v1.mts +3 -3
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +3 -107
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +25 -4
- package/src/sync/sync-saga-coordinator.mts +313 -40
- package/src/sync/sync-saga-message/sync-saga-message-types.mts +1 -7
- package/src/sync/sync-types.mts +12 -0
- 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
|
-
|
|
4
|
-
KeystonePoolBehavior,
|
|
5
|
-
KeystoneReplenishStrategy,
|
|
6
|
-
KeystonePoolConfigBase
|
|
5
|
+
KeystonePoolConfig, KeystonePoolConfig_HashV1, KeystonePoolBehavior,
|
|
6
|
+
KeystoneReplenishStrategy, KeystonePoolConfigBase, KeystoneChallengeType,
|
|
7
7
|
} from './keystone-types.mjs';
|
|
8
|
-
import {
|
|
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
|
|
18
|
-
protected
|
|
19
|
-
protected
|
|
20
|
-
protected
|
|
21
|
-
protected
|
|
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
|
|
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
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
128
|
-
private
|
|
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:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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(
|
|
173
|
-
.withHybrid(
|
|
174
|
-
|
|
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
|
|
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
|
-
.
|
|
182
|
-
.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
|
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.
|
|
21
|
-
iReckon(sir, config.
|
|
22
|
-
iReckon(sir, config.type).willEqual(
|
|
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(
|
|
27
|
-
iReckon(sir, b.selectSequentially).willEqual(
|
|
28
|
-
iReckon(sir, b.selectRandomly).willEqual(
|
|
29
|
-
iReckon(sir, b.replenish).willEqual(
|
|
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
|
|
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.
|
|
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(
|
|
43
|
-
iReckon(sir, b.replenish).willEqual(
|
|
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 {
|
|
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
|
|
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
|
|
58
|
+
* @see {@link KeystoneIb_V1}
|
|
51
59
|
*/
|
|
52
60
|
export async function parseKeystoneIb({
|
|
53
61
|
ib,
|
|
54
62
|
}: {
|
|
55
63
|
ib: Ib,
|
|
56
|
-
}): Promise<
|
|
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
|
|
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.
|
|
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) {
|
|
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
|
}
|