@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
@@ -0,0 +1,86 @@
1
+ /**
2
+ * SA-2026-009: ZK seal verification gap
3
+ * Verifies that verifyProof rejects documents with tampered seals.
4
+ * Prior to fix: expectedSeal was computed but never compared.
5
+ */
6
+
7
+ import { describe, it, expect, beforeAll } from 'vitest';
8
+ import { CommitmentEngine } from '../core/commitment.js';
9
+ import { ZKProofsEngine } from '../zk/engine.js';
10
+ import type { Seal } from '../core/crypto.js';
11
+
12
+ const TEST_KEY = 'test-seal-key-zk-verify-gap-minimum-32-chars';
13
+
14
+ describe('SA-2026-009: ZK seal verification gap', () => {
15
+ let commitmentEngine: CommitmentEngine;
16
+ let zkEngine: ZKProofsEngine;
17
+
18
+ beforeAll(async () => {
19
+ commitmentEngine = new CommitmentEngine();
20
+ await commitmentEngine.initialize(TEST_KEY);
21
+ zkEngine = new ZKProofsEngine(commitmentEngine);
22
+ await zkEngine.initialize(TEST_KEY);
23
+ });
24
+
25
+ it('verifyProof accepts a validly sealed document', async () => {
26
+ const doc = await zkEngine.requestProof({
27
+ type: 'commitment_inclusion',
28
+ statement: {
29
+ description: 'SA-2026-009 valid seal test',
30
+ claim: { test: 'valid-seal' },
31
+ },
32
+ });
33
+
34
+ const completed = await zkEngine.waitForProof(doc.id, 5000);
35
+ const result = await zkEngine.verifyProof(completed);
36
+
37
+ expect(result.valid).toBe(true);
38
+ expect(result.errors).toHaveLength(0);
39
+ });
40
+
41
+ it('verifyProof rejects a document with a tampered seal', async () => {
42
+ const doc = await zkEngine.requestProof({
43
+ type: 'commitment_inclusion',
44
+ statement: {
45
+ description: 'SA-2026-009 tampered seal test',
46
+ claim: { test: 'tampered-seal' },
47
+ },
48
+ });
49
+
50
+ const completed = await zkEngine.waitForProof(doc.id, 5000);
51
+
52
+ // Tamper with the seal
53
+ const tampered = { ...completed, seal: 'tampered-seal-value' as Seal };
54
+
55
+ const result = await zkEngine.verifyProof(tampered);
56
+
57
+ expect(result.valid).toBe(false);
58
+ expect(result.errors).toContain('Seal verification failed');
59
+ });
60
+
61
+ it('verifyProof rejects a document with mutated content', async () => {
62
+ const doc = await zkEngine.requestProof({
63
+ type: 'commitment_inclusion',
64
+ statement: {
65
+ description: 'SA-2026-009 mutation test',
66
+ claim: { test: 'content-mutation' },
67
+ },
68
+ });
69
+
70
+ const completed = await zkEngine.waitForProof(doc.id, 5000);
71
+
72
+ // Mutate content without re-sealing
73
+ const mutated = {
74
+ ...completed,
75
+ statement: {
76
+ ...completed.statement,
77
+ description: 'ALTERED after sealing',
78
+ },
79
+ };
80
+
81
+ const result = await zkEngine.verifyProof(mutated);
82
+
83
+ expect(result.valid).toBe(false);
84
+ expect(result.errors).toContain('Seal verification failed');
85
+ });
86
+ });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * SA-2026-010: Checkpoint fire-and-forget error handling
3
+ * Verifies that L1 commitment failures are caught and surfaced
4
+ * via checkpoint status rather than silently swallowed.
5
+ */
6
+
7
+ import { describe, it, expect, beforeAll, vi } from 'vitest';
8
+ import { CommitmentEngine } from '../core/commitment.js';
9
+ import { CheckpointEngine } from '../checkpoint/engine.js';
10
+
11
+ const TEST_KEY = 'test-seal-key-checkpoint-catch-minimum-32-chars';
12
+
13
+ describe('SA-2026-010: Checkpoint fire-and-forget error handling', () => {
14
+ let commitmentEngine: CommitmentEngine;
15
+ let checkpointEngine: CheckpointEngine;
16
+
17
+ beforeAll(async () => {
18
+ commitmentEngine = new CommitmentEngine();
19
+ await commitmentEngine.initialize(TEST_KEY);
20
+ checkpointEngine = new CheckpointEngine(commitmentEngine);
21
+ await checkpointEngine.initialize(TEST_KEY);
22
+ });
23
+
24
+ it('checkpoint status becomes failed when L1 commit rejects', async () => {
25
+ // Spy on commit and make it reject
26
+ const commitSpy = vi.spyOn(commitmentEngine, 'commit')
27
+ .mockRejectedValueOnce(new Error('Simulated L1 failure'));
28
+
29
+ // Suppress expected console.error
30
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
31
+
32
+ const checkpoint = await checkpointEngine.createCheckpoint({
33
+ agent_id: 'test-agent-sa010',
34
+ trigger: 'action_start',
35
+ state: {
36
+ warrant_id: 'w-test-sa010' as any,
37
+ action_type: 'test',
38
+ context_hash: 'hash-test' as any,
39
+ },
40
+ });
41
+
42
+ // checkpoint is returned immediately (fire-and-forget)
43
+ expect(checkpoint.status).toBe('pending');
44
+
45
+ // Wait for the async .then/.catch to resolve
46
+ await new Promise(resolve => setTimeout(resolve, 50));
47
+
48
+ // After failure, status should be 'failed', not stuck on 'pending'
49
+ expect(checkpoint.status).toBe('failed');
50
+
51
+ commitSpy.mockRestore();
52
+ errorSpy.mockRestore();
53
+ });
54
+
55
+ it('checkpoint status becomes sealed on successful L1 commit', async () => {
56
+ const checkpoint = await checkpointEngine.createCheckpoint({
57
+ agent_id: 'test-agent-sa010-ok',
58
+ trigger: 'action_start',
59
+ state: {
60
+ warrant_id: 'w-test-sa010-ok' as any,
61
+ action_type: 'test',
62
+ context_hash: 'hash-test-ok' as any,
63
+ },
64
+ });
65
+
66
+ // Wait for async commit
67
+ await new Promise(resolve => setTimeout(resolve, 50));
68
+
69
+ expect(checkpoint.status).toBe('sealed');
70
+ expect(checkpoint.commitment_id).toBeTruthy();
71
+ });
72
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * SA-2026-012: Influence budget underflow protection
3
+ * Verifies that influence and token counts never go negative
4
+ * after fragment removal.
5
+ */
6
+
7
+ import { describe, it, expect, beforeAll } from 'vitest';
8
+ import { CommitmentEngine } from '../core/commitment.js';
9
+ import { MCCAEngine } from '../mcca/engine.js';
10
+
11
+ const TEST_KEY = 'test-seal-key-mcca-underflow-minimum-32-chars';
12
+
13
+ describe('SA-2026-012: Influence budget underflow protection', () => {
14
+ let commitmentEngine: CommitmentEngine;
15
+ let engine: MCCAEngine;
16
+
17
+ beforeAll(async () => {
18
+ commitmentEngine = new CommitmentEngine();
19
+ await commitmentEngine.initialize(TEST_KEY);
20
+ engine = new MCCAEngine(commitmentEngine);
21
+ await engine.initialize(TEST_KEY);
22
+ });
23
+
24
+ it('influence never goes negative after fragment removal', async () => {
25
+ // Add a fragment
26
+ const fragment = await engine.addFragment({
27
+ content: { test: 'underflow-influence' },
28
+ source_class: 'user',
29
+ region: 'task',
30
+ token_count: 50,
31
+ influence: 0.05,
32
+ });
33
+
34
+ // Remove it once
35
+ await engine.removeFragment(fragment.id);
36
+
37
+ // Remove it again (simulating race or double-remove)
38
+ await engine.removeFragment(fragment.id);
39
+
40
+ // influenceBySource is private; access via cast to verify the floor guard
41
+ const influenceBySource = (engine as any).influenceBySource as Record<string, number>;
42
+ expect(influenceBySource.user).toBeGreaterThanOrEqual(0);
43
+ });
44
+
45
+ it('token count never goes negative after double removal', async () => {
46
+ // Add a fragment
47
+ const fragment = await engine.addFragment({
48
+ content: { test: 'underflow-tokens' },
49
+ source_class: 'system',
50
+ region: 'task',
51
+ token_count: 100,
52
+ influence: 0.1,
53
+ });
54
+
55
+ // Remove it once
56
+ await engine.removeFragment(fragment.id);
57
+
58
+ // Remove again
59
+ await engine.removeFragment(fragment.id);
60
+
61
+ // stats.tokens maps to the internal totalTokens field
62
+ const stats = engine.getStats();
63
+ expect(stats.tokens).toBeGreaterThanOrEqual(0);
64
+ });
65
+ });
@@ -0,0 +1,40 @@
1
+ /**
2
+ * SA-2026-NFC: Unicode normalization in deterministicStringify
3
+ * Verifies that decomposed and precomposed Unicode codepoints
4
+ * produce identical hashes.
5
+ */
6
+
7
+ import { describe, it, expect } from 'vitest';
8
+ import { sha256Object, deterministicStringify } from '../core/crypto.js';
9
+
10
+ describe('SA-2026-NFC: Unicode normalization', () => {
11
+ it('NFD and NFC representations hash identically', async () => {
12
+ // U+00E9 (precomposed e-acute) vs U+0065 + U+0301 (e + combining acute)
13
+ const nfc = { name: '\u00E9' }; // e with acute (precomposed)
14
+ const nfd = { name: '\u0065\u0301' }; // e + combining acute (decomposed)
15
+
16
+ const hashNFC = await sha256Object(nfc);
17
+ const hashNFD = await sha256Object(nfd);
18
+
19
+ expect(hashNFC).toBe(hashNFD);
20
+ });
21
+
22
+ it('deterministicStringify normalizes strings to NFC', () => {
23
+ const nfd = '\u0065\u0301'; // decomposed
24
+ const nfc = '\u00E9'; // precomposed
25
+
26
+ const resultNFD = deterministicStringify({ val: nfd });
27
+ const resultNFC = deterministicStringify({ val: nfc });
28
+
29
+ expect(resultNFD).toBe(resultNFC);
30
+ });
31
+
32
+ it('non-string values are unaffected', () => {
33
+ const result = deterministicStringify({ num: 42, bool: true, nil: null });
34
+ const parsed = JSON.parse(result);
35
+
36
+ expect(parsed.num).toBe(42);
37
+ expect(parsed.bool).toBe(true);
38
+ expect(parsed.nil).toBeNull();
39
+ });
40
+ });