@ibgib/core-gib 0.1.60 → 0.1.62
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/CHANGELOG.md +16 -0
- package/dist/common/other/graph-helper.d.mts.map +1 -1
- package/dist/common/other/graph-helper.mjs +7 -6
- package/dist/common/other/graph-helper.mjs.map +1 -1
- package/dist/keystone/keystone-config-builder.d.mts +1 -2
- package/dist/keystone/keystone-config-builder.d.mts.map +1 -1
- package/dist/keystone/keystone-config-builder.mjs +4 -19
- package/dist/keystone/keystone-config-builder.mjs.map +1 -1
- package/dist/keystone/keystone-constants.d.mts +2 -1
- package/dist/keystone/keystone-constants.d.mts.map +1 -1
- package/dist/keystone/keystone-constants.mjs +2 -1
- package/dist/keystone/keystone-constants.mjs.map +1 -1
- package/dist/keystone/keystone-helpers.d.mts +28 -16
- package/dist/keystone/keystone-helpers.d.mts.map +1 -1
- package/dist/keystone/keystone-helpers.mjs +155 -76
- package/dist/keystone/keystone-helpers.mjs.map +1 -1
- package/dist/keystone/keystone-policy-types.d.mts +6 -4
- package/dist/keystone/keystone-policy-types.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.d.mts +38 -2
- package/dist/keystone/keystone-service-v1.d.mts.map +1 -1
- package/dist/keystone/keystone-service-v1.mjs +177 -11
- package/dist/keystone/keystone-service-v1.mjs.map +1 -1
- package/dist/keystone/keystone-service-v1.respec.mjs +527 -41
- package/dist/keystone/keystone-service-v1.respec.mjs.map +1 -1
- package/dist/keystone/keystone-types.d.mts +53 -11
- package/dist/keystone/keystone-types.d.mts.map +1 -1
- package/dist/keystone/policy/keystone-profile-builder.d.mts +25 -0
- package/dist/keystone/policy/keystone-profile-builder.d.mts.map +1 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs +117 -0
- package/dist/keystone/policy/keystone-profile-builder.mjs.map +1 -0
- package/dist/keystone/policy/profiles/profile-high.json +84 -0
- package/dist/keystone/policy/profiles/profile-low.json +84 -0
- package/dist/keystone/policy/profiles/profile-medium.json +84 -0
- package/dist/keystone/policy/profiles/profile-session.json +84 -0
- package/dist/keystone/policy/profiles/profile-test.json +84 -0
- package/dist/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/dist/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/dist/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/dist/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs +582 -0
- package/dist/sync/sync-conflict-adv-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs +274 -0
- package/dist/sync/sync-conflict-basic-divergence.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts +8 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs +322 -0
- package/dist/sync/sync-conflict-basic-multitimelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts +7 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs +307 -0
- package/dist/sync/sync-conflict-text-merge.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-constants.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs +233 -0
- package/dist/sync/sync-innerspace-deep-updates.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs +225 -0
- package/dist/sync/sync-innerspace-dest-ahead.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs +235 -0
- package/dist/sync/sync-innerspace-multiple-timelines.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts +7 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs +211 -0
- package/dist/sync/sync-innerspace-partial-update.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts +8 -0
- package/dist/sync/sync-innerspace.withid.respec.d.mts.map +1 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs +260 -0
- package/dist/sync/sync-innerspace.withid.respec.mjs.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs +13 -4
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs +5 -3
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +165 -145
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-withid.pingpong.respec.mjs +8 -8
- package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -1
- package/dist/timeline/timeline-api.d.mts.map +1 -1
- package/dist/timeline/timeline-api.mjs +1 -14
- package/dist/timeline/timeline-api.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs +0 -40
- package/dist/witness/space/reconciliation-space/reconciliation-space-base.mjs.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.d.mts.map +1 -1
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs +6 -6
- package/dist/witness/space/reconciliation-space/reconciliation-space-helper.mjs.map +1 -1
- package/ibgib-foundations.md +2 -1
- package/package.json +1 -1
- package/src/common/other/graph-helper.mts +7 -6
- package/src/keystone/README.md +34 -17
- package/src/keystone/docs/CRYPTANALYSIS.md +185 -0
- package/src/keystone/docs/architecture.md +45 -3
- package/src/keystone/docs/delegation.md +57 -0
- package/src/keystone/docs/profiles.md +124 -0
- package/src/keystone/keystone-config-builder.mts +3 -21
- package/src/keystone/keystone-constants.mts +2 -1
- package/src/keystone/keystone-helpers.mts +204 -81
- package/src/keystone/keystone-policy-types.mts +6 -4
- package/src/keystone/keystone-service-v1.mts +223 -11
- package/src/keystone/keystone-service-v1.respec.mts +596 -39
- package/src/keystone/keystone-types.mts +55 -9
- package/src/keystone/policy/IMPLEMENTATION.md +60 -0
- package/src/keystone/policy/README.md +94 -0
- package/src/keystone/policy/keystone-profile-builder.mts +131 -0
- package/src/keystone/policy/profiles/profile-high.json +84 -0
- package/src/keystone/policy/profiles/profile-low.json +84 -0
- package/src/keystone/policy/profiles/profile-medium.json +84 -0
- package/src/keystone/policy/profiles/profile-session.json +84 -0
- package/src/keystone/policy/profiles/profile-test.json +84 -0
- package/src/keystone/policy/schemas/connect-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/connect-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/keystone.high.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.low.schema.json +26 -0
- package/src/keystone/policy/schemas/keystone.medium.schema.json +26 -0
- package/src/keystone/policy/schemas/manage-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/manage-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/revoke-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sign-pool.medium.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.high.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.low.schema.json +23 -0
- package/src/keystone/policy/schemas/sync-pool.medium.schema.json +23 -0
- package/src/sync/docs/security.md +54 -21
- package/src/sync/sync-conflict-adv-multitimelines.withid.respec.mts +706 -0
- package/src/sync/sync-conflict-basic-divergence.withid.respec.mts +321 -0
- package/src/sync/sync-conflict-basic-multitimelines.withid.respec.mts +374 -0
- package/src/sync/sync-conflict-text-merge.withid.respec.mts +347 -0
- package/src/sync/sync-innerspace-constants.withid.respec.mts +264 -0
- package/src/sync/sync-innerspace-deep-updates.withid.respec.mts +272 -0
- package/src/sync/sync-innerspace-dest-ahead.withid.respec.mts +266 -0
- package/src/sync/sync-innerspace-multiple-timelines.respec.mts +0 -1
- package/src/sync/sync-innerspace-multiple-timelines.withid.respec.mts +273 -0
- package/src/sync/sync-innerspace-partial-update.withid.respec.mts +249 -0
- package/src/sync/sync-innerspace.withid.respec.mts +265 -0
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mts +12 -4
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mts +5 -3
- package/src/sync/sync-saga-coordinator.mts +159 -143
- package/src/sync/sync-withid.pingpong.respec.mts +8 -8
- package/src/timeline/timeline-api.mts +1 -15
- package/src/timeline/timeline-api.respec.mts +3 -3
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts +0 -46
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts +6 -5
- package/tsconfig.json +6 -1
- package/src/keystone/keystone-policy.schema.json +0 -51
- package/src/witness/space/reconciliation-space/reconciliation-space-base.mts.OLD.md +0 -884
- package/src/witness/space/reconciliation-space/reconciliation-space-helper.mts.OLD.md +0 -125
|
@@ -8,7 +8,7 @@ import { Factory_V1 } from "@ibgib/ts-gib/dist/V1/factory.mjs";
|
|
|
8
8
|
import { getGib } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
|
|
9
9
|
|
|
10
10
|
import { GLOBAL_LOG_A_LOT } from "../core-constants.mjs";
|
|
11
|
-
import { KEYSTONE_ATOM, KEYSTONE_HASH_MAX_ROUNDS, KEYSTONE_POOL_ID_REGEXP, KEYSTONE_SALT_REGEXP } from "./keystone-constants.mjs";
|
|
11
|
+
import { KEYSTONE_ATOM, KEYSTONE_HASH_MAX_ROUNDS, KEYSTONE_POOL_ID_REGEXP, KEYSTONE_SALT_REGEXP, KEYSTONE_USERNAME_REGEXP, KEYSTONE_DESCRIPTION_REGEXP, KEYSTONE_VERB_MANAGE } from "./keystone-constants.mjs";
|
|
12
12
|
import {
|
|
13
13
|
KeystoneData_V1, KeystoneIbGib_V1, KeystoneIb_V1, KeystoneChallengePool,
|
|
14
14
|
DeterministicResult, KeystoneProof, KeystonePoolConfig,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
KeystoneChallengeType,
|
|
18
18
|
KEYSTONE_CHALLENGE_TYPE_VALID_VALUES,
|
|
19
19
|
KeystonePoolConfig_HashV1,
|
|
20
|
+
DelegateKeystoneInfo,
|
|
20
21
|
} from "./keystone-types.mjs";
|
|
21
22
|
import { MetaspaceService } from "../witness/space/metaspace/metaspace-types.mjs";
|
|
22
23
|
import { IbGibSpaceAny } from "../witness/space/space-base-v1.mjs";
|
|
@@ -90,12 +91,28 @@ export async function parseKeystoneIb({
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Helper to validate if an ib string is a well-formed keystone ib.
|
|
96
|
+
*/
|
|
97
|
+
export async function validateKeystoneIb({
|
|
98
|
+
ib,
|
|
99
|
+
}: {
|
|
100
|
+
ib: Ib,
|
|
101
|
+
}): Promise<boolean> {
|
|
102
|
+
try {
|
|
103
|
+
await parseKeystoneIb({ ib });
|
|
104
|
+
return true;
|
|
105
|
+
} catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
93
110
|
/**
|
|
94
111
|
* The Policy Engine.
|
|
95
112
|
* Calculates exactly which challenges MUST be consumed based on config and demands.
|
|
96
113
|
* Enforces STRICT DISTINCTNESS (No double-dipping).
|
|
97
114
|
*/
|
|
98
|
-
export function getDeterministicRequirements({
|
|
115
|
+
export async function getDeterministicRequirements({
|
|
99
116
|
pool,
|
|
100
117
|
requiredChallengeIds,
|
|
101
118
|
targetAddr
|
|
@@ -103,7 +120,7 @@ export function getDeterministicRequirements({
|
|
|
103
120
|
pool: KeystoneChallengePool;
|
|
104
121
|
requiredChallengeIds?: string[];
|
|
105
122
|
targetAddr?: string;
|
|
106
|
-
}): DeterministicResult {
|
|
123
|
+
}): Promise<DeterministicResult> {
|
|
107
124
|
const behavior = pool.config.behavior;
|
|
108
125
|
const mandatory = new Set<string>();
|
|
109
126
|
|
|
@@ -131,31 +148,34 @@ export function getDeterministicRequirements({
|
|
|
131
148
|
}
|
|
132
149
|
|
|
133
150
|
// ---------------------------------------------------------
|
|
134
|
-
// 2. Target Binding (
|
|
151
|
+
// 2. Target Binding (Drawing Without Replacement)
|
|
135
152
|
// ---------------------------------------------------------
|
|
136
|
-
if (behavior.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// Get required hex prefixes (e.g. 'a', 'b', 'c', '1')
|
|
140
|
-
const prefixes = gib !== GIB ?
|
|
141
|
-
gib.substring(0, behavior.targetBindingChars).toLowerCase() :
|
|
142
|
-
'abc'; // arbitrary for primitive binding target ibgib
|
|
143
|
-
|
|
144
|
-
for (const char of prefixes) {
|
|
145
|
-
// Look in the Explicit Bucket
|
|
146
|
-
const bucket = pool.bindingMap[char] || [];
|
|
147
|
-
|
|
148
|
-
// Find the first ID in this bucket that is still in 'available'
|
|
149
|
-
const match = bucket.find(id => available.includes(id));
|
|
150
|
-
|
|
151
|
-
if (!match) {
|
|
152
|
-
throw new Error(`Entropy Exhaustion. Cannot satisfy binding for char '${char}'. (E: 341b95dc3a58be3e083d1d9c4a0c4925)`);
|
|
153
|
-
}
|
|
153
|
+
if (behavior.targetBindingCount > 0 && targetAddr) {
|
|
154
|
+
// Sort remaining available IDs alphabetically to ensure stable ordering across platforms
|
|
155
|
+
let sortedAvailable = [...available].sort();
|
|
154
156
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
// Start hashing path from targetAddr
|
|
158
|
+
let currentHash = await hash({ s: targetAddr });
|
|
159
|
+
|
|
160
|
+
for (let i = 0; i < behavior.targetBindingCount; i++) {
|
|
161
|
+
if (sortedAvailable.length === 0) {
|
|
162
|
+
throw new Error(`Entropy Exhaustion. Cannot satisfy target binding. Sorted available pool is empty. (E: 341b95dc3a58be3e083d1d9c4a0c4925)`);
|
|
158
163
|
}
|
|
164
|
+
|
|
165
|
+
// Parse the entire hash via BigInt to eliminate modulo bias
|
|
166
|
+
const hashBigInt = BigInt("0x" + currentHash);
|
|
167
|
+
const index = Number(hashBigInt % BigInt(sortedAvailable.length));
|
|
168
|
+
const selectedId = sortedAvailable[index];
|
|
169
|
+
|
|
170
|
+
// Consume selected challenge ID
|
|
171
|
+
mandatory.add(selectedId);
|
|
172
|
+
sortedAvailable.splice(index, 1);
|
|
173
|
+
|
|
174
|
+
// Filter out of insertion-ordered available list (for FIFO)
|
|
175
|
+
available = available.filter(id => id !== selectedId);
|
|
176
|
+
|
|
177
|
+
// Hash recursively for the next draw
|
|
178
|
+
currentHash = await hash({ s: currentHash });
|
|
159
179
|
}
|
|
160
180
|
}
|
|
161
181
|
|
|
@@ -179,42 +199,7 @@ export function getDeterministicRequirements({
|
|
|
179
199
|
return { mandatoryIds: mandatory, availableIds: available };
|
|
180
200
|
}
|
|
181
201
|
|
|
182
|
-
/**
|
|
183
|
-
* Helper to update the Binding Map when adding new Challenge IDs.
|
|
184
|
-
* Uses "Implicit Bucketing" (ID start char) but can be extended for full coverage.
|
|
185
|
-
*/
|
|
186
|
-
export function addToBindingMap(
|
|
187
|
-
map: { [char: string]: string[] },
|
|
188
|
-
challengeId: string
|
|
189
|
-
): void {
|
|
190
|
-
const firstChar = challengeId.charAt(0).toLowerCase();
|
|
191
|
-
// Validate it is hex
|
|
192
|
-
if (/[0-9a-f]/.test(firstChar)) {
|
|
193
|
-
if (!map[firstChar]) { map[firstChar] = []; }
|
|
194
|
-
map[firstChar].push(challengeId);
|
|
195
|
-
|
|
196
|
-
// OPTIONAL: Implement Full Coverage Strategy here?
|
|
197
|
-
// e.g. map[challengeId[1]].push(challengeId) ...
|
|
198
|
-
// For V1, we stick to Native/Implicit bucket (Index 0).
|
|
199
|
-
} else {
|
|
200
|
-
throw new Error(`invalid challengeId (${challengeId}). Must start with a hex character. (E: c96ed8460de89e28c801370a0f07f826)`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
202
|
|
|
204
|
-
/**
|
|
205
|
-
* Helper to clean up Binding Map when removing IDs.
|
|
206
|
-
*/
|
|
207
|
-
export function removeFromBindingMap(
|
|
208
|
-
map: { [char: string]: string[] },
|
|
209
|
-
challengeId: string
|
|
210
|
-
): void {
|
|
211
|
-
// Since we don't know exactly which buckets an ID is in (if we did multi-bucket),
|
|
212
|
-
// we strictly should scan all. For V1 Native, we check first char.
|
|
213
|
-
// SAFE IMPLEMENTATION: Scan all buckets.
|
|
214
|
-
for (const key of Object.keys(map)) {
|
|
215
|
-
map[key] = map[key].filter(id => id !== challengeId);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
203
|
|
|
219
204
|
/**
|
|
220
205
|
* Selects the specific pool to use for an operation based on ID, filter criteria, or verb authorization.
|
|
@@ -297,7 +282,7 @@ export function resolveTargetPool({
|
|
|
297
282
|
*
|
|
298
283
|
* @returns Array of unique challenge IDs.
|
|
299
284
|
*/
|
|
300
|
-
export function selectChallengeIds({
|
|
285
|
+
export async function selectChallengeIds({
|
|
301
286
|
pool,
|
|
302
287
|
targetAddr,
|
|
303
288
|
requiredChallengeIds,
|
|
@@ -311,11 +296,11 @@ export function selectChallengeIds({
|
|
|
311
296
|
* Explicit demands from a verifier.
|
|
312
297
|
*/
|
|
313
298
|
requiredChallengeIds?: string[];
|
|
314
|
-
}): string[] {
|
|
299
|
+
}): Promise<string[]> {
|
|
315
300
|
const lc = `[selectChallengeIds]`;
|
|
316
301
|
try {
|
|
317
302
|
// 1. Get Deterministic Requirements
|
|
318
|
-
const { mandatoryIds, availableIds } = getDeterministicRequirements({
|
|
303
|
+
const { mandatoryIds, availableIds } = await getDeterministicRequirements({
|
|
319
304
|
pool,
|
|
320
305
|
requiredChallengeIds,
|
|
321
306
|
targetAddr
|
|
@@ -398,11 +383,6 @@ export async function applyReplenishmentStrategy({
|
|
|
398
383
|
|
|
399
384
|
const strategyType = config.behavior.replenish;
|
|
400
385
|
|
|
401
|
-
// Clean up Binding Map for consumed IDs
|
|
402
|
-
consumedIds.forEach(id => {
|
|
403
|
-
if (pool.bindingMap) { removeFromBindingMap(pool.bindingMap, id); }
|
|
404
|
-
});
|
|
405
|
-
|
|
406
386
|
if (strategyType === KeystoneReplenishStrategy.topUp) {
|
|
407
387
|
// Remove consumed
|
|
408
388
|
consumedIds.forEach(id => delete pool.challenges[id]);
|
|
@@ -417,14 +397,9 @@ export async function applyReplenishmentStrategy({
|
|
|
417
397
|
poolSecret, poolId: pool.id, challengeId: newId
|
|
418
398
|
});
|
|
419
399
|
pool.challenges[newId] = await strategy.generateChallenge({ solution });
|
|
420
|
-
|
|
421
|
-
// Update Binding Map
|
|
422
|
-
if (!pool.bindingMap) { pool.bindingMap = {}; }
|
|
423
|
-
addToBindingMap(pool.bindingMap, newId);
|
|
424
400
|
}
|
|
425
401
|
} else if (strategyType === KeystoneReplenishStrategy.replaceAll) {
|
|
426
402
|
pool.challenges = {};
|
|
427
|
-
pool.bindingMap = {};
|
|
428
403
|
|
|
429
404
|
for (let i = 0; i < config.behavior.size; i++) {
|
|
430
405
|
const newId = await generateOpaqueChallengeId({
|
|
@@ -434,13 +409,11 @@ export async function applyReplenishmentStrategy({
|
|
|
434
409
|
poolSecret, poolId: pool.id, challengeId: newId
|
|
435
410
|
});
|
|
436
411
|
pool.challenges[newId] = await strategy.generateChallenge({ solution });
|
|
437
|
-
addToBindingMap(pool.bindingMap, newId);
|
|
438
412
|
}
|
|
439
413
|
} else if (strategyType === KeystoneReplenishStrategy.consume) {
|
|
440
414
|
consumedIds.forEach(id => delete pool.challenges[id]);
|
|
441
415
|
} else if (strategyType === KeystoneReplenishStrategy.deleteAll) {
|
|
442
416
|
pool.challenges = {};
|
|
443
|
-
pool.bindingMap = {};
|
|
444
417
|
} else {
|
|
445
418
|
throw new Error(`Unknown replenish strategy: ${strategyType}. Valid list: ${pretty(KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES)} (E: 0acf56f1e1486240080e11e8046d0825)`);
|
|
446
419
|
}
|
|
@@ -599,10 +572,14 @@ export async function validateChallengePool({ pool }: {
|
|
|
599
572
|
}
|
|
600
573
|
|
|
601
574
|
if (pool.config.behavior) {
|
|
602
|
-
const { size } = pool.config.behavior;
|
|
575
|
+
const { size, selectSequentially, selectRandomly, targetBindingCount } = pool.config.behavior;
|
|
603
576
|
if (!size || size === 0) {
|
|
604
577
|
errors.push(`${lc} invalid pool.config.behavior.size (${size}). Must be positive integer. (E: b221e36ec102bdc944552248ce8fe626)`)
|
|
605
578
|
}
|
|
579
|
+
const totalRequested = (selectSequentially || 0) + (selectRandomly || 0) + (targetBindingCount || 0);
|
|
580
|
+
if (totalRequested >= size) {
|
|
581
|
+
errors.push(`${lc} Total requested challenges (${totalRequested}) cannot equal or exceed pool size (${size}) to prevent full pool exposure and selection exhaustion. (E: 81cb834f826315264bca81c15fca58f1)`);
|
|
582
|
+
}
|
|
606
583
|
// todo: more behavior checks
|
|
607
584
|
} else {
|
|
608
585
|
errors.push(`${lc} pool.config.behavior falsy (E: bede081c066c39732eefe2f92e296326)`)
|
|
@@ -632,6 +609,35 @@ export async function validateChallengePool({ pool }: {
|
|
|
632
609
|
}
|
|
633
610
|
|
|
634
611
|
|
|
612
|
+
export function validateKeystoneMetadata({
|
|
613
|
+
data
|
|
614
|
+
}: {
|
|
615
|
+
data: KeystoneData_V1;
|
|
616
|
+
}): string[] {
|
|
617
|
+
const lc = `[validateKeystoneMetadata]`;
|
|
618
|
+
const errors: string[] = [];
|
|
619
|
+
|
|
620
|
+
const checkDetails = (details: any, source: string) => {
|
|
621
|
+
if (!details) return;
|
|
622
|
+
if (details.username !== undefined) {
|
|
623
|
+
if (typeof details.username !== 'string' || !KEYSTONE_USERNAME_REGEXP.test(details.username)) {
|
|
624
|
+
errors.push(`${lc} invalid username in ${source} (${details.username}). Must match ${KEYSTONE_USERNAME_REGEXP}`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (details.description !== undefined) {
|
|
628
|
+
if (typeof details.description !== 'string' || !KEYSTONE_DESCRIPTION_REGEXP.test(details.description)) {
|
|
629
|
+
errors.push(`${lc} invalid description in ${source} (${details.description}). Must match ${KEYSTONE_DESCRIPTION_REGEXP}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
checkDetails(data.frameDetails, 'frameDetails');
|
|
635
|
+
checkDetails(data.checkpointDetails, 'checkpointDetails');
|
|
636
|
+
|
|
637
|
+
return errors;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
|
|
635
641
|
export async function validateGenesisKeystone({
|
|
636
642
|
keystoneIbGib
|
|
637
643
|
}: {
|
|
@@ -645,6 +651,15 @@ export async function validateGenesisKeystone({
|
|
|
645
651
|
|
|
646
652
|
const { data, rel8ns } = keystoneIbGib;
|
|
647
653
|
|
|
654
|
+
const isValidIb = await validateKeystoneIb({ ib: keystoneIbGib.ib });
|
|
655
|
+
if (!isValidIb) {
|
|
656
|
+
errors.push(`${lc} invalid keystone ib (${keystoneIbGib.ib}). (E: ad7a88bc38c290a184dfbd42be48f526)`);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Validate username/description metadata if present
|
|
660
|
+
const metadataErrors = validateKeystoneMetadata({ data });
|
|
661
|
+
metadataErrors.forEach(x => errors.push(x));
|
|
662
|
+
|
|
648
663
|
// no proofs/solutions yet
|
|
649
664
|
if (data.proofs && data.proofs.length > 0) {
|
|
650
665
|
errors.push(`${lc} proofs already exist on genesis keystone. (E: 7a5e15f20918f1bbd8ffb62857dcd526)`);
|
|
@@ -677,6 +692,89 @@ export async function validateGenesisKeystone({
|
|
|
677
692
|
}
|
|
678
693
|
}
|
|
679
694
|
|
|
695
|
+
/**
|
|
696
|
+
* Helper to determine if two delegates maps differ.
|
|
697
|
+
*/
|
|
698
|
+
export function isDelegatesChanged({
|
|
699
|
+
currDelegates,
|
|
700
|
+
prevDelegates,
|
|
701
|
+
}: {
|
|
702
|
+
currDelegates?: Record<string, DelegateKeystoneInfo>,
|
|
703
|
+
prevDelegates?: Record<string, DelegateKeystoneInfo>,
|
|
704
|
+
}): boolean {
|
|
705
|
+
const curr = currDelegates || {};
|
|
706
|
+
const prev = prevDelegates || {};
|
|
707
|
+
const currKeys = Object.keys(curr);
|
|
708
|
+
const prevKeys = Object.keys(prev);
|
|
709
|
+
|
|
710
|
+
if (currKeys.length !== prevKeys.length) { return true; }
|
|
711
|
+
|
|
712
|
+
for (const key of currKeys) {
|
|
713
|
+
const currVal = curr[key];
|
|
714
|
+
const prevVal = prev[key];
|
|
715
|
+
if (!prevVal) { return true; }
|
|
716
|
+
if (currVal.delegateTjpAddr !== prevVal.delegateTjpAddr ||
|
|
717
|
+
currVal.delegateAddr !== prevVal.delegateAddr ||
|
|
718
|
+
currVal.thisAddr !== prevVal.thisAddr) {
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Validates the structure and constraints of the delegates map.
|
|
728
|
+
*/
|
|
729
|
+
export async function validateDelegates({
|
|
730
|
+
currDelegates,
|
|
731
|
+
prevIbGib,
|
|
732
|
+
lc,
|
|
733
|
+
errors,
|
|
734
|
+
}: {
|
|
735
|
+
currDelegates: Record<string, DelegateKeystoneInfo>,
|
|
736
|
+
prevIbGib: KeystoneIbGib_V1,
|
|
737
|
+
lc: string,
|
|
738
|
+
errors: string[],
|
|
739
|
+
}): Promise<void> {
|
|
740
|
+
const currKeys = Object.keys(currDelegates);
|
|
741
|
+
const prevAddr = getIbGibAddr({ ibGib: prevIbGib });
|
|
742
|
+
|
|
743
|
+
for (const key of currKeys) {
|
|
744
|
+
const info = currDelegates[key];
|
|
745
|
+
if (key !== info.delegateTjpAddr) {
|
|
746
|
+
errors.push(`${lc} Invalid delegate mapping: Key '${key}' does not match delegateTjpAddr '${info.delegateTjpAddr}'. (E: 9c8da8bc38c290a184dfbd42be48f526)`);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Verify addresses are valid keystone addresses
|
|
750
|
+
const [
|
|
751
|
+
parsedDelegateTjp,
|
|
752
|
+
parsedDelegate,
|
|
753
|
+
parsedThis,
|
|
754
|
+
] = await Promise.all([
|
|
755
|
+
validateKeystoneIb({ ib: info.delegateTjpAddr.split('^')[0] }),
|
|
756
|
+
validateKeystoneIb({ ib: info.delegateAddr.split('^')[0] }),
|
|
757
|
+
validateKeystoneIb({ ib: info.thisAddr.split('^')[0] }),
|
|
758
|
+
]);
|
|
759
|
+
|
|
760
|
+
if (!parsedDelegateTjp) {
|
|
761
|
+
errors.push(`${lc} Delegate delegateTjpAddr '${info.delegateTjpAddr}' is not a valid keystone address. (E: 10d8a8bc38c290a184dfbd42be48f526)`);
|
|
762
|
+
}
|
|
763
|
+
if (!parsedDelegate) {
|
|
764
|
+
errors.push(`${lc} Delegate delegateAddr '${info.delegateAddr}' is not a valid keystone address. (E: 20d8a8bc38c290a184dfbd42be48f526)`);
|
|
765
|
+
}
|
|
766
|
+
if (!parsedThis) {
|
|
767
|
+
errors.push(`${lc} Delegate thisAddr '${info.thisAddr}' is not a valid keystone address. (E: 30d8a8bc38c290a184dfbd42be48f526)`);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Verify thisAddr is in the parent's past (or is the current parent address)
|
|
771
|
+
const isHistoricalParent = info.thisAddr === prevAddr || (prevIbGib.rel8ns?.past || []).includes(info.thisAddr);
|
|
772
|
+
if (!isHistoricalParent) {
|
|
773
|
+
errors.push(`${lc} Delegate thisAddr '${info.thisAddr}' is not a valid historical address in the parent keystone timeline. (E: 40d8a8bc38c290a184dfbd42be48f526)`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
680
778
|
/**
|
|
681
779
|
* Validates the transition from Prev -> Curr.
|
|
682
780
|
* Enforces Cryptography AND Behavioral Policy.
|
|
@@ -707,24 +805,48 @@ export async function validateKeystoneTransition({
|
|
|
707
805
|
const currData = currentIbGib.data!;
|
|
708
806
|
const prevData = prevIbGib.data!;
|
|
709
807
|
|
|
808
|
+
const isValidIb = await validateKeystoneIb({ ib: currentIbGib.ib });
|
|
809
|
+
if (!isValidIb) {
|
|
810
|
+
errors.push(`${lc} invalid keystone ib (${currentIbGib.ib}). (E: a98dc8bc38c290a184dfbd42be48f526)`);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Validate username/description metadata if present
|
|
814
|
+
const metadataErrors = validateKeystoneMetadata({ data: currData });
|
|
815
|
+
metadataErrors.forEach(x => errors.push(x));
|
|
816
|
+
|
|
817
|
+
// Validate delegates map mutations if present
|
|
818
|
+
const currDelegates = currData.delegates || {};
|
|
819
|
+
const prevDelegates = prevData.delegates || {};
|
|
820
|
+
const delegatesChanged = isDelegatesChanged({ currDelegates, prevDelegates });
|
|
821
|
+
|
|
822
|
+
if (delegatesChanged) {
|
|
823
|
+
const hasManageProof = currData.proofs?.some(proof => proof.claim?.verb === KEYSTONE_VERB_MANAGE);
|
|
824
|
+
if (!hasManageProof) {
|
|
825
|
+
errors.push(`${lc} Policy Violation: Delegates map was mutated but no proof for manage verb ('${KEYSTONE_VERB_MANAGE}') is present. (E: 819fa8cb28c9b60e68994511a5825)`);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Validate each delegate's structure and constraints
|
|
830
|
+
await validateDelegates({ currDelegates, prevIbGib, lc, errors });
|
|
831
|
+
|
|
710
832
|
// must be sequential data.n values
|
|
711
833
|
// note: "-2" because we don't want a "valid" sequential data.n if we
|
|
712
834
|
// have an invalid prev and a valid currDataN of 0
|
|
713
835
|
const currDataN = currData.n ?? -2;
|
|
714
836
|
const prevDataN = prevData.n ?? -2;
|
|
715
837
|
if (currDataN < 0) {
|
|
716
|
-
errors.push('invalid keystone.currData.n is undefined or null.');
|
|
838
|
+
errors.push('invalid keystone.currData.n is undefined or null. (E: 9fbe38704b68829d18ea1d0940d0aa26)');
|
|
717
839
|
}
|
|
718
840
|
if (prevDataN < 0) {
|
|
719
|
-
errors.push('invalid keystone.prevData.n is undefined or null.');
|
|
841
|
+
errors.push('invalid keystone.prevData.n is undefined or null. (E: 6dc5aa9c87017db6080ed4268b07af26)');
|
|
720
842
|
};
|
|
721
843
|
if (currDataN !== (prevDataN + 1)) {
|
|
722
|
-
errors.push(`keystone data.n values are not sequential. prevData.n: ${prevDataN}, currData.n: ${currDataN}. `);
|
|
844
|
+
errors.push(`keystone data.n values are not sequential. prevData.n: ${prevDataN}, currData.n: ${currDataN}. (E: 5ae12809f2c67216d38d8ba8d6c42826)`);
|
|
723
845
|
}
|
|
724
846
|
|
|
725
847
|
for (const proof of currData.proofs) {
|
|
726
848
|
if (proof.solutions.length === 0) {
|
|
727
|
-
errors.push(`Proof ${proof.id || 'unknown'} has no solutions
|
|
849
|
+
errors.push(`Proof ${proof.id || 'unknown'} has no solutions. (E: e2b4683ce0ce30f798ec77841e88c826)`);
|
|
728
850
|
continue;
|
|
729
851
|
}
|
|
730
852
|
|
|
@@ -784,7 +906,7 @@ export async function verifyProofAgainstPool({
|
|
|
784
906
|
}
|
|
785
907
|
|
|
786
908
|
// 1. Reconstruct Deterministic Requirements
|
|
787
|
-
const { mandatoryIds, availableIds } = getDeterministicRequirements({
|
|
909
|
+
const { mandatoryIds, availableIds } = await getDeterministicRequirements({
|
|
788
910
|
pool,
|
|
789
911
|
requiredChallengeIds: proof.requiredChallengeIds,
|
|
790
912
|
targetAddr: proof.claim.target // Not used extensively in V1 logic yet, mainly for logging/context
|
|
@@ -863,6 +985,7 @@ export async function evolvePersistAndRegisterKeystone({
|
|
|
863
985
|
if (prevData.challengePools) { dataToRemove.challengePools = []; }
|
|
864
986
|
if (prevData.frameDetails) { dataToRemove.frameDetails = {}; }
|
|
865
987
|
if (prevData.checkpointDetails) { dataToRemove.checkpointDetails = {}; }
|
|
988
|
+
if (prevData.delegates) { (dataToRemove as any).delegates = 'remove'; }
|
|
866
989
|
if (Object.keys(dataToRemove).length === 0) { dataToRemove = undefined; }
|
|
867
990
|
|
|
868
991
|
const resMut8 = await mut8({
|
|
@@ -6,20 +6,22 @@ export interface KeystoneBehaviorProfileTemplate {
|
|
|
6
6
|
replenish: KeystoneReplenishStrategy;
|
|
7
7
|
selectSequentially: number;
|
|
8
8
|
selectRandomly: number;
|
|
9
|
-
|
|
9
|
+
targetBindingCount: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface KeystonePoolTemplate {
|
|
13
13
|
id: string;
|
|
14
14
|
allowedVerbs: string[];
|
|
15
|
-
|
|
16
|
-
behaviorInline?: KeystoneBehaviorProfileTemplate; // Or specify behavior inline
|
|
15
|
+
behavior: KeystoneBehaviorProfileTemplate;
|
|
17
16
|
algo: HashAlgorithm;
|
|
18
17
|
rounds: number;
|
|
19
18
|
type?: KeystoneChallengeType;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
export interface KeystonePolicyConfigTemplate {
|
|
23
|
-
|
|
22
|
+
metadata?: {
|
|
23
|
+
name?: string;
|
|
24
|
+
securityLevel?: string;
|
|
25
|
+
};
|
|
24
26
|
pools: Record<string, KeystonePoolTemplate>;
|
|
25
27
|
}
|