@sentinel-atl/revocation 0.1.1
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 +64 -0
- package/dist/__tests__/revocation.test.d.ts +2 -0
- package/dist/__tests__/revocation.test.d.ts.map +1 -0
- package/dist/__tests__/revocation.test.js +230 -0
- package/dist/__tests__/revocation.test.js.map +1 -0
- package/dist/index.d.ts +200 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +371 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @sentinel-atl/revocation
|
|
2
|
+
|
|
3
|
+
DID and VC revocation, key rotation, and emergency kill switch for the Agent Trust Layer.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **VC revocation** — revoke individual credentials with signed proof
|
|
8
|
+
- **DID revocation** — revoke an entire agent identity
|
|
9
|
+
- **Key rotation** — dual-signature rotation with automatic DID resolution
|
|
10
|
+
- **Kill switch** — emergency cascade termination with signed evidence
|
|
11
|
+
- **Signed revocation lists** — publishable, verifiable revocation state
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @sentinel-atl/revocation
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { RevocationManager } from '@sentinel-atl/revocation';
|
|
23
|
+
import { AuditLog } from '@sentinel-atl/audit';
|
|
24
|
+
|
|
25
|
+
const auditLog = new AuditLog({ logPath: './audit.jsonl' });
|
|
26
|
+
const revMgr = new RevocationManager(auditLog);
|
|
27
|
+
|
|
28
|
+
// Revoke a credential
|
|
29
|
+
await revMgr.revokeVC(keyProvider, keyId, issuerDid, vcId, 'policy_violation', 'Unauthorized access');
|
|
30
|
+
|
|
31
|
+
// Check revocation
|
|
32
|
+
revMgr.isVCRevoked(vcId); // true
|
|
33
|
+
|
|
34
|
+
// Emergency kill switch
|
|
35
|
+
await revMgr.killSwitch(keyProvider, keyId, issuerDid, targetDid, 'Data breach', { cascade: true });
|
|
36
|
+
|
|
37
|
+
// Key rotation
|
|
38
|
+
const rotation = await revMgr.rotateKey(oldKP, oldKeyId, newKP, newKeyId, oldDid, newDid);
|
|
39
|
+
revMgr.resolveCurrentDid(oldDid); // returns newDid
|
|
40
|
+
|
|
41
|
+
// Publish signed revocation list
|
|
42
|
+
const list = await revMgr.publishRevocationList(keyProvider, keyId, issuerDid);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
| Method | Description |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `revokeVC(...)` | Revoke a Verifiable Credential |
|
|
50
|
+
| `revokeDID(...)` | Revoke an entire DID |
|
|
51
|
+
| `isVCRevoked(vcId)` | Check if a VC is revoked |
|
|
52
|
+
| `isTrusted(did)` | Check if a DID is trusted |
|
|
53
|
+
| `killSwitch(...)` | Emergency kill switch |
|
|
54
|
+
| `verifyKillSwitch(event)` | Verify kill switch signature |
|
|
55
|
+
| `rotateKey(...)` | Rotate agent key pair |
|
|
56
|
+
| `verifyKeyRotation(notice)` | Verify key rotation |
|
|
57
|
+
| `resolveCurrentDid(did)` | Resolve to latest DID after rotation |
|
|
58
|
+
| `publishRevocationList(...)` | Publish signed revocation list |
|
|
59
|
+
| `verifyRevocationList(list)` | Verify revocation list |
|
|
60
|
+
| `getStats()` | Get revocation statistics |
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revocation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/revocation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { RevocationManager } from '../index.js';
|
|
3
|
+
import { InMemoryKeyProvider, publicKeyToDid, } from '@sentinel-atl/core';
|
|
4
|
+
async function makeIdentity(keyProvider, name) {
|
|
5
|
+
await keyProvider.generate(name);
|
|
6
|
+
const pubKey = await keyProvider.getPublicKey(name);
|
|
7
|
+
const did = publicKeyToDid(pubKey);
|
|
8
|
+
return { keyId: name, did };
|
|
9
|
+
}
|
|
10
|
+
describe('@sentinel-atl/revocation', () => {
|
|
11
|
+
let keyProvider;
|
|
12
|
+
let manager;
|
|
13
|
+
let admin;
|
|
14
|
+
let agentA;
|
|
15
|
+
let agentB;
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
keyProvider = new InMemoryKeyProvider();
|
|
18
|
+
manager = new RevocationManager();
|
|
19
|
+
admin = await makeIdentity(keyProvider, 'admin');
|
|
20
|
+
agentA = await makeIdentity(keyProvider, 'agentA');
|
|
21
|
+
agentB = await makeIdentity(keyProvider, 'agentB');
|
|
22
|
+
});
|
|
23
|
+
// ─── VC Revocation ────────────────────────────────────────────────
|
|
24
|
+
describe('VC revocation', () => {
|
|
25
|
+
it('revokes a VC and detects it', async () => {
|
|
26
|
+
const credId = 'urn:uuid:test-vc-1';
|
|
27
|
+
expect(manager.isVCRevoked(credId)).toBe(false);
|
|
28
|
+
const entry = await manager.revokeVC(keyProvider, admin.keyId, admin.did, credId, 'policy_violation', 'Used outside scope');
|
|
29
|
+
expect(entry.credentialId).toBe(credId);
|
|
30
|
+
expect(entry.reason).toBe('policy_violation');
|
|
31
|
+
expect(entry.details).toBe('Used outside scope');
|
|
32
|
+
expect(manager.isVCRevoked(credId)).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('returns revocation details', async () => {
|
|
35
|
+
const credId = 'urn:uuid:test-vc-2';
|
|
36
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, credId, 'key_compromise');
|
|
37
|
+
const rev = manager.getVCRevocation(credId);
|
|
38
|
+
expect(rev).toBeDefined();
|
|
39
|
+
expect(rev.reason).toBe('key_compromise');
|
|
40
|
+
expect(rev.revokedAt).toBeDefined();
|
|
41
|
+
});
|
|
42
|
+
it('returns undefined for non-revoked VC', () => {
|
|
43
|
+
expect(manager.getVCRevocation('urn:uuid:not-revoked')).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
// ─── Signed Revocation List ───────────────────────────────────────
|
|
47
|
+
describe('signed revocation list', () => {
|
|
48
|
+
it('publishes and verifies a signed revocation list', async () => {
|
|
49
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, 'urn:uuid:vc-1', 'manual');
|
|
50
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, 'urn:uuid:vc-2', 'scope_violation');
|
|
51
|
+
const list = await manager.publishRevocationList(keyProvider, admin.keyId, admin.did);
|
|
52
|
+
expect(list.version).toBe(1);
|
|
53
|
+
expect(list.issuerDid).toBe(admin.did);
|
|
54
|
+
expect(list.entries).toHaveLength(2);
|
|
55
|
+
expect(list.signature).toBeDefined();
|
|
56
|
+
const result = await manager.verifyRevocationList(list);
|
|
57
|
+
expect(result.valid).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
it('detects tampered revocation list', async () => {
|
|
60
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, 'urn:uuid:vc-tamper', 'manual');
|
|
61
|
+
const list = await manager.publishRevocationList(keyProvider, admin.keyId, admin.did);
|
|
62
|
+
// Tamper: add a fake entry
|
|
63
|
+
list.entries.push({
|
|
64
|
+
credentialId: 'urn:uuid:injected',
|
|
65
|
+
revokedAt: new Date().toISOString(),
|
|
66
|
+
reason: 'manual',
|
|
67
|
+
});
|
|
68
|
+
const result = await manager.verifyRevocationList(list);
|
|
69
|
+
expect(result.valid).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
it('increments version on each publish', async () => {
|
|
72
|
+
const list1 = await manager.publishRevocationList(keyProvider, admin.keyId, admin.did);
|
|
73
|
+
const list2 = await manager.publishRevocationList(keyProvider, admin.keyId, admin.did);
|
|
74
|
+
expect(list1.version).toBe(1);
|
|
75
|
+
expect(list2.version).toBe(2);
|
|
76
|
+
});
|
|
77
|
+
it('imports revocation list entries', async () => {
|
|
78
|
+
// Manager 1 publishes a list
|
|
79
|
+
const manager1 = new RevocationManager();
|
|
80
|
+
await manager1.revokeVC(keyProvider, admin.keyId, admin.did, 'urn:uuid:import-vc-1', 'manual');
|
|
81
|
+
const list = await manager1.publishRevocationList(keyProvider, admin.keyId, admin.did);
|
|
82
|
+
// Manager 2 imports it
|
|
83
|
+
const manager2 = new RevocationManager();
|
|
84
|
+
expect(manager2.isVCRevoked('urn:uuid:import-vc-1')).toBe(false);
|
|
85
|
+
const imported = manager2.importRevocationList(list);
|
|
86
|
+
expect(imported).toBe(1);
|
|
87
|
+
expect(manager2.isVCRevoked('urn:uuid:import-vc-1')).toBe(true);
|
|
88
|
+
// Importing again doesn't duplicate
|
|
89
|
+
const imported2 = manager2.importRevocationList(list);
|
|
90
|
+
expect(imported2).toBe(0);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
// ─── DID Revocation ───────────────────────────────────────────────
|
|
94
|
+
describe('DID revocation', () => {
|
|
95
|
+
it('revokes a DID and detects it', async () => {
|
|
96
|
+
expect(manager.isDIDRevoked(agentA.did)).toBe(false);
|
|
97
|
+
const revocation = await manager.revokeDID(keyProvider, admin.keyId, admin.did, agentA.did, 'agent_decommissioned', 'Agent replaced');
|
|
98
|
+
expect(revocation.did).toBe(agentA.did);
|
|
99
|
+
expect(revocation.revokedBy).toBe(admin.did);
|
|
100
|
+
expect(revocation.reason).toBe('agent_decommissioned');
|
|
101
|
+
expect(manager.isDIDRevoked(agentA.did)).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
it('verifies a DID revocation signature', async () => {
|
|
104
|
+
const revocation = await manager.revokeDID(keyProvider, admin.keyId, admin.did, agentA.did, 'policy_violation');
|
|
105
|
+
const result = await manager.verifyDIDRevocation(revocation);
|
|
106
|
+
expect(result.valid).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
it('detects tampered DID revocation', async () => {
|
|
109
|
+
const revocation = await manager.revokeDID(keyProvider, admin.keyId, admin.did, agentA.did, 'policy_violation');
|
|
110
|
+
// Tamper: change the reason
|
|
111
|
+
revocation.reason = 'emergency';
|
|
112
|
+
const result = await manager.verifyDIDRevocation(revocation);
|
|
113
|
+
expect(result.valid).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// ─── Key Rotation ─────────────────────────────────────────────────
|
|
117
|
+
describe('key rotation', () => {
|
|
118
|
+
it('rotates keys with dual-signature notice', async () => {
|
|
119
|
+
const newKeyProvider = new InMemoryKeyProvider();
|
|
120
|
+
const newAgent = await makeIdentity(newKeyProvider, 'agentA-v2');
|
|
121
|
+
const notice = await manager.rotateKey(keyProvider, agentA.keyId, agentA.did, newKeyProvider, newAgent.keyId, newAgent.did);
|
|
122
|
+
expect(notice.oldDid).toBe(agentA.did);
|
|
123
|
+
expect(notice.newDid).toBe(newAgent.did);
|
|
124
|
+
expect(notice.oldKeySignature).toBeDefined();
|
|
125
|
+
expect(notice.newKeySignature).toBeDefined();
|
|
126
|
+
});
|
|
127
|
+
it('verifies a valid key rotation', async () => {
|
|
128
|
+
const newKeyProvider = new InMemoryKeyProvider();
|
|
129
|
+
const newAgent = await makeIdentity(newKeyProvider, 'agentA-v2');
|
|
130
|
+
const notice = await manager.rotateKey(keyProvider, agentA.keyId, agentA.did, newKeyProvider, newAgent.keyId, newAgent.did);
|
|
131
|
+
const result = await manager.verifyKeyRotation(notice);
|
|
132
|
+
expect(result.valid).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
it('marks old DID as revoked after rotation', async () => {
|
|
135
|
+
const newKeyProvider = new InMemoryKeyProvider();
|
|
136
|
+
const newAgent = await makeIdentity(newKeyProvider, 'agentA-v2');
|
|
137
|
+
await manager.rotateKey(keyProvider, agentA.keyId, agentA.did, newKeyProvider, newAgent.keyId, newAgent.did);
|
|
138
|
+
expect(manager.isDIDRevoked(agentA.did)).toBe(true);
|
|
139
|
+
expect(manager.isDIDRevoked(newAgent.did)).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
it('resolves current DID through rotation chain', async () => {
|
|
142
|
+
const kp2 = new InMemoryKeyProvider();
|
|
143
|
+
const agent2 = await makeIdentity(kp2, 'v2');
|
|
144
|
+
const kp3 = new InMemoryKeyProvider();
|
|
145
|
+
const agent3 = await makeIdentity(kp3, 'v3');
|
|
146
|
+
// Rotate A → 2, then 2 → 3
|
|
147
|
+
await manager.rotateKey(keyProvider, agentA.keyId, agentA.did, kp2, agent2.keyId, agent2.did);
|
|
148
|
+
await manager.rotateKey(kp2, agent2.keyId, agent2.did, kp3, agent3.keyId, agent3.did);
|
|
149
|
+
// Resolve from original DID should land on v3
|
|
150
|
+
expect(manager.resolveCurrentDid(agentA.did)).toBe(agent3.did);
|
|
151
|
+
expect(manager.resolveCurrentDid(agent2.did)).toBe(agent3.did);
|
|
152
|
+
expect(manager.resolveCurrentDid(agent3.did)).toBe(agent3.did);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
// ─── Kill Switch ──────────────────────────────────────────────────
|
|
156
|
+
describe('kill switch', () => {
|
|
157
|
+
it('revokes target DID immediately', async () => {
|
|
158
|
+
const event = await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentA.did, 'Agent producing harmful output');
|
|
159
|
+
expect(event.targetDid).toBe(agentA.did);
|
|
160
|
+
expect(event.activatedBy).toBe(admin.did);
|
|
161
|
+
expect(manager.isDIDRevoked(agentA.did)).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
it('cascades to downstream agents', async () => {
|
|
164
|
+
const event = await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentA.did, 'Compromised key — cascade to dependents', { cascade: true, downstreamDids: [agentB.did] });
|
|
165
|
+
expect(event.cascade).toBe(true);
|
|
166
|
+
expect(event.cascadedDids).toContain(agentB.did);
|
|
167
|
+
expect(manager.isDIDRevoked(agentA.did)).toBe(true);
|
|
168
|
+
expect(manager.isDIDRevoked(agentB.did)).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
it('verifies kill switch event signature', async () => {
|
|
171
|
+
const event = await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentA.did, 'Test kill');
|
|
172
|
+
const result = await manager.verifyKillSwitch(event);
|
|
173
|
+
expect(result.valid).toBe(true);
|
|
174
|
+
});
|
|
175
|
+
it('detects tampered kill switch event', async () => {
|
|
176
|
+
const event = await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentA.did, 'Test kill');
|
|
177
|
+
// Tamper: change the target
|
|
178
|
+
event.targetDid = agentB.did;
|
|
179
|
+
const result = await manager.verifyKillSwitch(event);
|
|
180
|
+
expect(result.valid).toBe(false);
|
|
181
|
+
});
|
|
182
|
+
it('records kill events in history', async () => {
|
|
183
|
+
await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentA.did, 'Kill 1');
|
|
184
|
+
await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentB.did, 'Kill 2');
|
|
185
|
+
const events = manager.getKillEvents();
|
|
186
|
+
expect(events).toHaveLength(2);
|
|
187
|
+
expect(events[0].reason).toBe('Kill 1');
|
|
188
|
+
expect(events[1].reason).toBe('Kill 2');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
// ─── Comprehensive Trust Check ────────────────────────────────────
|
|
192
|
+
describe('isTrusted', () => {
|
|
193
|
+
it('trusts unrevoked DID + VC', () => {
|
|
194
|
+
const result = manager.isTrusted(agentA.did, 'urn:uuid:valid-vc');
|
|
195
|
+
expect(result.trusted).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
it('rejects revoked DID', async () => {
|
|
198
|
+
await manager.revokeDID(keyProvider, admin.keyId, admin.did, agentA.did, 'emergency');
|
|
199
|
+
const result = manager.isTrusted(agentA.did);
|
|
200
|
+
expect(result.trusted).toBe(false);
|
|
201
|
+
expect(result.reason).toContain('DID revoked');
|
|
202
|
+
});
|
|
203
|
+
it('rejects revoked VC even if DID is fine', async () => {
|
|
204
|
+
const credId = 'urn:uuid:revoked-vc';
|
|
205
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, credId, 'scope_violation');
|
|
206
|
+
const result = manager.isTrusted(agentA.did, credId);
|
|
207
|
+
expect(result.trusted).toBe(false);
|
|
208
|
+
expect(result.reason).toContain('VC revoked');
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
// ─── Stats ─────────────────────────────────────────────────────────
|
|
212
|
+
describe('stats', () => {
|
|
213
|
+
it('reports correct stats', async () => {
|
|
214
|
+
expect(manager.getStats()).toEqual({
|
|
215
|
+
revokedVCs: 0,
|
|
216
|
+
revokedDIDs: 0,
|
|
217
|
+
rotations: 0,
|
|
218
|
+
killEvents: 0,
|
|
219
|
+
});
|
|
220
|
+
await manager.revokeVC(keyProvider, admin.keyId, admin.did, 'urn:uuid:s1', 'manual');
|
|
221
|
+
await manager.revokeDID(keyProvider, admin.keyId, admin.did, agentA.did, 'emergency');
|
|
222
|
+
await manager.killSwitch(keyProvider, admin.keyId, admin.did, agentB.did, 'Test');
|
|
223
|
+
const stats = manager.getStats();
|
|
224
|
+
expect(stats.revokedVCs).toBe(1);
|
|
225
|
+
expect(stats.revokedDIDs).toBeGreaterThanOrEqual(2); // agentA + agentB (from kill)
|
|
226
|
+
expect(stats.killEvents).toBe(1);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
//# sourceMappingURL=revocation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revocation.test.js","sourceRoot":"","sources":["../../src/__tests__/revocation.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sentinel-atl/revocation — DID & VC Revocation, Key Rotation, Kill Switch
|
|
3
|
+
*
|
|
4
|
+
* When things go wrong — compromised keys, rogue agents, policy violations —
|
|
5
|
+
* you need to revoke trust FAST. This module provides:
|
|
6
|
+
*
|
|
7
|
+
* 1. **VC Revocation List (VRL):** Signed list of revoked credential IDs.
|
|
8
|
+
* Any verifier checks the VRL before trusting a VC.
|
|
9
|
+
*
|
|
10
|
+
* 2. **DID Revocation:** Mark an entire agent identity as revoked.
|
|
11
|
+
* All VCs issued by or to that DID become untrusted.
|
|
12
|
+
*
|
|
13
|
+
* 3. **Key Rotation:** Generate a new keypair and publish a signed rotation
|
|
14
|
+
* notice linking old DID → new DID. Verifiers follow the chain.
|
|
15
|
+
*
|
|
16
|
+
* 4. **Emergency Kill Switch:** Immediately revoke an agent + all downstream
|
|
17
|
+
* delegations. Logged to audit with highest priority.
|
|
18
|
+
*
|
|
19
|
+
* All revocation decisions are signed by the revoker to prevent spoofing,
|
|
20
|
+
* and every action is audit-logged.
|
|
21
|
+
*/
|
|
22
|
+
import { type KeyProvider } from '@sentinel-atl/core';
|
|
23
|
+
import { AuditLog } from '@sentinel-atl/audit';
|
|
24
|
+
export interface RevocationEntry {
|
|
25
|
+
/** The revoked VC's ID (urn:uuid:...) */
|
|
26
|
+
credentialId: string;
|
|
27
|
+
/** When it was revoked */
|
|
28
|
+
revokedAt: string;
|
|
29
|
+
/** Why it was revoked */
|
|
30
|
+
reason: RevocationReason;
|
|
31
|
+
/** Optional human-readable explanation */
|
|
32
|
+
details?: string;
|
|
33
|
+
}
|
|
34
|
+
export type RevocationReason = 'key_compromise' | 'credential_expired_early' | 'policy_violation' | 'scope_violation' | 'agent_decommissioned' | 'emergency' | 'key_rotation' | 'manual';
|
|
35
|
+
export interface SignedRevocationList {
|
|
36
|
+
/** List version — monotonically increasing */
|
|
37
|
+
version: number;
|
|
38
|
+
/** DID of the entity that published this list */
|
|
39
|
+
issuerDid: string;
|
|
40
|
+
/** When this list was published */
|
|
41
|
+
publishedAt: string;
|
|
42
|
+
/** Revoked credentials */
|
|
43
|
+
entries: RevocationEntry[];
|
|
44
|
+
/** Ed25519 signature over the canonical list (base64url) */
|
|
45
|
+
signature: string;
|
|
46
|
+
}
|
|
47
|
+
export interface DIDRevocation {
|
|
48
|
+
/** The revoked DID */
|
|
49
|
+
did: string;
|
|
50
|
+
/** Who revoked it */
|
|
51
|
+
revokedBy: string;
|
|
52
|
+
/** When */
|
|
53
|
+
revokedAt: string;
|
|
54
|
+
/** Why */
|
|
55
|
+
reason: RevocationReason;
|
|
56
|
+
details?: string;
|
|
57
|
+
/** Signature by the revoker (base64url) */
|
|
58
|
+
signature: string;
|
|
59
|
+
}
|
|
60
|
+
export interface KeyRotationNotice {
|
|
61
|
+
/** The old DID being rotated away from */
|
|
62
|
+
oldDid: string;
|
|
63
|
+
/** The new DID to use going forward */
|
|
64
|
+
newDid: string;
|
|
65
|
+
/** When the rotation happened */
|
|
66
|
+
rotatedAt: string;
|
|
67
|
+
/** Signature by the OLD key (proves control) */
|
|
68
|
+
oldKeySignature: string;
|
|
69
|
+
/** Signature by the NEW key (proves ownership) */
|
|
70
|
+
newKeySignature: string;
|
|
71
|
+
}
|
|
72
|
+
export interface KillSwitchEvent {
|
|
73
|
+
/** The agent DID being killed */
|
|
74
|
+
targetDid: string;
|
|
75
|
+
/** Who activated the kill switch */
|
|
76
|
+
activatedBy: string;
|
|
77
|
+
/** When */
|
|
78
|
+
activatedAt: string;
|
|
79
|
+
/** Why */
|
|
80
|
+
reason: string;
|
|
81
|
+
/** Whether to cascade to all downstream delegations */
|
|
82
|
+
cascade: boolean;
|
|
83
|
+
/** DIDs of downstream agents also revoked (if cascade=true) */
|
|
84
|
+
cascadedDids: string[];
|
|
85
|
+
/** Signature by the activator (base64url) */
|
|
86
|
+
signature: string;
|
|
87
|
+
}
|
|
88
|
+
export declare class RevocationManager {
|
|
89
|
+
private revokedVCs;
|
|
90
|
+
private revokedDIDs;
|
|
91
|
+
private rotations;
|
|
92
|
+
private killEvents;
|
|
93
|
+
private listVersion;
|
|
94
|
+
private auditLog?;
|
|
95
|
+
constructor(auditLog?: AuditLog);
|
|
96
|
+
/**
|
|
97
|
+
* Revoke a Verifiable Credential.
|
|
98
|
+
* The revoker signs the revocation entry to prevent spoofing.
|
|
99
|
+
*/
|
|
100
|
+
revokeVC(keyProvider: KeyProvider, revokerKeyId: string, revokerDid: string, credentialId: string, reason: RevocationReason, details?: string): Promise<RevocationEntry>;
|
|
101
|
+
/**
|
|
102
|
+
* Check if a VC is revoked.
|
|
103
|
+
*/
|
|
104
|
+
isVCRevoked(credentialId: string): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Get the revocation entry for a VC (if revoked).
|
|
107
|
+
*/
|
|
108
|
+
getVCRevocation(credentialId: string): RevocationEntry | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Publish a signed revocation list.
|
|
111
|
+
*/
|
|
112
|
+
publishRevocationList(keyProvider: KeyProvider, issuerKeyId: string, issuerDid: string): Promise<SignedRevocationList>;
|
|
113
|
+
/**
|
|
114
|
+
* Verify a signed revocation list.
|
|
115
|
+
*/
|
|
116
|
+
verifyRevocationList(list: SignedRevocationList): Promise<{
|
|
117
|
+
valid: boolean;
|
|
118
|
+
error?: string;
|
|
119
|
+
}>;
|
|
120
|
+
/**
|
|
121
|
+
* Import a verified revocation list (merge entries).
|
|
122
|
+
*/
|
|
123
|
+
importRevocationList(list: SignedRevocationList): number;
|
|
124
|
+
/**
|
|
125
|
+
* Revoke a DID. Signs the revocation with the revoker's key.
|
|
126
|
+
*/
|
|
127
|
+
revokeDID(keyProvider: KeyProvider, revokerKeyId: string, revokerDid: string, targetDid: string, reason: RevocationReason, details?: string): Promise<DIDRevocation>;
|
|
128
|
+
/**
|
|
129
|
+
* Check if a DID is revoked.
|
|
130
|
+
*/
|
|
131
|
+
isDIDRevoked(did: string): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Verify a DID revocation notice.
|
|
134
|
+
*/
|
|
135
|
+
verifyDIDRevocation(revocation: DIDRevocation): Promise<{
|
|
136
|
+
valid: boolean;
|
|
137
|
+
error?: string;
|
|
138
|
+
}>;
|
|
139
|
+
/**
|
|
140
|
+
* Rotate an agent's key. Both old and new keys sign the rotation notice.
|
|
141
|
+
* This proves: "I own the old key AND the new key, and I'm switching."
|
|
142
|
+
*/
|
|
143
|
+
rotateKey(oldKeyProvider: KeyProvider, oldKeyId: string, oldDid: string, newKeyProvider: KeyProvider, newKeyId: string, newDid: string): Promise<KeyRotationNotice>;
|
|
144
|
+
/**
|
|
145
|
+
* Verify a key rotation notice (both signatures must be valid).
|
|
146
|
+
*/
|
|
147
|
+
verifyKeyRotation(notice: KeyRotationNotice): Promise<{
|
|
148
|
+
valid: boolean;
|
|
149
|
+
error?: string;
|
|
150
|
+
}>;
|
|
151
|
+
/**
|
|
152
|
+
* Resolve the current DID for an agent (follows rotation chain).
|
|
153
|
+
*/
|
|
154
|
+
resolveCurrentDid(did: string): string;
|
|
155
|
+
/**
|
|
156
|
+
* Emergency kill switch — immediately revoke an agent and optionally
|
|
157
|
+
* cascade to all downstream delegations.
|
|
158
|
+
*
|
|
159
|
+
* This is the "big red button." Use when an agent is:
|
|
160
|
+
* - Compromised
|
|
161
|
+
* - Producing harmful output
|
|
162
|
+
* - Violating scope
|
|
163
|
+
* - Otherwise untrustworthy
|
|
164
|
+
*/
|
|
165
|
+
killSwitch(keyProvider: KeyProvider, activatorKeyId: string, activatorDid: string, targetDid: string, reason: string, options?: {
|
|
166
|
+
cascade?: boolean;
|
|
167
|
+
downstreamDids?: string[];
|
|
168
|
+
}): Promise<KillSwitchEvent>;
|
|
169
|
+
/**
|
|
170
|
+
* Verify a kill switch event signature.
|
|
171
|
+
*/
|
|
172
|
+
verifyKillSwitch(event: KillSwitchEvent): Promise<{
|
|
173
|
+
valid: boolean;
|
|
174
|
+
error?: string;
|
|
175
|
+
}>;
|
|
176
|
+
/**
|
|
177
|
+
* Get all kill switch events.
|
|
178
|
+
*/
|
|
179
|
+
getKillEvents(): KillSwitchEvent[];
|
|
180
|
+
/**
|
|
181
|
+
* Full trust check: is this DID + credential ID currently trusted?
|
|
182
|
+
*
|
|
183
|
+
* Returns false if the DID is revoked, the VC is revoked,
|
|
184
|
+
* or the agent has been killed.
|
|
185
|
+
*/
|
|
186
|
+
isTrusted(did: string, credentialId?: string): {
|
|
187
|
+
trusted: boolean;
|
|
188
|
+
reason?: string;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Get summary stats.
|
|
192
|
+
*/
|
|
193
|
+
getStats(): {
|
|
194
|
+
revokedVCs: number;
|
|
195
|
+
revokedDIDs: number;
|
|
196
|
+
rotations: number;
|
|
197
|
+
killEvents: number;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sentinel-atl/revocation — DID & VC Revocation, Key Rotation, Kill Switch
|
|
3
|
+
*
|
|
4
|
+
* When things go wrong — compromised keys, rogue agents, policy violations —
|
|
5
|
+
* you need to revoke trust FAST. This module provides:
|
|
6
|
+
*
|
|
7
|
+
* 1. **VC Revocation List (VRL):** Signed list of revoked credential IDs.
|
|
8
|
+
* Any verifier checks the VRL before trusting a VC.
|
|
9
|
+
*
|
|
10
|
+
* 2. **DID Revocation:** Mark an entire agent identity as revoked.
|
|
11
|
+
* All VCs issued by or to that DID become untrusted.
|
|
12
|
+
*
|
|
13
|
+
* 3. **Key Rotation:** Generate a new keypair and publish a signed rotation
|
|
14
|
+
* notice linking old DID → new DID. Verifiers follow the chain.
|
|
15
|
+
*
|
|
16
|
+
* 4. **Emergency Kill Switch:** Immediately revoke an agent + all downstream
|
|
17
|
+
* delegations. Logged to audit with highest priority.
|
|
18
|
+
*
|
|
19
|
+
* All revocation decisions are signed by the revoker to prevent spoofing,
|
|
20
|
+
* and every action is audit-logged.
|
|
21
|
+
*/
|
|
22
|
+
import { toBase64Url, fromBase64Url, textToBytes, verify, didToPublicKey, } from '@sentinel-atl/core';
|
|
23
|
+
// ─── Canonicalization ────────────────────────────────────────────────
|
|
24
|
+
function sortDeep(value) {
|
|
25
|
+
if (Array.isArray(value))
|
|
26
|
+
return value.map(sortDeep);
|
|
27
|
+
if (value !== null && typeof value === 'object') {
|
|
28
|
+
const sorted = {};
|
|
29
|
+
for (const key of Object.keys(value).sort()) {
|
|
30
|
+
sorted[key] = sortDeep(value[key]);
|
|
31
|
+
}
|
|
32
|
+
return sorted;
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
function canonicalize(obj) {
|
|
37
|
+
return textToBytes(JSON.stringify(sortDeep(obj)));
|
|
38
|
+
}
|
|
39
|
+
// ─── Revocation Manager ─────────────────────────────────────────────
|
|
40
|
+
export class RevocationManager {
|
|
41
|
+
revokedVCs = new Map();
|
|
42
|
+
revokedDIDs = new Map();
|
|
43
|
+
rotations = new Map();
|
|
44
|
+
killEvents = [];
|
|
45
|
+
listVersion = 0;
|
|
46
|
+
auditLog;
|
|
47
|
+
constructor(auditLog) {
|
|
48
|
+
this.auditLog = auditLog;
|
|
49
|
+
}
|
|
50
|
+
// ─── VC Revocation ───────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Revoke a Verifiable Credential.
|
|
53
|
+
* The revoker signs the revocation entry to prevent spoofing.
|
|
54
|
+
*/
|
|
55
|
+
async revokeVC(keyProvider, revokerKeyId, revokerDid, credentialId, reason, details) {
|
|
56
|
+
const entry = {
|
|
57
|
+
credentialId,
|
|
58
|
+
revokedAt: new Date().toISOString(),
|
|
59
|
+
reason,
|
|
60
|
+
details,
|
|
61
|
+
};
|
|
62
|
+
this.revokedVCs.set(credentialId, entry);
|
|
63
|
+
await this.auditLog?.log({
|
|
64
|
+
eventType: 'vc_revoked',
|
|
65
|
+
actorDid: revokerDid,
|
|
66
|
+
result: 'success',
|
|
67
|
+
metadata: { credentialId, reason },
|
|
68
|
+
});
|
|
69
|
+
return entry;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if a VC is revoked.
|
|
73
|
+
*/
|
|
74
|
+
isVCRevoked(credentialId) {
|
|
75
|
+
return this.revokedVCs.has(credentialId);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the revocation entry for a VC (if revoked).
|
|
79
|
+
*/
|
|
80
|
+
getVCRevocation(credentialId) {
|
|
81
|
+
return this.revokedVCs.get(credentialId);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Publish a signed revocation list.
|
|
85
|
+
*/
|
|
86
|
+
async publishRevocationList(keyProvider, issuerKeyId, issuerDid) {
|
|
87
|
+
this.listVersion++;
|
|
88
|
+
const listBody = {
|
|
89
|
+
version: this.listVersion,
|
|
90
|
+
issuerDid,
|
|
91
|
+
publishedAt: new Date().toISOString(),
|
|
92
|
+
entries: Array.from(this.revokedVCs.values()),
|
|
93
|
+
};
|
|
94
|
+
const dataToSign = canonicalize(listBody);
|
|
95
|
+
const sig = await keyProvider.sign(issuerKeyId, dataToSign);
|
|
96
|
+
return {
|
|
97
|
+
...listBody,
|
|
98
|
+
signature: toBase64Url(sig),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Verify a signed revocation list.
|
|
103
|
+
*/
|
|
104
|
+
async verifyRevocationList(list) {
|
|
105
|
+
try {
|
|
106
|
+
const publicKey = didToPublicKey(list.issuerDid);
|
|
107
|
+
const { signature, ...body } = list;
|
|
108
|
+
const dataToVerify = canonicalize(body);
|
|
109
|
+
const sig = fromBase64Url(signature);
|
|
110
|
+
const valid = await verify(sig, dataToVerify, publicKey);
|
|
111
|
+
return valid ? { valid: true } : { valid: false, error: 'Invalid signature on revocation list' };
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
return { valid: false, error: `Verification failed: ${e.message}` };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Import a verified revocation list (merge entries).
|
|
119
|
+
*/
|
|
120
|
+
importRevocationList(list) {
|
|
121
|
+
let imported = 0;
|
|
122
|
+
for (const entry of list.entries) {
|
|
123
|
+
if (!this.revokedVCs.has(entry.credentialId)) {
|
|
124
|
+
this.revokedVCs.set(entry.credentialId, entry);
|
|
125
|
+
imported++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return imported;
|
|
129
|
+
}
|
|
130
|
+
// ─── DID Revocation ──────────────────────────────────────────────
|
|
131
|
+
/**
|
|
132
|
+
* Revoke a DID. Signs the revocation with the revoker's key.
|
|
133
|
+
*/
|
|
134
|
+
async revokeDID(keyProvider, revokerKeyId, revokerDid, targetDid, reason, details) {
|
|
135
|
+
const body = {
|
|
136
|
+
did: targetDid,
|
|
137
|
+
revokedBy: revokerDid,
|
|
138
|
+
revokedAt: new Date().toISOString(),
|
|
139
|
+
reason,
|
|
140
|
+
details,
|
|
141
|
+
};
|
|
142
|
+
const dataToSign = canonicalize(body);
|
|
143
|
+
const sig = await keyProvider.sign(revokerKeyId, dataToSign);
|
|
144
|
+
const revocation = {
|
|
145
|
+
...body,
|
|
146
|
+
signature: toBase64Url(sig),
|
|
147
|
+
};
|
|
148
|
+
this.revokedDIDs.set(targetDid, revocation);
|
|
149
|
+
await this.auditLog?.log({
|
|
150
|
+
eventType: 'emergency_revoke',
|
|
151
|
+
actorDid: revokerDid,
|
|
152
|
+
targetDid,
|
|
153
|
+
result: 'success',
|
|
154
|
+
metadata: { reason, type: 'did_revocation' },
|
|
155
|
+
});
|
|
156
|
+
return revocation;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if a DID is revoked.
|
|
160
|
+
*/
|
|
161
|
+
isDIDRevoked(did) {
|
|
162
|
+
return this.revokedDIDs.has(did);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Verify a DID revocation notice.
|
|
166
|
+
*/
|
|
167
|
+
async verifyDIDRevocation(revocation) {
|
|
168
|
+
try {
|
|
169
|
+
const publicKey = didToPublicKey(revocation.revokedBy);
|
|
170
|
+
const { signature, ...body } = revocation;
|
|
171
|
+
const dataToVerify = canonicalize(body);
|
|
172
|
+
const sig = fromBase64Url(signature);
|
|
173
|
+
const valid = await verify(sig, dataToVerify, publicKey);
|
|
174
|
+
return valid ? { valid: true } : { valid: false, error: 'Invalid signature on DID revocation' };
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
return { valid: false, error: `Verification failed: ${e.message}` };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// ─── Key Rotation ────────────────────────────────────────────────
|
|
181
|
+
/**
|
|
182
|
+
* Rotate an agent's key. Both old and new keys sign the rotation notice.
|
|
183
|
+
* This proves: "I own the old key AND the new key, and I'm switching."
|
|
184
|
+
*/
|
|
185
|
+
async rotateKey(oldKeyProvider, oldKeyId, oldDid, newKeyProvider, newKeyId, newDid) {
|
|
186
|
+
const rotatedAt = new Date().toISOString();
|
|
187
|
+
const rotationData = textToBytes(`key-rotation:${oldDid}:${newDid}:${rotatedAt}`);
|
|
188
|
+
const oldSig = await oldKeyProvider.sign(oldKeyId, rotationData);
|
|
189
|
+
const newSig = await newKeyProvider.sign(newKeyId, rotationData);
|
|
190
|
+
const notice = {
|
|
191
|
+
oldDid,
|
|
192
|
+
newDid,
|
|
193
|
+
rotatedAt,
|
|
194
|
+
oldKeySignature: toBase64Url(oldSig),
|
|
195
|
+
newKeySignature: toBase64Url(newSig),
|
|
196
|
+
};
|
|
197
|
+
this.rotations.set(oldDid, notice);
|
|
198
|
+
// Also revoke the old DID
|
|
199
|
+
this.revokedDIDs.set(oldDid, {
|
|
200
|
+
did: oldDid,
|
|
201
|
+
revokedBy: oldDid,
|
|
202
|
+
revokedAt: notice.rotatedAt,
|
|
203
|
+
reason: 'key_rotation',
|
|
204
|
+
details: `Rotated to ${newDid}`,
|
|
205
|
+
signature: notice.oldKeySignature,
|
|
206
|
+
});
|
|
207
|
+
await this.auditLog?.log({
|
|
208
|
+
eventType: 'key_rotated',
|
|
209
|
+
actorDid: oldDid,
|
|
210
|
+
targetDid: newDid,
|
|
211
|
+
result: 'success',
|
|
212
|
+
metadata: { type: 'key_rotation' },
|
|
213
|
+
});
|
|
214
|
+
return notice;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Verify a key rotation notice (both signatures must be valid).
|
|
218
|
+
*/
|
|
219
|
+
async verifyKeyRotation(notice) {
|
|
220
|
+
try {
|
|
221
|
+
const rotationData = textToBytes(`key-rotation:${notice.oldDid}:${notice.newDid}:${notice.rotatedAt}`);
|
|
222
|
+
const oldPubKey = didToPublicKey(notice.oldDid);
|
|
223
|
+
const newPubKey = didToPublicKey(notice.newDid);
|
|
224
|
+
const oldSig = fromBase64Url(notice.oldKeySignature);
|
|
225
|
+
const newSig = fromBase64Url(notice.newKeySignature);
|
|
226
|
+
const oldValid = await verify(oldSig, rotationData, oldPubKey);
|
|
227
|
+
if (!oldValid)
|
|
228
|
+
return { valid: false, error: 'Old key signature invalid' };
|
|
229
|
+
const newValid = await verify(newSig, rotationData, newPubKey);
|
|
230
|
+
if (!newValid)
|
|
231
|
+
return { valid: false, error: 'New key signature invalid' };
|
|
232
|
+
return { valid: true };
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
return { valid: false, error: `Verification failed: ${e.message}` };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Resolve the current DID for an agent (follows rotation chain).
|
|
240
|
+
*/
|
|
241
|
+
resolveCurrentDid(did) {
|
|
242
|
+
let current = did;
|
|
243
|
+
const seen = new Set();
|
|
244
|
+
while (this.rotations.has(current)) {
|
|
245
|
+
if (seen.has(current))
|
|
246
|
+
break; // Prevent cycles
|
|
247
|
+
seen.add(current);
|
|
248
|
+
current = this.rotations.get(current).newDid;
|
|
249
|
+
}
|
|
250
|
+
return current;
|
|
251
|
+
}
|
|
252
|
+
// ─── Kill Switch ─────────────────────────────────────────────────
|
|
253
|
+
/**
|
|
254
|
+
* Emergency kill switch — immediately revoke an agent and optionally
|
|
255
|
+
* cascade to all downstream delegations.
|
|
256
|
+
*
|
|
257
|
+
* This is the "big red button." Use when an agent is:
|
|
258
|
+
* - Compromised
|
|
259
|
+
* - Producing harmful output
|
|
260
|
+
* - Violating scope
|
|
261
|
+
* - Otherwise untrustworthy
|
|
262
|
+
*/
|
|
263
|
+
async killSwitch(keyProvider, activatorKeyId, activatorDid, targetDid, reason, options = {}) {
|
|
264
|
+
const cascade = options.cascade ?? false;
|
|
265
|
+
const cascadedDids = options.downstreamDids ?? [];
|
|
266
|
+
const body = {
|
|
267
|
+
targetDid,
|
|
268
|
+
activatedBy: activatorDid,
|
|
269
|
+
activatedAt: new Date().toISOString(),
|
|
270
|
+
reason,
|
|
271
|
+
cascade,
|
|
272
|
+
cascadedDids,
|
|
273
|
+
};
|
|
274
|
+
const dataToSign = canonicalize(body);
|
|
275
|
+
const sig = await keyProvider.sign(activatorKeyId, dataToSign);
|
|
276
|
+
const event = {
|
|
277
|
+
...body,
|
|
278
|
+
signature: toBase64Url(sig),
|
|
279
|
+
};
|
|
280
|
+
this.killEvents.push(event);
|
|
281
|
+
// Revoke the target DID
|
|
282
|
+
this.revokedDIDs.set(targetDid, {
|
|
283
|
+
did: targetDid,
|
|
284
|
+
revokedBy: activatorDid,
|
|
285
|
+
revokedAt: event.activatedAt,
|
|
286
|
+
reason: 'emergency',
|
|
287
|
+
details: reason,
|
|
288
|
+
signature: event.signature,
|
|
289
|
+
});
|
|
290
|
+
// Cascade if requested
|
|
291
|
+
if (cascade) {
|
|
292
|
+
for (const downstream of cascadedDids) {
|
|
293
|
+
this.revokedDIDs.set(downstream, {
|
|
294
|
+
did: downstream,
|
|
295
|
+
revokedBy: activatorDid,
|
|
296
|
+
revokedAt: event.activatedAt,
|
|
297
|
+
reason: 'emergency',
|
|
298
|
+
details: `Cascaded from kill switch on ${targetDid}: ${reason}`,
|
|
299
|
+
signature: event.signature,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
await this.auditLog?.log({
|
|
304
|
+
eventType: 'emergency_revoke',
|
|
305
|
+
actorDid: activatorDid,
|
|
306
|
+
targetDid,
|
|
307
|
+
result: 'success',
|
|
308
|
+
metadata: {
|
|
309
|
+
type: 'kill_switch',
|
|
310
|
+
reason,
|
|
311
|
+
cascade,
|
|
312
|
+
cascadedCount: cascadedDids.length,
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
return event;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Verify a kill switch event signature.
|
|
319
|
+
*/
|
|
320
|
+
async verifyKillSwitch(event) {
|
|
321
|
+
try {
|
|
322
|
+
const publicKey = didToPublicKey(event.activatedBy);
|
|
323
|
+
const { signature, ...body } = event;
|
|
324
|
+
const dataToVerify = canonicalize(body);
|
|
325
|
+
const sig = fromBase64Url(signature);
|
|
326
|
+
const valid = await verify(sig, dataToVerify, publicKey);
|
|
327
|
+
return valid ? { valid: true } : { valid: false, error: 'Invalid kill switch signature' };
|
|
328
|
+
}
|
|
329
|
+
catch (e) {
|
|
330
|
+
return { valid: false, error: `Verification failed: ${e.message}` };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Get all kill switch events.
|
|
335
|
+
*/
|
|
336
|
+
getKillEvents() {
|
|
337
|
+
return [...this.killEvents];
|
|
338
|
+
}
|
|
339
|
+
// ─── Comprehensive Trust Check ───────────────────────────────────
|
|
340
|
+
/**
|
|
341
|
+
* Full trust check: is this DID + credential ID currently trusted?
|
|
342
|
+
*
|
|
343
|
+
* Returns false if the DID is revoked, the VC is revoked,
|
|
344
|
+
* or the agent has been killed.
|
|
345
|
+
*/
|
|
346
|
+
isTrusted(did, credentialId) {
|
|
347
|
+
// Check DID revocation
|
|
348
|
+
if (this.revokedDIDs.has(did)) {
|
|
349
|
+
const rev = this.revokedDIDs.get(did);
|
|
350
|
+
return { trusted: false, reason: `DID revoked: ${rev.reason}` };
|
|
351
|
+
}
|
|
352
|
+
// Check VC revocation
|
|
353
|
+
if (credentialId && this.revokedVCs.has(credentialId)) {
|
|
354
|
+
const rev = this.revokedVCs.get(credentialId);
|
|
355
|
+
return { trusted: false, reason: `VC revoked: ${rev.reason}` };
|
|
356
|
+
}
|
|
357
|
+
return { trusted: true };
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Get summary stats.
|
|
361
|
+
*/
|
|
362
|
+
getStats() {
|
|
363
|
+
return {
|
|
364
|
+
revokedVCs: this.revokedVCs.size,
|
|
365
|
+
revokedDIDs: this.revokedDIDs.size,
|
|
366
|
+
rotations: this.rotations.size,
|
|
367
|
+
killEvents: this.killEvents.length,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sentinel-atl/revocation",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "DID and VC revocation, key rotation, and emergency kill switch for the Agent Trust Layer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"lint": "tsc --noEmit",
|
|
18
|
+
"clean": "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@sentinel-atl/core": "*",
|
|
22
|
+
"@sentinel-atl/audit": "*"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.7.0",
|
|
26
|
+
"vitest": "^3.0.0",
|
|
27
|
+
"@types/node": "^20.0.0"
|
|
28
|
+
},
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/sentinel-atl/project-sentinel.git",
|
|
33
|
+
"directory": "packages/revocation"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"ai-agent",
|
|
37
|
+
"trust",
|
|
38
|
+
"identity",
|
|
39
|
+
"did",
|
|
40
|
+
"verifiable-credentials",
|
|
41
|
+
"mcp",
|
|
42
|
+
"security"
|
|
43
|
+
],
|
|
44
|
+
"homepage": "https://github.com/sentinel-atl/project-sentinel#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/sentinel-atl/project-sentinel/issues"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist",
|
|
50
|
+
"README.md"
|
|
51
|
+
]
|
|
52
|
+
}
|