@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.
Files changed (178) 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 +2 -2
  12. package/dist/checkpoint/engine.d.ts.map +1 -1
  13. package/dist/checkpoint/engine.js +5 -1
  14. package/dist/checkpoint/engine.js.map +1 -1
  15. package/dist/context/compose.d.ts +62 -0
  16. package/dist/context/compose.d.ts.map +1 -0
  17. package/dist/context/compose.js +286 -0
  18. package/dist/context/compose.js.map +1 -0
  19. package/dist/context/crypto/hash.d.ts +100 -0
  20. package/dist/context/crypto/hash.d.ts.map +1 -0
  21. package/dist/context/crypto/hash.js +248 -0
  22. package/dist/context/crypto/hash.js.map +1 -0
  23. package/dist/context/crypto/hmac.d.ts +80 -0
  24. package/dist/context/crypto/hmac.d.ts.map +1 -0
  25. package/dist/context/crypto/hmac.js +192 -0
  26. package/dist/context/crypto/hmac.js.map +1 -0
  27. package/dist/context/crypto/index.d.ts +7 -0
  28. package/dist/context/crypto/index.d.ts.map +1 -0
  29. package/dist/context/crypto/index.js +7 -0
  30. package/dist/context/crypto/index.js.map +1 -0
  31. package/dist/context/engine-v3.0-backup.d.ts +197 -0
  32. package/dist/context/engine-v3.0-backup.d.ts.map +1 -0
  33. package/dist/context/engine-v3.0-backup.js +392 -0
  34. package/dist/context/engine-v3.0-backup.js.map +1 -0
  35. package/dist/context/engine.d.ts +2 -2
  36. package/dist/context/engine.d.ts.map +1 -1
  37. package/dist/context/engine.js +2 -2
  38. package/dist/context/engine.js.map +1 -1
  39. package/dist/context/fragment.d.ts +99 -0
  40. package/dist/context/fragment.d.ts.map +1 -0
  41. package/dist/context/fragment.js +316 -0
  42. package/dist/context/fragment.js.map +1 -0
  43. package/dist/context/index.d.ts +99 -0
  44. package/dist/context/index.d.ts.map +1 -0
  45. package/dist/context/index.js +180 -0
  46. package/dist/context/index.js.map +1 -0
  47. package/dist/context/provenance.d.ts +80 -0
  48. package/dist/context/provenance.d.ts.map +1 -0
  49. package/dist/context/provenance.js +294 -0
  50. package/dist/context/provenance.js.map +1 -0
  51. package/dist/context/resolve.d.ts +106 -0
  52. package/dist/context/resolve.d.ts.map +1 -0
  53. package/dist/context/resolve.js +440 -0
  54. package/dist/context/resolve.js.map +1 -0
  55. package/dist/context/store.d.ts +156 -0
  56. package/dist/context/store.d.ts.map +1 -0
  57. package/dist/context/store.js +396 -0
  58. package/dist/context/store.js.map +1 -0
  59. package/dist/context/types.d.ts +463 -0
  60. package/dist/context/types.d.ts.map +1 -0
  61. package/dist/context/types.js +94 -0
  62. package/dist/context/types.js.map +1 -0
  63. package/dist/context/utils/atomic.d.ts +76 -0
  64. package/dist/context/utils/atomic.d.ts.map +1 -0
  65. package/dist/context/utils/atomic.js +159 -0
  66. package/dist/context/utils/atomic.js.map +1 -0
  67. package/dist/context/utils/credit.d.ts +65 -0
  68. package/dist/context/utils/credit.d.ts.map +1 -0
  69. package/dist/context/utils/credit.js +164 -0
  70. package/dist/context/utils/credit.js.map +1 -0
  71. package/dist/context/utils/index.d.ts +13 -0
  72. package/dist/context/utils/index.d.ts.map +1 -0
  73. package/dist/context/utils/index.js +13 -0
  74. package/dist/context/utils/index.js.map +1 -0
  75. package/dist/context/utils/utility.d.ts +63 -0
  76. package/dist/context/utils/utility.d.ts.map +1 -0
  77. package/dist/context/utils/utility.js +141 -0
  78. package/dist/context/utils/utility.js.map +1 -0
  79. package/dist/core/commitment.d.ts +26 -3
  80. package/dist/core/commitment.d.ts.map +1 -1
  81. package/dist/core/commitment.js +45 -7
  82. package/dist/core/commitment.js.map +1 -1
  83. package/dist/core/crypto.d.ts +2 -0
  84. package/dist/core/crypto.d.ts.map +1 -1
  85. package/dist/core/crypto.js +12 -0
  86. package/dist/core/crypto.js.map +1 -1
  87. package/dist/index.d.ts +11 -6
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +35 -10
  90. package/dist/index.js.map +1 -1
  91. package/dist/mcca/engine.d.ts.map +1 -1
  92. package/dist/mcca/engine.js +5 -4
  93. package/dist/mcca/engine.js.map +1 -1
  94. package/dist/physics/engine.d.ts +3 -2
  95. package/dist/physics/engine.d.ts.map +1 -1
  96. package/dist/physics/engine.js +37 -3
  97. package/dist/physics/engine.js.map +1 -1
  98. package/dist/provenance/api-handler.d.ts +45 -0
  99. package/dist/provenance/api-handler.d.ts.map +1 -0
  100. package/dist/provenance/api-handler.js +223 -0
  101. package/dist/provenance/api-handler.js.map +1 -0
  102. package/dist/provenance/api-types.d.ts +108 -0
  103. package/dist/provenance/api-types.d.ts.map +1 -0
  104. package/dist/provenance/api-types.js +9 -0
  105. package/dist/provenance/api-types.js.map +1 -0
  106. package/dist/provenance/index.d.ts +6 -0
  107. package/dist/provenance/index.d.ts.map +1 -0
  108. package/dist/provenance/index.js +3 -0
  109. package/dist/provenance/index.js.map +1 -0
  110. package/dist/provenance/provenance-engine.d.ts +63 -0
  111. package/dist/provenance/provenance-engine.d.ts.map +1 -0
  112. package/dist/provenance/provenance-engine.js +311 -0
  113. package/dist/provenance/provenance-engine.js.map +1 -0
  114. package/dist/provenance/types.d.ts +193 -0
  115. package/dist/provenance/types.d.ts.map +1 -0
  116. package/dist/provenance/types.js +9 -0
  117. package/dist/provenance/types.js.map +1 -0
  118. package/dist/tee/engine.d.ts.map +1 -1
  119. package/dist/tee/engine.js +14 -0
  120. package/dist/tee/engine.js.map +1 -1
  121. package/dist/warrant/engine.d.ts +24 -1
  122. package/dist/warrant/engine.d.ts.map +1 -1
  123. package/dist/warrant/engine.js +76 -1
  124. package/dist/warrant/engine.js.map +1 -1
  125. package/dist/zk/engine.d.ts.map +1 -1
  126. package/dist/zk/engine.js +7 -4
  127. package/dist/zk/engine.js.map +1 -1
  128. package/docs/SECURITY-PATCHES.md +170 -0
  129. package/package.json +17 -5
  130. package/src/__tests__/accountability.test.ts +308 -0
  131. package/src/__tests__/l1-verification-modes.test.ts +424 -0
  132. package/src/__tests__/phase1.benchmark.test.ts +94 -0
  133. package/src/__tests__/phase1.test.ts +0 -77
  134. package/src/__tests__/phase2-4.benchmark.test.ts +60 -0
  135. package/src/__tests__/phase2-4.test.ts +1 -52
  136. package/src/__tests__/provenance/api-handler.test.ts +356 -0
  137. package/src/__tests__/provenance/provenance-engine.test.ts +628 -0
  138. package/src/__tests__/sa-2026-008.test.ts +45 -0
  139. package/src/__tests__/sa-2026-009.test.ts +86 -0
  140. package/src/__tests__/sa-2026-010.test.ts +72 -0
  141. package/src/__tests__/sa-2026-012.test.ts +65 -0
  142. package/src/__tests__/sa-2026-nfc.test.ts +40 -0
  143. package/src/__tests__/security.test.ts +786 -0
  144. package/src/accountability/engine.ts +230 -0
  145. package/src/accountability/types.ts +58 -0
  146. package/src/checkpoint/engine.ts +6 -2
  147. package/src/context/__tests__/caret-v0.2.0.test.ts +860 -0
  148. package/src/context/__tests__/integration.test.ts +356 -0
  149. package/src/context/compose.ts +388 -0
  150. package/src/context/crypto/hash.ts +277 -0
  151. package/src/context/crypto/hmac.ts +253 -0
  152. package/src/context/crypto/index.ts +29 -0
  153. package/src/context/engine-v3.0-backup.ts +598 -0
  154. package/src/context/engine.ts +2 -2
  155. package/src/context/fragment.ts +454 -0
  156. package/src/context/index.ts +427 -0
  157. package/src/context/provenance.ts +380 -0
  158. package/src/context/resolve.ts +581 -0
  159. package/src/context/store.ts +503 -0
  160. package/src/context/types.ts +679 -0
  161. package/src/context/utils/atomic.ts +207 -0
  162. package/src/context/utils/credit.ts +224 -0
  163. package/src/context/utils/index.ts +13 -0
  164. package/src/context/utils/utility.ts +200 -0
  165. package/src/core/commitment.ts +130 -68
  166. package/src/core/crypto.ts +13 -0
  167. package/src/index.ts +62 -10
  168. package/src/mcca/engine.ts +5 -4
  169. package/src/physics/engine.ts +42 -5
  170. package/src/provenance/api-handler.ts +248 -0
  171. package/src/provenance/api-types.ts +112 -0
  172. package/src/provenance/index.ts +19 -0
  173. package/src/provenance/provenance-engine.ts +387 -0
  174. package/src/provenance/types.ts +211 -0
  175. package/src/tee/engine.ts +16 -0
  176. package/src/warrant/engine.ts +89 -1
  177. package/src/zk/engine.ts +8 -4
  178. package/tsconfig.json +1 -1
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Caret — Provenance Chain Implementation
3
+ * @module @longarcstudios/caret/provenance
4
+ *
5
+ * Immutable provenance tracking for context fragments.
6
+ * Every fragment knows exactly where it came from.
7
+ */
8
+
9
+ import type {
10
+ ProvenanceRecord,
11
+ ProvenanceChain,
12
+ SourceURI,
13
+ Attribution,
14
+ TrustLevel,
15
+ Timestamp,
16
+ Hash,
17
+ } from './types.js';
18
+ import { sha256Object, rollingHash } from './crypto/hash.js';
19
+
20
+ // ============================================================================
21
+ // FACTORY FUNCTIONS
22
+ // ============================================================================
23
+
24
+ /**
25
+ * Create a new ProvenanceRecord.
26
+ */
27
+ export async function createProvenanceRecord(options: {
28
+ source: SourceURI | string;
29
+ attribution: Attribution;
30
+ trust_level?: number;
31
+ parent_hash?: Hash | null;
32
+ signature?: string;
33
+ }): Promise<ProvenanceRecord> {
34
+ const trust = validateTrustLevel(options.trust_level ?? getDefaultTrust(options.attribution));
35
+
36
+ return {
37
+ source: options.source as SourceURI,
38
+ attribution: options.attribution,
39
+ trust_level: trust,
40
+ timestamp: new Date().toISOString() as Timestamp,
41
+ parent_hash: options.parent_hash ?? null,
42
+ signature: options.signature,
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Create a new ProvenanceChain with a single record.
48
+ */
49
+ export async function createProvenanceChain(
50
+ record: ProvenanceRecord
51
+ ): Promise<ProvenanceChain> {
52
+ const chain_hash = await sha256Object(record);
53
+
54
+ return {
55
+ head: record,
56
+ tail: null,
57
+ length: 1,
58
+ chain_hash,
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Extend an existing ProvenanceChain with a new record.
64
+ * Returns a new chain (immutable).
65
+ */
66
+ export async function extendProvenanceChain(
67
+ chain: ProvenanceChain,
68
+ record: ProvenanceRecord
69
+ ): Promise<ProvenanceChain> {
70
+ // Update record's parent_hash to point to current chain
71
+ const linkedRecord: ProvenanceRecord = {
72
+ ...record,
73
+ parent_hash: chain.chain_hash,
74
+ };
75
+
76
+ // Compute new chain hash
77
+ const recordHash = await sha256Object(linkedRecord);
78
+ const chain_hash = await rollingHash([chain.chain_hash, recordHash]);
79
+
80
+ return {
81
+ head: linkedRecord,
82
+ tail: chain,
83
+ length: chain.length + 1,
84
+ chain_hash,
85
+ };
86
+ }
87
+
88
+ // ============================================================================
89
+ // CHAIN OPERATIONS
90
+ // ============================================================================
91
+
92
+ /**
93
+ * Get all records in the chain as an array (head to tail).
94
+ */
95
+ export function flattenChain(chain: ProvenanceChain): ProvenanceRecord[] {
96
+ const records: ProvenanceRecord[] = [];
97
+ let current: ProvenanceChain | null = chain;
98
+
99
+ while (current !== null) {
100
+ records.push(current.head);
101
+ current = current.tail;
102
+ }
103
+
104
+ return records;
105
+ }
106
+
107
+ /**
108
+ * Find a record in the chain by source URI.
109
+ */
110
+ export function findBySource(
111
+ chain: ProvenanceChain,
112
+ source: SourceURI | string
113
+ ): ProvenanceRecord | null {
114
+ let current: ProvenanceChain | null = chain;
115
+
116
+ while (current !== null) {
117
+ if (current.head.source === source) {
118
+ return current.head;
119
+ }
120
+ current = current.tail;
121
+ }
122
+
123
+ return null;
124
+ }
125
+
126
+ /**
127
+ * Get the minimum trust level in the chain.
128
+ */
129
+ export function getMinTrust(chain: ProvenanceChain): TrustLevel {
130
+ let min = chain.head.trust_level;
131
+ let current: ProvenanceChain | null = chain.tail;
132
+
133
+ while (current !== null) {
134
+ if (current.head.trust_level < min) {
135
+ min = current.head.trust_level;
136
+ }
137
+ current = current.tail;
138
+ }
139
+
140
+ return min;
141
+ }
142
+
143
+ /**
144
+ * Get the maximum trust level in the chain.
145
+ */
146
+ export function getMaxTrust(chain: ProvenanceChain): TrustLevel {
147
+ let max = chain.head.trust_level;
148
+ let current: ProvenanceChain | null = chain.tail;
149
+
150
+ while (current !== null) {
151
+ if (current.head.trust_level > max) {
152
+ max = current.head.trust_level;
153
+ }
154
+ current = current.tail;
155
+ }
156
+
157
+ return max;
158
+ }
159
+
160
+ /**
161
+ * Check if chain contains a specific attribution type.
162
+ */
163
+ export function hasAttribution(
164
+ chain: ProvenanceChain,
165
+ attribution: Attribution
166
+ ): boolean {
167
+ let current: ProvenanceChain | null = chain;
168
+
169
+ while (current !== null) {
170
+ if (current.head.attribution === attribution) {
171
+ return true;
172
+ }
173
+ current = current.tail;
174
+ }
175
+
176
+ return false;
177
+ }
178
+
179
+ /**
180
+ * Get all unique attributions in the chain.
181
+ */
182
+ export function getAttributions(chain: ProvenanceChain): Attribution[] {
183
+ const attributions = new Set<Attribution>();
184
+ let current: ProvenanceChain | null = chain;
185
+
186
+ while (current !== null) {
187
+ attributions.add(current.head.attribution);
188
+ current = current.tail;
189
+ }
190
+
191
+ return Array.from(attributions);
192
+ }
193
+
194
+ // ============================================================================
195
+ // CHAIN VERIFICATION
196
+ // ============================================================================
197
+
198
+ /**
199
+ * Verify the integrity of a provenance chain.
200
+ * Checks that all hash links are valid.
201
+ */
202
+ export async function verifyChain(chain: ProvenanceChain): Promise<{
203
+ valid: boolean;
204
+ errors: string[];
205
+ }> {
206
+ const errors: string[] = [];
207
+
208
+ // Single-record chain
209
+ if (chain.length === 1) {
210
+ const expectedHash = await sha256Object(chain.head);
211
+ if (expectedHash !== chain.chain_hash) {
212
+ errors.push('Chain hash mismatch for single-record chain');
213
+ }
214
+ return { valid: errors.length === 0, errors };
215
+ }
216
+
217
+ // Multi-record chain
218
+ let current: ProvenanceChain | null = chain;
219
+ const recordHashes: Hash[] = [];
220
+
221
+ while (current !== null) {
222
+ const recordHash = await sha256Object(current.head);
223
+ recordHashes.unshift(recordHash); // Add to front (we're traversing head to tail)
224
+
225
+ // Check parent_hash linkage
226
+ if (current.tail !== null && current.head.parent_hash !== current.tail.chain_hash) {
227
+ errors.push(`Parent hash mismatch at depth ${recordHashes.length}`);
228
+ }
229
+
230
+ current = current.tail;
231
+ }
232
+
233
+ // Verify rolling hash
234
+ const expectedChainHash = await computeChainHash(chain);
235
+ if (expectedChainHash !== chain.chain_hash) {
236
+ errors.push('Rolling chain hash verification failed');
237
+ }
238
+
239
+ return { valid: errors.length === 0, errors };
240
+ }
241
+
242
+ /**
243
+ * Recompute the chain hash from records.
244
+ */
245
+ async function computeChainHash(chain: ProvenanceChain): Promise<Hash> {
246
+ if (chain.tail === null) {
247
+ return sha256Object(chain.head);
248
+ }
249
+
250
+ const tailHash = await computeChainHash(chain.tail);
251
+ const headHash = await sha256Object(chain.head);
252
+ return rollingHash([tailHash, headHash]);
253
+ }
254
+
255
+ // ============================================================================
256
+ // CHAIN MERGING
257
+ // ============================================================================
258
+
259
+ /**
260
+ * Merge multiple provenance chains into one.
261
+ * Used when composing multiple fragments into a manifold.
262
+ *
263
+ * Strategy: Creates a new chain with all records, ordered by timestamp.
264
+ */
265
+ export async function mergeChains(
266
+ chains: readonly ProvenanceChain[]
267
+ ): Promise<ProvenanceChain> {
268
+ if (chains.length === 0) {
269
+ throw new Error('Cannot merge empty chain array');
270
+ }
271
+
272
+ if (chains.length === 1) {
273
+ const first = chains[0];
274
+ if (!first) throw new Error('Invalid chain');
275
+ return first;
276
+ }
277
+
278
+ // Collect all records
279
+ const allRecords: ProvenanceRecord[] = [];
280
+ for (const chain of chains) {
281
+ allRecords.push(...flattenChain(chain));
282
+ }
283
+
284
+ // Sort by timestamp (oldest first)
285
+ allRecords.sort((a, b) =>
286
+ new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
287
+ );
288
+
289
+ // Deduplicate by source + timestamp
290
+ const seen = new Set<string>();
291
+ const uniqueRecords = allRecords.filter(record => {
292
+ const key = `${record.source}:${record.timestamp}`;
293
+ if (seen.has(key)) return false;
294
+ seen.add(key);
295
+ return true;
296
+ });
297
+
298
+ // Build new chain
299
+ const firstRecord = uniqueRecords[0];
300
+ if (!firstRecord) {
301
+ throw new Error('No records to merge');
302
+ }
303
+
304
+ let result = await createProvenanceChain(firstRecord);
305
+
306
+ for (let i = 1; i < uniqueRecords.length; i++) {
307
+ const record = uniqueRecords[i];
308
+ if (record) {
309
+ result = await extendProvenanceChain(result, record);
310
+ }
311
+ }
312
+
313
+ return result;
314
+ }
315
+
316
+ // ============================================================================
317
+ // UTILITY FUNCTIONS
318
+ // ============================================================================
319
+
320
+ /**
321
+ * Get default trust level for an attribution type.
322
+ */
323
+ function getDefaultTrust(attribution: Attribution): number {
324
+ switch (attribution) {
325
+ case 'system':
326
+ return 100;
327
+ case 'operator':
328
+ return 90;
329
+ case 'user':
330
+ return 70;
331
+ case 'derived':
332
+ return 60;
333
+ case 'agent':
334
+ return 50;
335
+ case 'external':
336
+ return 30;
337
+ default:
338
+ return 50;
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Validate and clamp trust level to 0-100.
344
+ */
345
+ function validateTrustLevel(value: number): TrustLevel {
346
+ const clamped = Math.max(0, Math.min(100, Math.round(value)));
347
+ return clamped as TrustLevel;
348
+ }
349
+
350
+ /**
351
+ * Parse a source string into a SourceURI.
352
+ * Validates the format if strict mode is enabled.
353
+ */
354
+ export function parseSourceURI(source: string, strict = false): SourceURI {
355
+ if (strict) {
356
+ // Validate URI format: scheme://path
357
+ const uriPattern = /^[a-z][a-z0-9+.-]*:\/\/.+$/i;
358
+ if (!uriPattern.test(source)) {
359
+ throw new Error('Invalid source URI format');
360
+ }
361
+ }
362
+
363
+ return source as SourceURI;
364
+ }
365
+
366
+ /**
367
+ * Create a timestamp for the current moment.
368
+ */
369
+ export function now(): Timestamp {
370
+ return new Date().toISOString() as Timestamp;
371
+ }
372
+
373
+ /**
374
+ * Check if a timestamp is expired given a max age.
375
+ */
376
+ export function isExpired(timestamp: Timestamp, maxAgeMs: number): boolean {
377
+ const then = new Date(timestamp).getTime();
378
+ const now = Date.now();
379
+ return (now - then) > maxAgeMs;
380
+ }