@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.
- 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.map +1 -1
- package/dist/checkpoint/engine.js +4 -0
- 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/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 +25 -2
- package/dist/core/commitment.d.ts.map +1 -1
- package/dist/core/commitment.js +44 -6
- 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 +1 -0
- package/dist/physics/engine.d.ts.map +1 -1
- package/dist/physics/engine.js +36 -2
- 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 +4 -0
- 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/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 +129 -67
- 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 +40 -3
- 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
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AccountabilityEngine Test Suite
|
|
3
|
+
*
|
|
4
|
+
* Full lifecycle: issue warrant → check action → commit attestation → verify
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
8
|
+
import { AccountabilityEngine } from '../accountability/engine.js';
|
|
9
|
+
import type { WarrantPermissions } from '../accountability/types.js';
|
|
10
|
+
|
|
11
|
+
const SEAL_KEY = 'test-seal-key-minimum-32-characters-long';
|
|
12
|
+
|
|
13
|
+
const DEFAULT_PERMISSIONS: WarrantPermissions = {
|
|
14
|
+
allowedActions: ['read', 'write', 'query'],
|
|
15
|
+
forbiddenActions: ['delete', 'drop-table'],
|
|
16
|
+
ttlMs: 60_000,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('AccountabilityEngine', () => {
|
|
20
|
+
let engine: AccountabilityEngine;
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
engine = new AccountabilityEngine();
|
|
24
|
+
await engine.initialize(SEAL_KEY);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// ── Authorization ──
|
|
28
|
+
|
|
29
|
+
it('should execute authorized actions with cryptographic attestation', async () => {
|
|
30
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
31
|
+
|
|
32
|
+
const result = await engine.executeAction('agent-1', 'read', { file: 'data.csv' });
|
|
33
|
+
|
|
34
|
+
expect(result.executed).toBe(true);
|
|
35
|
+
expect(result.commitment).toBeDefined();
|
|
36
|
+
expect(result.commitment!.content_hash).toBeTruthy();
|
|
37
|
+
expect(result.commitment!.seal).toBeTruthy();
|
|
38
|
+
expect(result.verified).toBe(true);
|
|
39
|
+
expect(result.violation).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should verify commitment seals are cryptographically valid', async () => {
|
|
43
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
44
|
+
const result = await engine.executeAction('agent-1', 'read', {});
|
|
45
|
+
|
|
46
|
+
const valid = await engine.verifyCommitment(result.commitment!);
|
|
47
|
+
expect(valid).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should handle multiple authorized actions with distinct commitments', async () => {
|
|
51
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
52
|
+
|
|
53
|
+
const r1 = await engine.executeAction('agent-1', 'read', { id: 1 });
|
|
54
|
+
const r2 = await engine.executeAction('agent-1', 'write', { id: 2 });
|
|
55
|
+
const r3 = await engine.executeAction('agent-1', 'query', { sql: 'SELECT 1' });
|
|
56
|
+
|
|
57
|
+
expect(r1.executed).toBe(true);
|
|
58
|
+
expect(r2.executed).toBe(true);
|
|
59
|
+
expect(r3.executed).toBe(true);
|
|
60
|
+
|
|
61
|
+
// Each gets a unique commitment
|
|
62
|
+
expect(r1.commitment!.id).not.toBe(r2.commitment!.id);
|
|
63
|
+
expect(r2.commitment!.id).not.toBe(r3.commitment!.id);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// ── Denial: Forbidden Actions ──
|
|
67
|
+
|
|
68
|
+
it('should deny forbidden actions with typed violation', async () => {
|
|
69
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
70
|
+
|
|
71
|
+
const result = await engine.executeAction('agent-1', 'delete', { target: 'users' });
|
|
72
|
+
|
|
73
|
+
expect(result.executed).toBe(false);
|
|
74
|
+
expect(result.violation).toBeDefined();
|
|
75
|
+
expect(result.violation!.type).toBe('FORBIDDEN_ACTION');
|
|
76
|
+
expect(result.violation!.agentId).toBe('agent-1');
|
|
77
|
+
expect(result.violation!.action).toBe('delete');
|
|
78
|
+
expect(result.commitment).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should deny forbidden actions even if also in allowed list', async () => {
|
|
82
|
+
// Forbidden takes precedence
|
|
83
|
+
await engine.issueWarrant('agent-1', {
|
|
84
|
+
allowedActions: ['delete'],
|
|
85
|
+
forbiddenActions: ['delete'],
|
|
86
|
+
ttlMs: 60_000,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = await engine.executeAction('agent-1', 'delete', {});
|
|
90
|
+
expect(result.executed).toBe(false);
|
|
91
|
+
expect(result.violation!.type).toBe('FORBIDDEN_ACTION');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ── Denial: Unauthorized Actions ──
|
|
95
|
+
|
|
96
|
+
it('should deny actions not in the allowed list', async () => {
|
|
97
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
98
|
+
|
|
99
|
+
const result = await engine.executeAction('agent-1', 'execute-shell', { cmd: 'rm -rf /' });
|
|
100
|
+
|
|
101
|
+
expect(result.executed).toBe(false);
|
|
102
|
+
expect(result.violation!.type).toBe('UNAUTHORIZED_ACTION');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ── Denial: No Warrant ──
|
|
106
|
+
|
|
107
|
+
it('should deny actions from agents with no warrant', async () => {
|
|
108
|
+
const result = await engine.executeAction('unknown-agent', 'read', {});
|
|
109
|
+
|
|
110
|
+
expect(result.executed).toBe(false);
|
|
111
|
+
expect(result.violation!.type).toBe('NO_WARRANT');
|
|
112
|
+
expect(result.violation!.agentId).toBe('unknown-agent');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// ── Denial: Expired Warrants ──
|
|
116
|
+
|
|
117
|
+
it('should deny actions when warrant has expired', async () => {
|
|
118
|
+
await engine.issueWarrant('agent-1', {
|
|
119
|
+
allowedActions: ['read'],
|
|
120
|
+
forbiddenActions: [],
|
|
121
|
+
ttlMs: 1, // 1ms TTL — will expire immediately
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Wait for expiry
|
|
125
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
126
|
+
|
|
127
|
+
const result = await engine.executeAction('agent-1', 'read', {});
|
|
128
|
+
|
|
129
|
+
expect(result.executed).toBe(false);
|
|
130
|
+
expect(result.violation!.type).toBe('WARRANT_EXPIRED');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// ── Denial: Revoked Warrants ──
|
|
134
|
+
|
|
135
|
+
it('should deny actions after warrant revocation', async () => {
|
|
136
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
137
|
+
|
|
138
|
+
// Authorized before revocation
|
|
139
|
+
const before = await engine.executeAction('agent-1', 'read', {});
|
|
140
|
+
expect(before.executed).toBe(true);
|
|
141
|
+
|
|
142
|
+
engine.revokeWarrant('agent-1');
|
|
143
|
+
|
|
144
|
+
const after = await engine.executeAction('agent-1', 'read', {});
|
|
145
|
+
expect(after.executed).toBe(false);
|
|
146
|
+
expect(after.violation!.type).toBe('WARRANT_REVOKED');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// ── Denial: Execution Limit ──
|
|
150
|
+
|
|
151
|
+
it('should deny actions when execution limit is reached', async () => {
|
|
152
|
+
await engine.issueWarrant('agent-1', {
|
|
153
|
+
allowedActions: ['read'],
|
|
154
|
+
forbiddenActions: [],
|
|
155
|
+
ttlMs: 60_000,
|
|
156
|
+
maxExecutions: 2,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const r1 = await engine.executeAction('agent-1', 'read', { n: 1 });
|
|
160
|
+
const r2 = await engine.executeAction('agent-1', 'read', { n: 2 });
|
|
161
|
+
const r3 = await engine.executeAction('agent-1', 'read', { n: 3 });
|
|
162
|
+
|
|
163
|
+
expect(r1.executed).toBe(true);
|
|
164
|
+
expect(r2.executed).toBe(true);
|
|
165
|
+
expect(r3.executed).toBe(false);
|
|
166
|
+
expect(r3.violation!.type).toBe('EXECUTION_LIMIT_REACHED');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// ── Audit Trail ──
|
|
170
|
+
|
|
171
|
+
it('should produce correct audit summary', async () => {
|
|
172
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
173
|
+
|
|
174
|
+
await engine.executeAction('agent-1', 'read', {});
|
|
175
|
+
await engine.executeAction('agent-1', 'write', {});
|
|
176
|
+
await engine.executeAction('agent-1', 'delete', {});
|
|
177
|
+
await engine.executeAction('agent-1', 'execute-shell', {});
|
|
178
|
+
|
|
179
|
+
const audit = engine.getAuditSummary();
|
|
180
|
+
|
|
181
|
+
expect(audit.total).toBe(4);
|
|
182
|
+
expect(audit.authorized).toBe(2);
|
|
183
|
+
expect(audit.denied).toBe(2);
|
|
184
|
+
expect(audit.log).toHaveLength(4);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should include commit details in audit records for attested actions', async () => {
|
|
188
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
189
|
+
await engine.executeAction('agent-1', 'read', { file: 'test.txt' });
|
|
190
|
+
|
|
191
|
+
const audit = engine.getAuditSummary();
|
|
192
|
+
const record = audit.log[0]!;
|
|
193
|
+
|
|
194
|
+
expect(record.type).toBe('ATTESTED_ACTION');
|
|
195
|
+
expect(record.commitId).toBeTruthy();
|
|
196
|
+
expect(record.contentHash).toBeTruthy();
|
|
197
|
+
expect(record.verified).toBe(true);
|
|
198
|
+
expect(record.warrantId).toBeTruthy();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should include violation details in audit records for denied actions', async () => {
|
|
202
|
+
await engine.issueWarrant('agent-1', DEFAULT_PERMISSIONS);
|
|
203
|
+
await engine.executeAction('agent-1', 'delete', {});
|
|
204
|
+
|
|
205
|
+
const audit = engine.getAuditSummary();
|
|
206
|
+
const record = audit.log[0]!;
|
|
207
|
+
|
|
208
|
+
expect(record.type).toBe('FORBIDDEN_ACTION');
|
|
209
|
+
expect(record.detail).toContain('forbidden');
|
|
210
|
+
expect(record.warrantId).toBeTruthy();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// ── Multi-Agent Isolation ──
|
|
214
|
+
|
|
215
|
+
it('should isolate warrants between agents', async () => {
|
|
216
|
+
await engine.issueWarrant('agent-a', {
|
|
217
|
+
allowedActions: ['read'],
|
|
218
|
+
forbiddenActions: ['write'],
|
|
219
|
+
ttlMs: 60_000,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await engine.issueWarrant('agent-b', {
|
|
223
|
+
allowedActions: ['write'],
|
|
224
|
+
forbiddenActions: ['read'],
|
|
225
|
+
ttlMs: 60_000,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// agent-a can read but not write
|
|
229
|
+
expect((await engine.executeAction('agent-a', 'read', {})).executed).toBe(true);
|
|
230
|
+
expect((await engine.executeAction('agent-a', 'write', {})).executed).toBe(false);
|
|
231
|
+
|
|
232
|
+
// agent-b can write but not read
|
|
233
|
+
expect((await engine.executeAction('agent-b', 'write', {})).executed).toBe(true);
|
|
234
|
+
expect((await engine.executeAction('agent-b', 'read', {})).executed).toBe(false);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// ── Full Lifecycle ──
|
|
238
|
+
|
|
239
|
+
it('should support the full lifecycle: issue → execute → deny → revoke → audit', async () => {
|
|
240
|
+
// Issue
|
|
241
|
+
await engine.issueWarrant('lifecycle-agent', {
|
|
242
|
+
allowedActions: ['query-database', 'read-file'],
|
|
243
|
+
forbiddenActions: ['delete-database'],
|
|
244
|
+
ttlMs: 60_000,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Execute authorized
|
|
248
|
+
const authorized = await engine.executeAction('lifecycle-agent', 'query-database', {
|
|
249
|
+
table: 'users',
|
|
250
|
+
limit: 100,
|
|
251
|
+
});
|
|
252
|
+
expect(authorized.executed).toBe(true);
|
|
253
|
+
expect(authorized.verified).toBe(true);
|
|
254
|
+
|
|
255
|
+
// Deny forbidden
|
|
256
|
+
const denied = await engine.executeAction('lifecycle-agent', 'delete-database', {
|
|
257
|
+
target: 'users',
|
|
258
|
+
});
|
|
259
|
+
expect(denied.executed).toBe(false);
|
|
260
|
+
expect(denied.violation!.type).toBe('FORBIDDEN_ACTION');
|
|
261
|
+
|
|
262
|
+
// Revoke
|
|
263
|
+
engine.revokeWarrant('lifecycle-agent');
|
|
264
|
+
|
|
265
|
+
// Deny after revocation
|
|
266
|
+
const postRevoke = await engine.executeAction('lifecycle-agent', 'read-file', {});
|
|
267
|
+
expect(postRevoke.executed).toBe(false);
|
|
268
|
+
expect(postRevoke.violation!.type).toBe('WARRANT_REVOKED');
|
|
269
|
+
|
|
270
|
+
// Audit
|
|
271
|
+
const audit = engine.getAuditSummary();
|
|
272
|
+
expect(audit.authorized).toBe(1);
|
|
273
|
+
expect(audit.denied).toBe(2);
|
|
274
|
+
expect(audit.total).toBe(3);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// ── Warrant checks happen BEFORE execution ──
|
|
278
|
+
|
|
279
|
+
it('should check warrant before creating commitment (no partial attestation on denial)', async () => {
|
|
280
|
+
// No warrant — should not create any commitment
|
|
281
|
+
const result = await engine.executeAction('no-warrant-agent', 'read', {});
|
|
282
|
+
|
|
283
|
+
expect(result.executed).toBe(false);
|
|
284
|
+
expect(result.commitment).toBeUndefined();
|
|
285
|
+
expect(result.verified).toBeUndefined();
|
|
286
|
+
|
|
287
|
+
// Audit should have zero attested actions
|
|
288
|
+
const audit = engine.getAuditSummary();
|
|
289
|
+
expect(audit.authorized).toBe(0);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ── Revoking nonexistent warrant is safe ──
|
|
293
|
+
|
|
294
|
+
it('should handle revoking a warrant that does not exist', () => {
|
|
295
|
+
// Should not throw
|
|
296
|
+
expect(() => engine.revokeWarrant('nonexistent-agent')).not.toThrow();
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// ── Audit starts empty ──
|
|
300
|
+
|
|
301
|
+
it('should return empty audit summary when no actions have been taken', () => {
|
|
302
|
+
const audit = engine.getAuditSummary();
|
|
303
|
+
expect(audit.total).toBe(0);
|
|
304
|
+
expect(audit.authorized).toBe(0);
|
|
305
|
+
expect(audit.denied).toBe(0);
|
|
306
|
+
expect(audit.log).toHaveLength(0);
|
|
307
|
+
});
|
|
308
|
+
});
|