@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,253 @@
1
+ /**
2
+ * Caret — HMAC Seal Utilities
3
+ * @module @longarcstudios/caret/crypto/hmac
4
+ *
5
+ * HMAC-SHA256 implementation for tamper-evident sealing.
6
+ * Seals bind content to a secret key — any modification invalidates the seal.
7
+ */
8
+
9
+ import type { Seal, Hash } from '../types.js';
10
+ import { deterministicStringify, constantTimeEqual } from './hash.js';
11
+
12
+ // ============================================================================
13
+ // CONSTANTS
14
+ // ============================================================================
15
+
16
+ const ALGORITHM = { name: 'HMAC', hash: 'SHA-256' };
17
+ const KEY_USAGES: KeyUsage[] = ['sign', 'verify'];
18
+
19
+ // SECURITY: HKDF_INFO must match core/crypto.ts to ensure cross-module
20
+ // seal verification works. Unified in SA-2026-008 (Feb 13, 2026).
21
+ // Prior value 'caret-seal-v1' caused silent verification failures.
22
+ const HKDF_INFO = new TextEncoder().encode('mdash-seal-v3');
23
+ const HKDF_SALT = new TextEncoder().encode('caret-context-primitive-engine');
24
+
25
+ // ============================================================================
26
+ // KEY MANAGEMENT
27
+ // ============================================================================
28
+
29
+ /**
30
+ * Derive an HMAC key from a master key using HKDF.
31
+ * SECURITY: Key is bound to 'mdash-seal-v3' context, unified with core/crypto.ts.
32
+ */
33
+ async function deriveKey(masterKey: string): Promise<CryptoKey> {
34
+ const crypto = await getCrypto();
35
+ const encoder = new TextEncoder();
36
+ const keyMaterial = encoder.encode(masterKey);
37
+
38
+ // Import as raw key material for HKDF
39
+ const baseKey = await crypto.importKey(
40
+ 'raw',
41
+ keyMaterial,
42
+ 'HKDF',
43
+ false,
44
+ ['deriveKey']
45
+ );
46
+
47
+ // Derive HMAC key using HKDF
48
+ return crypto.deriveKey(
49
+ {
50
+ name: 'HKDF',
51
+ hash: 'SHA-256',
52
+ salt: HKDF_SALT,
53
+ info: HKDF_INFO,
54
+ },
55
+ baseKey,
56
+ ALGORITHM,
57
+ false, // not extractable
58
+ KEY_USAGES
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Get crypto implementation (same as hash.ts).
64
+ */
65
+ async function getCrypto(): Promise<SubtleCrypto> {
66
+ if (typeof window !== 'undefined' && window.crypto?.subtle) {
67
+ return window.crypto.subtle;
68
+ }
69
+
70
+ if (typeof globalThis !== 'undefined' && (globalThis as any).crypto?.subtle) {
71
+ return (globalThis as any).crypto.subtle;
72
+ }
73
+
74
+ try {
75
+ const crypto = await import('crypto');
76
+ if (crypto.webcrypto?.subtle) {
77
+ return crypto.webcrypto.subtle as SubtleCrypto;
78
+ }
79
+ } catch {
80
+ // Import failed
81
+ }
82
+
83
+ throw new Error('No crypto implementation available');
84
+ }
85
+
86
+ /**
87
+ * Convert ArrayBuffer to hex string.
88
+ */
89
+ function bufferToHex(buffer: ArrayBuffer): string {
90
+ const bytes = new Uint8Array(buffer);
91
+ let hex = '';
92
+ for (let i = 0; i < bytes.length; i++) {
93
+ const byte = bytes[i];
94
+ if (byte !== undefined) {
95
+ hex += byte.toString(16).padStart(2, '0');
96
+ }
97
+ }
98
+ return hex;
99
+ }
100
+
101
+ // ============================================================================
102
+ // PUBLIC API
103
+ // ============================================================================
104
+
105
+ /**
106
+ * Generate an HMAC-SHA256 seal for content.
107
+ *
108
+ * @param content - The content to seal (will be JSON-stringified)
109
+ * @param key - The secret key
110
+ * @returns Promise resolving to the seal
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * const seal = await hmacSeal({ data: 'sensitive' }, 'secret-key');
115
+ * ```
116
+ */
117
+ export async function hmacSeal(content: unknown, key: string): Promise<Seal> {
118
+ const crypto = await getCrypto();
119
+ const cryptoKey = await deriveKey(key); // SECURITY: Use HKDF-derived key
120
+ const encoder = new TextEncoder();
121
+
122
+ // Deterministic serialization
123
+ const data = encoder.encode(deterministicStringify(content));
124
+
125
+ const signature = await crypto.sign(ALGORITHM, cryptoKey, data);
126
+ return bufferToHex(signature) as Seal;
127
+ }
128
+
129
+ /**
130
+ * Verify an HMAC seal against content.
131
+ *
132
+ * @param content - The content to verify
133
+ * @param seal - The seal to check
134
+ * @param key - The secret key
135
+ * @returns Promise resolving to boolean
136
+ */
137
+ export async function hmacVerify(content: unknown, seal: Seal, key: string): Promise<boolean> {
138
+ const expectedSeal = await hmacSeal(content, key);
139
+ return constantTimeEqual(seal, expectedSeal);
140
+ }
141
+
142
+ /**
143
+ * Create a seal binding multiple values together.
144
+ * Useful for sealing a fragment with all its metadata.
145
+ *
146
+ * @param values - Object with named values to seal
147
+ * @param key - The secret key
148
+ * @returns Promise resolving to the seal
149
+ */
150
+ export async function hmacSealMultiple(
151
+ values: Record<string, unknown>,
152
+ key: string
153
+ ): Promise<Seal> {
154
+ // Sort keys and create deterministic representation
155
+ const sorted: Record<string, unknown> = {};
156
+ const keys = Object.keys(values).sort();
157
+ for (const k of keys) {
158
+ sorted[k] = values[k];
159
+ }
160
+
161
+ return hmacSeal(sorted, key);
162
+ }
163
+
164
+ /**
165
+ * Generate a seal for a context fragment.
166
+ * Seals all critical fields to detect any tampering.
167
+ *
168
+ * @param fragment - Fragment data to seal (without the seal field)
169
+ * @param key - The secret key
170
+ * @returns Promise resolving to the seal
171
+ */
172
+ export async function sealFragment(
173
+ fragment: {
174
+ id: string;
175
+ hash: Hash;
176
+ content: unknown;
177
+ provenance: unknown;
178
+ sealed_at: string;
179
+ constraints: unknown;
180
+ },
181
+ key: string
182
+ ): Promise<Seal> {
183
+ // Create canonical representation for sealing
184
+ // SECURITY: _v binds seal to protocol version, preventing downgrade attacks
185
+ const canonical = {
186
+ _v: 1,
187
+ id: fragment.id,
188
+ hash: fragment.hash,
189
+ content: fragment.content,
190
+ provenance: fragment.provenance,
191
+ sealed_at: fragment.sealed_at,
192
+ constraints: fragment.constraints,
193
+ };
194
+
195
+ return hmacSeal(canonical, key);
196
+ }
197
+
198
+ /**
199
+ * Verify a fragment's seal.
200
+ *
201
+ * @param fragment - The fragment to verify
202
+ * @param key - The secret key
203
+ * @returns Promise resolving to boolean
204
+ */
205
+ export async function verifyFragmentSeal(
206
+ fragment: {
207
+ id: string;
208
+ hash: Hash;
209
+ content: unknown;
210
+ provenance: unknown;
211
+ sealed_at: string;
212
+ constraints: unknown;
213
+ seal: Seal;
214
+ },
215
+ key: string
216
+ ): Promise<boolean> {
217
+ // SECURITY: Must match _v from sealFragment
218
+ const canonical = {
219
+ _v: 1,
220
+ id: fragment.id,
221
+ hash: fragment.hash,
222
+ content: fragment.content,
223
+ provenance: fragment.provenance,
224
+ sealed_at: fragment.sealed_at,
225
+ constraints: fragment.constraints,
226
+ };
227
+
228
+ return hmacVerify(canonical, fragment.seal, key);
229
+ }
230
+
231
+ // ============================================================================
232
+ // SEAL UTILITIES
233
+ // ============================================================================
234
+
235
+ /**
236
+ * Validate seal format.
237
+ */
238
+ export function isValidSeal(value: string): value is Seal {
239
+ return typeof value === 'string' &&
240
+ value.length === 64 &&
241
+ /^[a-f0-9]+$/i.test(value);
242
+ }
243
+
244
+ /**
245
+ * Parse a string as a Seal, throwing if invalid.
246
+ */
247
+ export function parseSeal(value: string): Seal {
248
+ if (!isValidSeal(value)) {
249
+ // SECURITY: Do not leak input value in error message
250
+ throw new Error('Invalid seal format');
251
+ }
252
+ return value;
253
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Caret — Cryptographic Utilities
3
+ * @module @longarcstudios/caret/crypto
4
+ */
5
+
6
+ export {
7
+ sha256,
8
+ sha256Object,
9
+ sha256Binary,
10
+ rollingHash,
11
+ verifyHash,
12
+ verifyObjectHash,
13
+ isValidHash,
14
+ parseHash,
15
+ unsafeHash,
16
+ hexToBuffer,
17
+ deterministicStringify,
18
+ constantTimeEqual,
19
+ } from './hash.js';
20
+
21
+ export {
22
+ hmacSeal,
23
+ hmacVerify,
24
+ hmacSealMultiple,
25
+ sealFragment,
26
+ verifyFragmentSeal,
27
+ isValidSeal,
28
+ parseSeal,
29
+ } from './hmac.js';