@longarc/mdash 3.1.1 → 3.1.3
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/README.md +86 -23
- package/SECURITY.md +254 -0
- package/dist/accountability/engine.d.ts +27 -0
- package/dist/accountability/engine.d.ts.map +1 -0
- package/dist/accountability/engine.js +148 -0
- package/dist/accountability/engine.js.map +1 -0
- package/dist/accountability/types.d.ts +46 -0
- package/dist/accountability/types.d.ts.map +1 -0
- package/dist/accountability/types.js +8 -0
- package/dist/accountability/types.js.map +1 -0
- package/dist/checkpoint/engine.d.ts +2 -2
- package/dist/checkpoint/engine.d.ts.map +1 -1
- package/dist/checkpoint/engine.js +5 -1
- package/dist/checkpoint/engine.js.map +1 -1
- package/dist/context/compose.d.ts +62 -0
- package/dist/context/compose.d.ts.map +1 -0
- package/dist/context/compose.js +286 -0
- package/dist/context/compose.js.map +1 -0
- package/dist/context/crypto/hash.d.ts +100 -0
- package/dist/context/crypto/hash.d.ts.map +1 -0
- package/dist/context/crypto/hash.js +248 -0
- package/dist/context/crypto/hash.js.map +1 -0
- package/dist/context/crypto/hmac.d.ts +80 -0
- package/dist/context/crypto/hmac.d.ts.map +1 -0
- package/dist/context/crypto/hmac.js +192 -0
- package/dist/context/crypto/hmac.js.map +1 -0
- package/dist/context/crypto/index.d.ts +7 -0
- package/dist/context/crypto/index.d.ts.map +1 -0
- package/dist/context/crypto/index.js +7 -0
- package/dist/context/crypto/index.js.map +1 -0
- package/dist/context/engine-v3.0-backup.d.ts +197 -0
- package/dist/context/engine-v3.0-backup.d.ts.map +1 -0
- package/dist/context/engine-v3.0-backup.js +392 -0
- package/dist/context/engine-v3.0-backup.js.map +1 -0
- package/dist/context/engine.d.ts +2 -2
- package/dist/context/engine.d.ts.map +1 -1
- package/dist/context/engine.js +2 -2
- package/dist/context/engine.js.map +1 -1
- package/dist/context/fragment.d.ts +99 -0
- package/dist/context/fragment.d.ts.map +1 -0
- package/dist/context/fragment.js +316 -0
- package/dist/context/fragment.js.map +1 -0
- package/dist/context/index.d.ts +99 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +180 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/provenance.d.ts +80 -0
- package/dist/context/provenance.d.ts.map +1 -0
- package/dist/context/provenance.js +294 -0
- package/dist/context/provenance.js.map +1 -0
- package/dist/context/resolve.d.ts +106 -0
- package/dist/context/resolve.d.ts.map +1 -0
- package/dist/context/resolve.js +440 -0
- package/dist/context/resolve.js.map +1 -0
- package/dist/context/store.d.ts +156 -0
- package/dist/context/store.d.ts.map +1 -0
- package/dist/context/store.js +396 -0
- package/dist/context/store.js.map +1 -0
- package/dist/context/types.d.ts +463 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +94 -0
- package/dist/context/types.js.map +1 -0
- package/dist/context/utils/atomic.d.ts +76 -0
- package/dist/context/utils/atomic.d.ts.map +1 -0
- package/dist/context/utils/atomic.js +159 -0
- package/dist/context/utils/atomic.js.map +1 -0
- package/dist/context/utils/credit.d.ts +65 -0
- package/dist/context/utils/credit.d.ts.map +1 -0
- package/dist/context/utils/credit.js +164 -0
- package/dist/context/utils/credit.js.map +1 -0
- package/dist/context/utils/index.d.ts +13 -0
- package/dist/context/utils/index.d.ts.map +1 -0
- package/dist/context/utils/index.js +13 -0
- package/dist/context/utils/index.js.map +1 -0
- package/dist/context/utils/utility.d.ts +63 -0
- package/dist/context/utils/utility.d.ts.map +1 -0
- package/dist/context/utils/utility.js +141 -0
- package/dist/context/utils/utility.js.map +1 -0
- package/dist/core/commitment.d.ts +26 -3
- package/dist/core/commitment.d.ts.map +1 -1
- package/dist/core/commitment.js +45 -7
- package/dist/core/commitment.js.map +1 -1
- package/dist/core/crypto.d.ts +2 -0
- package/dist/core/crypto.d.ts.map +1 -1
- package/dist/core/crypto.js +12 -0
- package/dist/core/crypto.js.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -10
- package/dist/index.js.map +1 -1
- package/dist/mcca/engine.d.ts.map +1 -1
- package/dist/mcca/engine.js +5 -4
- package/dist/mcca/engine.js.map +1 -1
- package/dist/physics/engine.d.ts +3 -2
- package/dist/physics/engine.d.ts.map +1 -1
- package/dist/physics/engine.js +37 -3
- package/dist/physics/engine.js.map +1 -1
- package/dist/provenance/api-handler.d.ts +45 -0
- package/dist/provenance/api-handler.d.ts.map +1 -0
- package/dist/provenance/api-handler.js +223 -0
- package/dist/provenance/api-handler.js.map +1 -0
- package/dist/provenance/api-types.d.ts +108 -0
- package/dist/provenance/api-types.d.ts.map +1 -0
- package/dist/provenance/api-types.js +9 -0
- package/dist/provenance/api-types.js.map +1 -0
- package/dist/provenance/index.d.ts +6 -0
- package/dist/provenance/index.d.ts.map +1 -0
- package/dist/provenance/index.js +3 -0
- package/dist/provenance/index.js.map +1 -0
- package/dist/provenance/provenance-engine.d.ts +63 -0
- package/dist/provenance/provenance-engine.d.ts.map +1 -0
- package/dist/provenance/provenance-engine.js +311 -0
- package/dist/provenance/provenance-engine.js.map +1 -0
- package/dist/provenance/types.d.ts +193 -0
- package/dist/provenance/types.d.ts.map +1 -0
- package/dist/provenance/types.js +9 -0
- package/dist/provenance/types.js.map +1 -0
- package/dist/tee/engine.d.ts.map +1 -1
- package/dist/tee/engine.js +14 -0
- package/dist/tee/engine.js.map +1 -1
- package/dist/warrant/engine.d.ts +24 -1
- package/dist/warrant/engine.d.ts.map +1 -1
- package/dist/warrant/engine.js +76 -1
- package/dist/warrant/engine.js.map +1 -1
- package/dist/zk/engine.d.ts.map +1 -1
- package/dist/zk/engine.js +7 -4
- package/dist/zk/engine.js.map +1 -1
- package/docs/SECURITY-PATCHES.md +170 -0
- package/package.json +17 -5
- package/src/__tests__/accountability.test.ts +308 -0
- package/src/__tests__/l1-verification-modes.test.ts +424 -0
- package/src/__tests__/phase1.benchmark.test.ts +94 -0
- package/src/__tests__/phase1.test.ts +0 -77
- package/src/__tests__/phase2-4.benchmark.test.ts +60 -0
- package/src/__tests__/phase2-4.test.ts +1 -52
- package/src/__tests__/provenance/api-handler.test.ts +356 -0
- package/src/__tests__/provenance/provenance-engine.test.ts +628 -0
- package/src/__tests__/sa-2026-008.test.ts +45 -0
- package/src/__tests__/sa-2026-009.test.ts +86 -0
- package/src/__tests__/sa-2026-010.test.ts +72 -0
- package/src/__tests__/sa-2026-012.test.ts +65 -0
- package/src/__tests__/sa-2026-nfc.test.ts +40 -0
- package/src/__tests__/security.test.ts +786 -0
- package/src/accountability/engine.ts +230 -0
- package/src/accountability/types.ts +58 -0
- package/src/checkpoint/engine.ts +6 -2
- package/src/context/__tests__/caret-v0.2.0.test.ts +860 -0
- package/src/context/__tests__/integration.test.ts +356 -0
- package/src/context/compose.ts +388 -0
- package/src/context/crypto/hash.ts +277 -0
- package/src/context/crypto/hmac.ts +253 -0
- package/src/context/crypto/index.ts +29 -0
- package/src/context/engine-v3.0-backup.ts +598 -0
- package/src/context/engine.ts +2 -2
- package/src/context/fragment.ts +454 -0
- package/src/context/index.ts +427 -0
- package/src/context/provenance.ts +380 -0
- package/src/context/resolve.ts +581 -0
- package/src/context/store.ts +503 -0
- package/src/context/types.ts +679 -0
- package/src/context/utils/atomic.ts +207 -0
- package/src/context/utils/credit.ts +224 -0
- package/src/context/utils/index.ts +13 -0
- package/src/context/utils/utility.ts +200 -0
- package/src/core/commitment.ts +130 -68
- package/src/core/crypto.ts +13 -0
- package/src/index.ts +62 -10
- package/src/mcca/engine.ts +5 -4
- package/src/physics/engine.ts +42 -5
- package/src/provenance/api-handler.ts +248 -0
- package/src/provenance/api-types.ts +112 -0
- package/src/provenance/index.ts +19 -0
- package/src/provenance/provenance-engine.ts +387 -0
- package/src/provenance/types.ts +211 -0
- package/src/tee/engine.ts +16 -0
- package/src/warrant/engine.ts +89 -1
- package/src/zk/engine.ts +8 -4
- package/tsconfig.json +1 -1
package/src/core/commitment.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* mdash v3.0 - Commitment Layer (L1)
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Sub-millisecond cryptographic commitments.
|
|
5
5
|
* "The seal races the attack."
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Target Latency:
|
|
8
8
|
* - Commitment seal: <0.5ms P50, <1ms P99
|
|
9
9
|
* - Merkle proof: <0.1ms
|
|
@@ -21,12 +21,24 @@ import {
|
|
|
21
21
|
deriveKey,
|
|
22
22
|
generateTimestamp,
|
|
23
23
|
constantTimeEqual,
|
|
24
|
-
} from './crypto';
|
|
24
|
+
} from './crypto.js';
|
|
25
25
|
|
|
26
26
|
// ============================================================================
|
|
27
27
|
// COMMITMENT TYPES
|
|
28
28
|
// ============================================================================
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* L1 Verification Modes
|
|
32
|
+
*
|
|
33
|
+
* - 'claim': Agent self-reports. Cost: Minimal, Trust: Low.
|
|
34
|
+
* Uses _v:1 seal (backwards-compatible with all existing commitments).
|
|
35
|
+
* - 'verified': Inference verification via locality-sensitive hashing.
|
|
36
|
+
* Cost: Moderate, Trust: Medium. Uses _v:2 seal.
|
|
37
|
+
* - 'witnessed': Third-party Warden observes and co-signs.
|
|
38
|
+
* Cost: Higher, Trust: High. Uses _v:2 seal.
|
|
39
|
+
*/
|
|
40
|
+
export type VerificationMode = 'claim' | 'verified' | 'witnessed';
|
|
41
|
+
|
|
30
42
|
export interface Commitment {
|
|
31
43
|
/** Unique commitment identifier */
|
|
32
44
|
id: string;
|
|
@@ -39,7 +51,11 @@ export interface Commitment {
|
|
|
39
51
|
/** HMAC seal binding id + hash + timestamp */
|
|
40
52
|
seal: Seal;
|
|
41
53
|
/** Protocol version for upgrade path */
|
|
42
|
-
version: 'v3.0';
|
|
54
|
+
version: 'v3.0' | 'v3.1';
|
|
55
|
+
/** L1 verification mode (absent on v3.0 commitments, defaults to 'claim') */
|
|
56
|
+
verification_mode?: VerificationMode;
|
|
57
|
+
/** Verification evidence: LSH digest for 'verified', witness seal for 'witnessed' */
|
|
58
|
+
verification_proof?: Hash;
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
export interface CommitmentProof {
|
|
@@ -68,28 +84,28 @@ export class IncrementalMerkleTree {
|
|
|
68
84
|
private leaves: Hash[] = [];
|
|
69
85
|
private levels: Hash[][] = [];
|
|
70
86
|
private readonly maxDepth: number;
|
|
71
|
-
|
|
87
|
+
|
|
72
88
|
constructor(maxDepth: number = 20) {
|
|
73
89
|
this.maxDepth = maxDepth;
|
|
74
90
|
}
|
|
75
|
-
|
|
91
|
+
|
|
76
92
|
/**
|
|
77
93
|
* Add a leaf to the tree
|
|
78
94
|
* O(log n) operation
|
|
79
95
|
*/
|
|
80
96
|
async addLeaf(hash: Hash): Promise<number> {
|
|
81
97
|
const index = this.leaves.length;
|
|
82
|
-
|
|
98
|
+
|
|
83
99
|
if (index >= Math.pow(2, this.maxDepth)) {
|
|
84
100
|
throw new Error(`Tree capacity exceeded: max ${Math.pow(2, this.maxDepth)} leaves`);
|
|
85
101
|
}
|
|
86
|
-
|
|
102
|
+
|
|
87
103
|
this.leaves.push(hash);
|
|
88
104
|
await this.updatePath(index);
|
|
89
|
-
|
|
105
|
+
|
|
90
106
|
return index;
|
|
91
107
|
}
|
|
92
|
-
|
|
108
|
+
|
|
93
109
|
/**
|
|
94
110
|
* Update the Merkle path for a new leaf
|
|
95
111
|
* Incrementally updates only affected nodes
|
|
@@ -101,30 +117,30 @@ export class IncrementalMerkleTree {
|
|
|
101
117
|
}
|
|
102
118
|
let currentHash: Hash = leafHash;
|
|
103
119
|
let currentIndex = leafIndex;
|
|
104
|
-
|
|
120
|
+
|
|
105
121
|
for (let level = 0; level < this.maxDepth; level++) {
|
|
106
122
|
const levelArray = this.levels[level] ?? (this.levels[level] = []);
|
|
107
|
-
|
|
123
|
+
|
|
108
124
|
const siblingIndex = currentIndex ^ 1; // XOR to get sibling
|
|
109
125
|
const parentIndex = currentIndex >> 1; // Divide by 2
|
|
110
|
-
|
|
126
|
+
|
|
111
127
|
// Get sibling hash (empty hash if doesn't exist)
|
|
112
128
|
const siblingHash: Hash = levelArray[siblingIndex] ?? await sha256('');
|
|
113
|
-
|
|
129
|
+
|
|
114
130
|
// Store current hash at this level
|
|
115
131
|
levelArray[currentIndex] = currentHash;
|
|
116
|
-
|
|
132
|
+
|
|
117
133
|
// Compute parent hash
|
|
118
134
|
if (currentIndex % 2 === 0) {
|
|
119
135
|
currentHash = await rollingHash([currentHash, siblingHash]);
|
|
120
136
|
} else {
|
|
121
137
|
currentHash = await rollingHash([siblingHash, currentHash]);
|
|
122
138
|
}
|
|
123
|
-
|
|
139
|
+
|
|
124
140
|
currentIndex = parentIndex;
|
|
125
141
|
}
|
|
126
142
|
}
|
|
127
|
-
|
|
143
|
+
|
|
128
144
|
/**
|
|
129
145
|
* Get the current root hash
|
|
130
146
|
*/
|
|
@@ -132,12 +148,12 @@ export class IncrementalMerkleTree {
|
|
|
132
148
|
if (this.leaves.length === 0) {
|
|
133
149
|
return sha256('empty');
|
|
134
150
|
}
|
|
135
|
-
|
|
151
|
+
|
|
136
152
|
// Root is at the top level
|
|
137
153
|
const topLevel = this.levels[this.maxDepth - 1];
|
|
138
154
|
return topLevel?.[0] || await sha256('');
|
|
139
155
|
}
|
|
140
|
-
|
|
156
|
+
|
|
141
157
|
/**
|
|
142
158
|
* Generate Merkle proof for a leaf
|
|
143
159
|
* O(log n) operation
|
|
@@ -146,26 +162,26 @@ export class IncrementalMerkleTree {
|
|
|
146
162
|
if (leafIndex < 0 || leafIndex >= this.leaves.length) {
|
|
147
163
|
throw new Error(`Invalid leaf index: ${leafIndex}`);
|
|
148
164
|
}
|
|
149
|
-
|
|
165
|
+
|
|
150
166
|
const path: MerklePathNode[] = [];
|
|
151
167
|
let currentIndex = leafIndex;
|
|
152
|
-
|
|
168
|
+
|
|
153
169
|
for (let level = 0; level < this.maxDepth; level++) {
|
|
154
170
|
const siblingIndex = currentIndex ^ 1;
|
|
155
171
|
const levelArray = this.levels[level];
|
|
156
172
|
const siblingHash: Hash = levelArray?.[siblingIndex] ?? await sha256('');
|
|
157
|
-
|
|
173
|
+
|
|
158
174
|
path.push({
|
|
159
175
|
hash: siblingHash,
|
|
160
176
|
position: currentIndex % 2 === 0 ? 'right' : 'left',
|
|
161
177
|
});
|
|
162
|
-
|
|
178
|
+
|
|
163
179
|
currentIndex = currentIndex >> 1;
|
|
164
180
|
}
|
|
165
|
-
|
|
181
|
+
|
|
166
182
|
return path;
|
|
167
183
|
}
|
|
168
|
-
|
|
184
|
+
|
|
169
185
|
/**
|
|
170
186
|
* Verify a Merkle proof
|
|
171
187
|
* O(log n) operation
|
|
@@ -176,7 +192,7 @@ export class IncrementalMerkleTree {
|
|
|
176
192
|
expectedRoot: Hash
|
|
177
193
|
): Promise<boolean> {
|
|
178
194
|
let currentHash = leafHash;
|
|
179
|
-
|
|
195
|
+
|
|
180
196
|
for (const node of proof) {
|
|
181
197
|
if (node.position === 'left') {
|
|
182
198
|
currentHash = await rollingHash([node.hash, currentHash]);
|
|
@@ -184,10 +200,10 @@ export class IncrementalMerkleTree {
|
|
|
184
200
|
currentHash = await rollingHash([currentHash, node.hash]);
|
|
185
201
|
}
|
|
186
202
|
}
|
|
187
|
-
|
|
203
|
+
|
|
188
204
|
return constantTimeEqual(currentHash, expectedRoot);
|
|
189
205
|
}
|
|
190
|
-
|
|
206
|
+
|
|
191
207
|
/**
|
|
192
208
|
* Get tree statistics
|
|
193
209
|
*/
|
|
@@ -208,92 +224,138 @@ export class CommitmentEngine {
|
|
|
208
224
|
private key: CryptoKey | null = null;
|
|
209
225
|
private tree: IncrementalMerkleTree;
|
|
210
226
|
private commitments: Map<string, Commitment> = new Map();
|
|
211
|
-
|
|
227
|
+
|
|
212
228
|
constructor(maxTreeDepth: number = 20) {
|
|
213
229
|
this.tree = new IncrementalMerkleTree(maxTreeDepth);
|
|
214
230
|
}
|
|
215
|
-
|
|
231
|
+
|
|
216
232
|
/**
|
|
217
233
|
* Initialize the engine with a seal key
|
|
218
234
|
*/
|
|
219
235
|
async initialize(sealKey: string): Promise<void> {
|
|
220
236
|
this.key = await deriveKey(sealKey);
|
|
221
237
|
}
|
|
222
|
-
|
|
238
|
+
|
|
223
239
|
/**
|
|
224
240
|
* Create a commitment for content
|
|
225
241
|
* Target: <0.5ms P50, <1ms P99
|
|
242
|
+
*
|
|
243
|
+
* @param content - The content to commit
|
|
244
|
+
* @param id - Unique commitment identifier
|
|
245
|
+
* @param options - Optional verification mode configuration
|
|
226
246
|
*/
|
|
227
|
-
async commit<T>(content: T, id: string
|
|
247
|
+
async commit<T>(content: T, id: string, options?: {
|
|
248
|
+
mode?: VerificationMode;
|
|
249
|
+
verificationProof?: Hash;
|
|
250
|
+
}): Promise<Commitment> {
|
|
228
251
|
if (!this.key) {
|
|
229
252
|
throw new Error('Engine not initialized. Call initialize() first.');
|
|
230
253
|
}
|
|
231
|
-
|
|
254
|
+
|
|
255
|
+
const mode = options?.mode ?? 'claim';
|
|
256
|
+
const verificationProof = options?.verificationProof;
|
|
257
|
+
|
|
258
|
+
// Runtime guard: validate mode is a known value (TypeScript types erased at runtime)
|
|
259
|
+
const VALID_MODES: readonly VerificationMode[] = ['claim', 'verified', 'witnessed'];
|
|
260
|
+
if (!VALID_MODES.includes(mode)) {
|
|
261
|
+
throw new Error('Invalid verification mode');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Validate: 'verified' and 'witnessed' modes require proof
|
|
265
|
+
if (mode !== 'claim' && !verificationProof) {
|
|
266
|
+
throw new Error('Enhanced verification mode requires a verification_proof');
|
|
267
|
+
}
|
|
268
|
+
|
|
232
269
|
const startTime = performance.now();
|
|
233
|
-
|
|
270
|
+
|
|
234
271
|
// Hash the content
|
|
235
272
|
const contentHash = await sha256Object(content);
|
|
236
273
|
const timestamp = generateTimestamp();
|
|
237
|
-
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
274
|
+
|
|
275
|
+
// Seal computation bifurcates on mode:
|
|
276
|
+
// - 'claim' uses _v:1 (exact backwards compatibility)
|
|
277
|
+
// - 'verified'/'witnessed' use _v:2 (includes verification fields)
|
|
278
|
+
const isEnhanced = mode !== 'claim';
|
|
279
|
+
|
|
280
|
+
const commitmentData = isEnhanced ? {
|
|
281
|
+
_v: 2,
|
|
282
|
+
id,
|
|
283
|
+
content_hash: contentHash,
|
|
284
|
+
committed_at: timestamp,
|
|
285
|
+
verification_mode: mode,
|
|
286
|
+
verification_proof: verificationProof,
|
|
287
|
+
} : {
|
|
288
|
+
_v: 1, // Preserved exactly -- existing seals remain valid
|
|
241
289
|
id,
|
|
242
290
|
content_hash: contentHash,
|
|
243
291
|
committed_at: timestamp,
|
|
244
292
|
};
|
|
245
|
-
|
|
293
|
+
|
|
246
294
|
// Seal the commitment
|
|
247
295
|
const seal = await hmacSeal(commitmentData, this.key);
|
|
248
|
-
|
|
296
|
+
|
|
249
297
|
const commitment: Commitment = {
|
|
250
298
|
id,
|
|
251
299
|
operationId: id,
|
|
252
300
|
content_hash: contentHash,
|
|
253
301
|
committed_at: timestamp,
|
|
254
302
|
seal,
|
|
255
|
-
version: 'v3.0',
|
|
303
|
+
version: isEnhanced ? 'v3.1' : 'v3.0',
|
|
304
|
+
...(isEnhanced ? {
|
|
305
|
+
verification_mode: mode,
|
|
306
|
+
verification_proof: verificationProof,
|
|
307
|
+
} : {}),
|
|
256
308
|
};
|
|
257
|
-
|
|
309
|
+
|
|
258
310
|
// Add to Merkle tree
|
|
259
311
|
await this.tree.addLeaf(contentHash);
|
|
260
|
-
|
|
312
|
+
|
|
261
313
|
// Store commitment
|
|
262
314
|
this.commitments.set(id, commitment);
|
|
263
|
-
|
|
315
|
+
|
|
264
316
|
const elapsed = performance.now() - startTime;
|
|
265
317
|
if (elapsed > 1) {
|
|
266
318
|
console.warn(`Commitment latency exceeded P99: ${elapsed.toFixed(2)}ms`);
|
|
267
319
|
}
|
|
268
|
-
|
|
320
|
+
|
|
269
321
|
return commitment;
|
|
270
322
|
}
|
|
271
|
-
|
|
323
|
+
|
|
272
324
|
/**
|
|
273
325
|
* Get a commitment by ID
|
|
274
326
|
*/
|
|
275
327
|
getCommitment(id: string): Commitment | undefined {
|
|
276
328
|
return this.commitments.get(id);
|
|
277
329
|
}
|
|
278
|
-
|
|
330
|
+
|
|
279
331
|
/**
|
|
280
332
|
* Verify a commitment
|
|
333
|
+
* Handles both _v:1 (claim) and _v:2 (verified/witnessed) seal formats
|
|
281
334
|
*/
|
|
282
335
|
async verify(commitment: Commitment): Promise<boolean> {
|
|
283
336
|
if (!this.key) {
|
|
284
337
|
throw new Error('Engine not initialized. Call initialize() first.');
|
|
285
338
|
}
|
|
286
|
-
|
|
287
|
-
const
|
|
339
|
+
|
|
340
|
+
const isEnhanced = commitment.verification_mode && commitment.verification_mode !== 'claim';
|
|
341
|
+
|
|
342
|
+
const commitmentData = isEnhanced ? {
|
|
343
|
+
_v: 2,
|
|
344
|
+
id: commitment.id,
|
|
345
|
+
content_hash: commitment.content_hash,
|
|
346
|
+
committed_at: commitment.committed_at,
|
|
347
|
+
verification_mode: commitment.verification_mode,
|
|
348
|
+
verification_proof: commitment.verification_proof,
|
|
349
|
+
} : {
|
|
288
350
|
_v: 1,
|
|
289
351
|
id: commitment.id,
|
|
290
352
|
content_hash: commitment.content_hash,
|
|
291
353
|
committed_at: commitment.committed_at,
|
|
292
354
|
};
|
|
293
|
-
|
|
355
|
+
|
|
294
356
|
return hmacVerify(commitmentData, commitment.seal, this.key);
|
|
295
357
|
}
|
|
296
|
-
|
|
358
|
+
|
|
297
359
|
/**
|
|
298
360
|
* Generate a proof for a commitment
|
|
299
361
|
*/
|
|
@@ -302,13 +364,13 @@ export class CommitmentEngine {
|
|
|
302
364
|
if (!commitment) {
|
|
303
365
|
throw new Error(`Commitment not found: ${id}`);
|
|
304
366
|
}
|
|
305
|
-
|
|
367
|
+
|
|
306
368
|
// Find leaf index
|
|
307
369
|
const leafIndex = Array.from(this.commitments.keys()).indexOf(id);
|
|
308
|
-
|
|
370
|
+
|
|
309
371
|
const merkle_path = await this.tree.getProof(leafIndex);
|
|
310
372
|
const root_hash = await this.tree.getRoot();
|
|
311
|
-
|
|
373
|
+
|
|
312
374
|
return {
|
|
313
375
|
commitment,
|
|
314
376
|
merkle_path,
|
|
@@ -316,7 +378,7 @@ export class CommitmentEngine {
|
|
|
316
378
|
leaf_index: leafIndex,
|
|
317
379
|
};
|
|
318
380
|
}
|
|
319
|
-
|
|
381
|
+
|
|
320
382
|
/**
|
|
321
383
|
* Verify a proof
|
|
322
384
|
*/
|
|
@@ -326,7 +388,7 @@ export class CommitmentEngine {
|
|
|
326
388
|
if (!commitmentValid) {
|
|
327
389
|
return false;
|
|
328
390
|
}
|
|
329
|
-
|
|
391
|
+
|
|
330
392
|
// Then verify the Merkle path
|
|
331
393
|
return IncrementalMerkleTree.verifyProof(
|
|
332
394
|
proof.commitment.content_hash,
|
|
@@ -334,14 +396,14 @@ export class CommitmentEngine {
|
|
|
334
396
|
proof.root_hash
|
|
335
397
|
);
|
|
336
398
|
}
|
|
337
|
-
|
|
399
|
+
|
|
338
400
|
/**
|
|
339
401
|
* Get the current Merkle root
|
|
340
402
|
*/
|
|
341
403
|
async getRoot(): Promise<Hash> {
|
|
342
404
|
return this.tree.getRoot();
|
|
343
405
|
}
|
|
344
|
-
|
|
406
|
+
|
|
345
407
|
/**
|
|
346
408
|
* Get statistics
|
|
347
409
|
*/
|
|
@@ -371,7 +433,7 @@ export interface LatencyMetrics {
|
|
|
371
433
|
export class LatencyMonitor {
|
|
372
434
|
private metrics: Map<string, number[]> = new Map();
|
|
373
435
|
private thresholds: Map<string, { p50: number; p99: number }> = new Map();
|
|
374
|
-
|
|
436
|
+
|
|
375
437
|
constructor() {
|
|
376
438
|
// Default thresholds from v3.0 spec
|
|
377
439
|
this.thresholds.set('commitment_seal', { p50: 0.5, p99: 1 });
|
|
@@ -379,7 +441,7 @@ export class LatencyMonitor {
|
|
|
379
441
|
this.thresholds.set('context_chunk_seal', { p50: 2, p99: 5 });
|
|
380
442
|
this.thresholds.set('checkpoint_create', { p50: 0.5, p99: 1 });
|
|
381
443
|
}
|
|
382
|
-
|
|
444
|
+
|
|
383
445
|
/**
|
|
384
446
|
* Record a latency sample
|
|
385
447
|
*/
|
|
@@ -389,7 +451,7 @@ export class LatencyMonitor {
|
|
|
389
451
|
}
|
|
390
452
|
this.metrics.get(operation)!.push(latencyMs);
|
|
391
453
|
}
|
|
392
|
-
|
|
454
|
+
|
|
393
455
|
/**
|
|
394
456
|
* Get metrics for an operation
|
|
395
457
|
*/
|
|
@@ -398,15 +460,15 @@ export class LatencyMonitor {
|
|
|
398
460
|
if (!samples || samples.length === 0) {
|
|
399
461
|
return null;
|
|
400
462
|
}
|
|
401
|
-
|
|
463
|
+
|
|
402
464
|
const sorted = [...samples].sort((a, b) => a - b);
|
|
403
465
|
const p50Index = Math.floor(sorted.length * 0.5);
|
|
404
466
|
const p99Index = Math.floor(sorted.length * 0.99);
|
|
405
|
-
|
|
467
|
+
|
|
406
468
|
const threshold = this.thresholds.get(operation);
|
|
407
469
|
const p50 = sorted[p50Index] ?? 0;
|
|
408
470
|
const p99 = sorted[p99Index] ?? 0;
|
|
409
|
-
|
|
471
|
+
|
|
410
472
|
return {
|
|
411
473
|
operation,
|
|
412
474
|
p50_ms: p50,
|
|
@@ -415,21 +477,21 @@ export class LatencyMonitor {
|
|
|
415
477
|
breaches: threshold ? samples.filter(s => s > threshold.p99).length : 0,
|
|
416
478
|
};
|
|
417
479
|
}
|
|
418
|
-
|
|
480
|
+
|
|
419
481
|
/**
|
|
420
482
|
* Check if operation is within SLA
|
|
421
483
|
*/
|
|
422
484
|
isWithinSLA(operation: string): boolean {
|
|
423
485
|
const metrics = this.getMetrics(operation);
|
|
424
486
|
const threshold = this.thresholds.get(operation);
|
|
425
|
-
|
|
487
|
+
|
|
426
488
|
if (!metrics || !threshold) {
|
|
427
489
|
return true;
|
|
428
490
|
}
|
|
429
|
-
|
|
491
|
+
|
|
430
492
|
return metrics.p99_ms <= threshold.p99;
|
|
431
493
|
}
|
|
432
|
-
|
|
494
|
+
|
|
433
495
|
/**
|
|
434
496
|
* Clear metrics
|
|
435
497
|
*/
|
package/src/core/crypto.ts
CHANGED
|
@@ -137,6 +137,12 @@ export async function rollingHash(hashes: Hash[]): Promise<Hash> {
|
|
|
137
137
|
*/
|
|
138
138
|
export function deterministicStringify(obj: unknown): string {
|
|
139
139
|
return JSON.stringify(obj, (_, value) => {
|
|
140
|
+
// SA-2026-NFC: Normalize Unicode strings to NFC so visually identical
|
|
141
|
+
// codepoint sequences (e.g. e + combining accent vs precomposed e)
|
|
142
|
+
// produce identical hashes.
|
|
143
|
+
if (typeof value === 'string') {
|
|
144
|
+
return value.normalize('NFC');
|
|
145
|
+
}
|
|
140
146
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
141
147
|
return Object.keys(value)
|
|
142
148
|
.sort()
|
|
@@ -159,8 +165,15 @@ const HKDF_INFO = 'mdash-seal-v3';
|
|
|
159
165
|
/**
|
|
160
166
|
* Derive an HMAC key from a master key using HKDF
|
|
161
167
|
* The derived key is non-extractable
|
|
168
|
+
*
|
|
169
|
+
* SECURITY: Requires minimum key length of 32 characters
|
|
162
170
|
*/
|
|
163
171
|
export async function deriveKey(masterKey: string): Promise<CryptoKey> {
|
|
172
|
+
// P5 SECURITY: Enforce minimum key length
|
|
173
|
+
if (!masterKey || masterKey.length < 32) {
|
|
174
|
+
throw new Error('Seal key must be at least 32 characters');
|
|
175
|
+
}
|
|
176
|
+
|
|
164
177
|
const subtle = getSubtleCrypto();
|
|
165
178
|
const encoder = new TextEncoder();
|
|
166
179
|
|
package/src/index.ts
CHANGED
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* "The best defense is the fastest seal."
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* Cryptographic
|
|
8
|
-
*
|
|
9
|
-
* mdash proves. Kiwi runs. Eclair reveals. Roux holds. The Warden reasons.
|
|
6
|
+
* Cryptographic attestation protocol for autonomous AI agents.
|
|
7
|
+
* Cryptographic sealing at execution speed.
|
|
10
8
|
*
|
|
11
9
|
* Architecture:
|
|
12
10
|
* - L1: Commitment Layer (<1ms)
|
|
13
11
|
* - L2: TEE Attestation (<10ms)
|
|
14
12
|
* - L3: ZK Proofs (async)
|
|
15
13
|
* - MCCA: Manifold-Constrained Context Architecture
|
|
14
|
+
* - Context Module (formerly Caret v0.2.0)
|
|
16
15
|
*
|
|
17
16
|
* @version 3.1.0
|
|
18
17
|
* @author Long Arc Studios
|
|
@@ -34,8 +33,22 @@ export * from './tee/engine.js';
|
|
|
34
33
|
// Re-export L3 ZK Proofs
|
|
35
34
|
export * from './zk/engine.js';
|
|
36
35
|
|
|
36
|
+
// Re-export Provenance
|
|
37
|
+
export * from './provenance/index.js';
|
|
38
|
+
|
|
39
|
+
// Re-export Accountability Engine (consumer API: warrants + commitments)
|
|
40
|
+
export { AccountabilityEngine } from './accountability/engine.js';
|
|
41
|
+
export type {
|
|
42
|
+
ActionResult,
|
|
43
|
+
AuditRecord,
|
|
44
|
+
AuditSummary,
|
|
45
|
+
WarrantPermissions,
|
|
46
|
+
Violation,
|
|
47
|
+
ViolationType,
|
|
48
|
+
} from './accountability/types.js';
|
|
49
|
+
|
|
37
50
|
// Re-export MCCA v3 (excluding SourceClass which is already exported from context)
|
|
38
|
-
export {
|
|
51
|
+
export {
|
|
39
52
|
MCCAEngine,
|
|
40
53
|
ManifoldRegion,
|
|
41
54
|
InfluenceBudget,
|
|
@@ -45,6 +58,26 @@ export {
|
|
|
45
58
|
DEFAULT_CONFIG as MCCA_DEFAULT_CONFIG
|
|
46
59
|
} from './mcca/engine.js';
|
|
47
60
|
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// CONTEXT MODULE (formerly Caret v0.2.0)
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
export * as context from './context/index.js';
|
|
66
|
+
|
|
67
|
+
// Convenience re-exports for common context types
|
|
68
|
+
export type {
|
|
69
|
+
ContextFragment as CaretFragment,
|
|
70
|
+
InfluenceBudget as CaretInfluenceBudget,
|
|
71
|
+
Manifold,
|
|
72
|
+
Outcome,
|
|
73
|
+
} from './context/types.js';
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
requireInfluence,
|
|
77
|
+
requireMCCA,
|
|
78
|
+
createContext,
|
|
79
|
+
} from './context/index.js';
|
|
80
|
+
|
|
48
81
|
// Import for runtime
|
|
49
82
|
import { CommitmentEngine, LatencyMonitor, Commitment } from './core/commitment.js';
|
|
50
83
|
import { WarrantEngine, WarrantTier, WarrantConstraints, Warrant } from './warrant/engine.js';
|
|
@@ -157,7 +190,12 @@ export class MdashProtocol {
|
|
|
157
190
|
};
|
|
158
191
|
|
|
159
192
|
const warrant = await this.warrant.checkAuthorization(authParams);
|
|
160
|
-
if (!warrant)
|
|
193
|
+
if (!warrant) {
|
|
194
|
+
// P3 SECURITY: Generic error message prevents enumeration attacks
|
|
195
|
+
// Internal logging should capture specifics
|
|
196
|
+
console.warn(`[AUTH] Authorization denied for agent ${params.agentId}, action ${params.action}`);
|
|
197
|
+
throw new Error('Authorization denied');
|
|
198
|
+
}
|
|
161
199
|
|
|
162
200
|
const startCheckpoint = await this.checkpoint.onActionStart({
|
|
163
201
|
agent_id: params.agentId,
|
|
@@ -181,9 +219,10 @@ export class MdashProtocol {
|
|
|
181
219
|
agent_id: params.agentId,
|
|
182
220
|
warrant_id: warrant.id,
|
|
183
221
|
action: params.action,
|
|
184
|
-
error: `Physics validation failed`,
|
|
222
|
+
error: `Physics validation failed: ${validation.violations.map(v => v.type).join(', ')}`,
|
|
185
223
|
});
|
|
186
|
-
|
|
224
|
+
// P3 SECURITY: Generic error to user, details logged in checkpoint
|
|
225
|
+
throw new Error('Authorization denied');
|
|
187
226
|
}
|
|
188
227
|
|
|
189
228
|
const { attestation } = await this.bridge.commitAndAttest(
|
|
@@ -191,6 +230,19 @@ export class MdashProtocol {
|
|
|
191
230
|
`action:${params.agentId}:${Date.now()}`
|
|
192
231
|
);
|
|
193
232
|
|
|
233
|
+
// P1 SECURITY: Re-validate warrant immediately before execution
|
|
234
|
+
// Closes TOCTOU window between initial authorization and action execution
|
|
235
|
+
// A revocation could have propagated during physics validation and attestation
|
|
236
|
+
if (this.warrant.isRevoked(warrant.id)) {
|
|
237
|
+
await this.checkpoint.onError({
|
|
238
|
+
agent_id: params.agentId,
|
|
239
|
+
warrant_id: warrant.id,
|
|
240
|
+
action: params.action,
|
|
241
|
+
error: 'Warrant revoked during execution flow',
|
|
242
|
+
});
|
|
243
|
+
throw new Error('Authorization denied');
|
|
244
|
+
}
|
|
245
|
+
|
|
194
246
|
let result: T;
|
|
195
247
|
try {
|
|
196
248
|
result = await params.execute();
|
|
@@ -307,13 +359,13 @@ export function createMdash(config: MdashConfig): MdashProtocol {
|
|
|
307
359
|
export const VERSION = {
|
|
308
360
|
protocol: '3.1.0',
|
|
309
361
|
codename: 'Context Unification',
|
|
310
|
-
releaseDate: '2026-
|
|
362
|
+
releaseDate: '2026-01',
|
|
311
363
|
features: [
|
|
312
364
|
'L1 Commitment Layer (<1ms)',
|
|
313
365
|
'L2 TEE Attestation (AWS Nitro/SGX, <10ms)',
|
|
314
366
|
'L3 ZK Proofs (Plonky2, async)',
|
|
315
367
|
'MCCA v3 (Manifold-Constrained Context Architecture)',
|
|
316
|
-
'Context Module (
|
|
368
|
+
'Context Module (formerly Caret v0.2.0)',
|
|
317
369
|
'Speculative Warrant Issuance (<10ms activation)',
|
|
318
370
|
'Event-driven Checkpoints',
|
|
319
371
|
'Incremental Merkle Sealing',
|
package/src/mcca/engine.ts
CHANGED
|
@@ -393,9 +393,10 @@ export class MCCAEngine {
|
|
|
393
393
|
const fragment = this.fragments.get(id);
|
|
394
394
|
if (!fragment) return;
|
|
395
395
|
|
|
396
|
-
// Update totals
|
|
397
|
-
this.totalTokens
|
|
398
|
-
this.influenceBySource[fragment.source_class]
|
|
396
|
+
// Update totals (SA-2026-012: floor guard prevents floating-point underflow)
|
|
397
|
+
this.totalTokens = Math.max(0, this.totalTokens - fragment.token_count);
|
|
398
|
+
this.influenceBySource[fragment.source_class] =
|
|
399
|
+
Math.max(0, this.influenceBySource[fragment.source_class] - fragment.influence);
|
|
399
400
|
|
|
400
401
|
// Remove from indices
|
|
401
402
|
const regionIds = this.fragmentsByRegion.get(fragment.region) || [];
|
|
@@ -473,7 +474,7 @@ export class MCCAEngine {
|
|
|
473
474
|
|
|
474
475
|
// Commit to L1
|
|
475
476
|
const commitment = await this.commitmentEngine.commit(proofData, `mcca-proof:${id}`);
|
|
476
|
-
proofData.commitment_id = commitment.
|
|
477
|
+
proofData.commitment_id = commitment.id;
|
|
477
478
|
|
|
478
479
|
const seal = await hmacSeal(proofData, this.key);
|
|
479
480
|
|