@longarc/mdash 3.1.2 → 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.
Files changed (172) hide show
  1. package/README.md +86 -23
  2. package/SECURITY.md +254 -0
  3. package/dist/accountability/engine.d.ts +27 -0
  4. package/dist/accountability/engine.d.ts.map +1 -0
  5. package/dist/accountability/engine.js +148 -0
  6. package/dist/accountability/engine.js.map +1 -0
  7. package/dist/accountability/types.d.ts +46 -0
  8. package/dist/accountability/types.d.ts.map +1 -0
  9. package/dist/accountability/types.js +8 -0
  10. package/dist/accountability/types.js.map +1 -0
  11. package/dist/checkpoint/engine.d.ts.map +1 -1
  12. package/dist/checkpoint/engine.js +4 -0
  13. package/dist/checkpoint/engine.js.map +1 -1
  14. package/dist/context/compose.d.ts +62 -0
  15. package/dist/context/compose.d.ts.map +1 -0
  16. package/dist/context/compose.js +286 -0
  17. package/dist/context/compose.js.map +1 -0
  18. package/dist/context/crypto/hash.d.ts +100 -0
  19. package/dist/context/crypto/hash.d.ts.map +1 -0
  20. package/dist/context/crypto/hash.js +248 -0
  21. package/dist/context/crypto/hash.js.map +1 -0
  22. package/dist/context/crypto/hmac.d.ts +80 -0
  23. package/dist/context/crypto/hmac.d.ts.map +1 -0
  24. package/dist/context/crypto/hmac.js +192 -0
  25. package/dist/context/crypto/hmac.js.map +1 -0
  26. package/dist/context/crypto/index.d.ts +7 -0
  27. package/dist/context/crypto/index.d.ts.map +1 -0
  28. package/dist/context/crypto/index.js +7 -0
  29. package/dist/context/crypto/index.js.map +1 -0
  30. package/dist/context/engine-v3.0-backup.d.ts +197 -0
  31. package/dist/context/engine-v3.0-backup.d.ts.map +1 -0
  32. package/dist/context/engine-v3.0-backup.js +392 -0
  33. package/dist/context/engine-v3.0-backup.js.map +1 -0
  34. package/dist/context/fragment.d.ts +99 -0
  35. package/dist/context/fragment.d.ts.map +1 -0
  36. package/dist/context/fragment.js +316 -0
  37. package/dist/context/fragment.js.map +1 -0
  38. package/dist/context/index.d.ts +99 -0
  39. package/dist/context/index.d.ts.map +1 -0
  40. package/dist/context/index.js +180 -0
  41. package/dist/context/index.js.map +1 -0
  42. package/dist/context/provenance.d.ts +80 -0
  43. package/dist/context/provenance.d.ts.map +1 -0
  44. package/dist/context/provenance.js +294 -0
  45. package/dist/context/provenance.js.map +1 -0
  46. package/dist/context/resolve.d.ts +106 -0
  47. package/dist/context/resolve.d.ts.map +1 -0
  48. package/dist/context/resolve.js +440 -0
  49. package/dist/context/resolve.js.map +1 -0
  50. package/dist/context/store.d.ts +156 -0
  51. package/dist/context/store.d.ts.map +1 -0
  52. package/dist/context/store.js +396 -0
  53. package/dist/context/store.js.map +1 -0
  54. package/dist/context/types.d.ts +463 -0
  55. package/dist/context/types.d.ts.map +1 -0
  56. package/dist/context/types.js +94 -0
  57. package/dist/context/types.js.map +1 -0
  58. package/dist/context/utils/atomic.d.ts +76 -0
  59. package/dist/context/utils/atomic.d.ts.map +1 -0
  60. package/dist/context/utils/atomic.js +159 -0
  61. package/dist/context/utils/atomic.js.map +1 -0
  62. package/dist/context/utils/credit.d.ts +65 -0
  63. package/dist/context/utils/credit.d.ts.map +1 -0
  64. package/dist/context/utils/credit.js +164 -0
  65. package/dist/context/utils/credit.js.map +1 -0
  66. package/dist/context/utils/index.d.ts +13 -0
  67. package/dist/context/utils/index.d.ts.map +1 -0
  68. package/dist/context/utils/index.js +13 -0
  69. package/dist/context/utils/index.js.map +1 -0
  70. package/dist/context/utils/utility.d.ts +63 -0
  71. package/dist/context/utils/utility.d.ts.map +1 -0
  72. package/dist/context/utils/utility.js +141 -0
  73. package/dist/context/utils/utility.js.map +1 -0
  74. package/dist/core/commitment.d.ts +25 -2
  75. package/dist/core/commitment.d.ts.map +1 -1
  76. package/dist/core/commitment.js +44 -6
  77. package/dist/core/commitment.js.map +1 -1
  78. package/dist/core/crypto.d.ts +2 -0
  79. package/dist/core/crypto.d.ts.map +1 -1
  80. package/dist/core/crypto.js +12 -0
  81. package/dist/core/crypto.js.map +1 -1
  82. package/dist/index.d.ts +11 -6
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +35 -10
  85. package/dist/index.js.map +1 -1
  86. package/dist/mcca/engine.d.ts.map +1 -1
  87. package/dist/mcca/engine.js +5 -4
  88. package/dist/mcca/engine.js.map +1 -1
  89. package/dist/physics/engine.d.ts +1 -0
  90. package/dist/physics/engine.d.ts.map +1 -1
  91. package/dist/physics/engine.js +36 -2
  92. package/dist/physics/engine.js.map +1 -1
  93. package/dist/provenance/api-handler.d.ts +45 -0
  94. package/dist/provenance/api-handler.d.ts.map +1 -0
  95. package/dist/provenance/api-handler.js +223 -0
  96. package/dist/provenance/api-handler.js.map +1 -0
  97. package/dist/provenance/api-types.d.ts +108 -0
  98. package/dist/provenance/api-types.d.ts.map +1 -0
  99. package/dist/provenance/api-types.js +9 -0
  100. package/dist/provenance/api-types.js.map +1 -0
  101. package/dist/provenance/index.d.ts +6 -0
  102. package/dist/provenance/index.d.ts.map +1 -0
  103. package/dist/provenance/index.js +3 -0
  104. package/dist/provenance/index.js.map +1 -0
  105. package/dist/provenance/provenance-engine.d.ts +63 -0
  106. package/dist/provenance/provenance-engine.d.ts.map +1 -0
  107. package/dist/provenance/provenance-engine.js +311 -0
  108. package/dist/provenance/provenance-engine.js.map +1 -0
  109. package/dist/provenance/types.d.ts +193 -0
  110. package/dist/provenance/types.d.ts.map +1 -0
  111. package/dist/provenance/types.js +9 -0
  112. package/dist/provenance/types.js.map +1 -0
  113. package/dist/tee/engine.d.ts.map +1 -1
  114. package/dist/tee/engine.js +14 -0
  115. package/dist/tee/engine.js.map +1 -1
  116. package/dist/warrant/engine.d.ts +24 -1
  117. package/dist/warrant/engine.d.ts.map +1 -1
  118. package/dist/warrant/engine.js +76 -1
  119. package/dist/warrant/engine.js.map +1 -1
  120. package/dist/zk/engine.d.ts.map +1 -1
  121. package/dist/zk/engine.js +7 -4
  122. package/dist/zk/engine.js.map +1 -1
  123. package/docs/SECURITY-PATCHES.md +170 -0
  124. package/package.json +17 -5
  125. package/src/__tests__/accountability.test.ts +308 -0
  126. package/src/__tests__/l1-verification-modes.test.ts +424 -0
  127. package/src/__tests__/phase1.benchmark.test.ts +94 -0
  128. package/src/__tests__/phase1.test.ts +0 -77
  129. package/src/__tests__/phase2-4.benchmark.test.ts +60 -0
  130. package/src/__tests__/phase2-4.test.ts +1 -52
  131. package/src/__tests__/provenance/api-handler.test.ts +356 -0
  132. package/src/__tests__/provenance/provenance-engine.test.ts +628 -0
  133. package/src/__tests__/sa-2026-008.test.ts +45 -0
  134. package/src/__tests__/sa-2026-009.test.ts +86 -0
  135. package/src/__tests__/sa-2026-010.test.ts +72 -0
  136. package/src/__tests__/sa-2026-012.test.ts +65 -0
  137. package/src/__tests__/sa-2026-nfc.test.ts +40 -0
  138. package/src/__tests__/security.test.ts +786 -0
  139. package/src/accountability/engine.ts +230 -0
  140. package/src/accountability/types.ts +58 -0
  141. package/src/checkpoint/engine.ts +4 -0
  142. package/src/context/__tests__/caret-v0.2.0.test.ts +860 -0
  143. package/src/context/__tests__/integration.test.ts +356 -0
  144. package/src/context/compose.ts +388 -0
  145. package/src/context/crypto/hash.ts +277 -0
  146. package/src/context/crypto/hmac.ts +253 -0
  147. package/src/context/crypto/index.ts +29 -0
  148. package/src/context/engine-v3.0-backup.ts +598 -0
  149. package/src/context/fragment.ts +454 -0
  150. package/src/context/index.ts +427 -0
  151. package/src/context/provenance.ts +380 -0
  152. package/src/context/resolve.ts +581 -0
  153. package/src/context/store.ts +503 -0
  154. package/src/context/types.ts +679 -0
  155. package/src/context/utils/atomic.ts +207 -0
  156. package/src/context/utils/credit.ts +224 -0
  157. package/src/context/utils/index.ts +13 -0
  158. package/src/context/utils/utility.ts +200 -0
  159. package/src/core/commitment.ts +129 -67
  160. package/src/core/crypto.ts +13 -0
  161. package/src/index.ts +62 -10
  162. package/src/mcca/engine.ts +5 -4
  163. package/src/physics/engine.ts +40 -3
  164. package/src/provenance/api-handler.ts +248 -0
  165. package/src/provenance/api-types.ts +112 -0
  166. package/src/provenance/index.ts +19 -0
  167. package/src/provenance/provenance-engine.ts +387 -0
  168. package/src/provenance/types.ts +211 -0
  169. package/src/tee/engine.ts +16 -0
  170. package/src/warrant/engine.ts +89 -1
  171. package/src/zk/engine.ts +8 -4
  172. package/tsconfig.json +1 -1
@@ -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
@@ -27,6 +27,18 @@ import {
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): Promise<Commitment> {
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
- // Create the commitment record
239
- const commitmentData = {
240
- _v: 1, // Protocol version for upgrade path
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 commitmentData = {
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
  */
@@ -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
- * Accountability infrastructure for autonomous AI agents.
7
- * Cryptographic attestation at execution speed.
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) throw new Error(`No valid warrant for agent ${params.agentId}`);
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
- throw new Error(`Physics validation failed`);
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-03',
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 (unified context primitives)',
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',
@@ -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 -= fragment.token_count;
398
- this.influenceBySource[fragment.source_class] -= fragment.influence;
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.operationId;
477
+ proofData.commitment_id = commitment.id;
477
478
 
478
479
  const seal = await hmacSeal(proofData, this.key);
479
480