@adastracomputing/ink 0.1.0-alpha.0

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 (48) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/CODE_OF_CONDUCT.md +42 -0
  3. package/LICENSE-APACHE +201 -0
  4. package/LICENSE-MIT +21 -0
  5. package/README.md +133 -0
  6. package/SECURITY.md +57 -0
  7. package/docs/key-rotation-rule.md +108 -0
  8. package/docs/logo.svg +8 -0
  9. package/docs/maturity.md +81 -0
  10. package/docs/threat-model.md +150 -0
  11. package/package.json +72 -0
  12. package/specs/ink-agent-containment-and-governance-extension-spec.md +508 -0
  13. package/specs/ink-auditability.md +652 -0
  14. package/specs/ink-authorization-chain.md +242 -0
  15. package/specs/ink-compatibility-policy.md +263 -0
  16. package/specs/ink-compliance-checklist.md +309 -0
  17. package/specs/ink-containment-phase1-implementation-spec.md +593 -0
  18. package/specs/ink-introduction-receipts-extension.md +501 -0
  19. package/specs/ink-key-rotation-spec.md +535 -0
  20. package/src/crypto/ink.ts +902 -0
  21. package/src/crypto/keys.ts +211 -0
  22. package/src/crypto/multi-key-verify.ts +170 -0
  23. package/src/crypto/sign.ts +155 -0
  24. package/src/crypto/verify.ts +1 -0
  25. package/src/discovery/agent-card.ts +508 -0
  26. package/src/index.ts +59 -0
  27. package/src/ink/checkpoint.ts +75 -0
  28. package/src/ink/discovery-gating.ts +147 -0
  29. package/src/ink/handshake-budget.ts +413 -0
  30. package/src/ink/receipts.ts +114 -0
  31. package/src/ink/transport-auth.ts +96 -0
  32. package/src/middleware/ink-auth.ts +263 -0
  33. package/src/models/agent-card.ts +63 -0
  34. package/src/models/ink-audit.ts +205 -0
  35. package/src/models/ink-handshake.ts +123 -0
  36. package/src/models/intent.ts +201 -0
  37. package/src/models/key-entry.ts +52 -0
  38. package/src/models/profile.ts +31 -0
  39. package/test-vectors/README.md +129 -0
  40. package/test-vectors/encryption.json +90 -0
  41. package/test-vectors/handshake.json +482 -0
  42. package/test-vectors/jcs.json +30 -0
  43. package/test-vectors/key-rotation.json +101 -0
  44. package/test-vectors/keys.json +32 -0
  45. package/test-vectors/receipts-and-audit.json +142 -0
  46. package/test-vectors/replay.json +88 -0
  47. package/test-vectors/signing.json +61 -0
  48. package/test-vectors/witness.json +394 -0
@@ -0,0 +1,535 @@
1
+ # INK Key Rotation Specification v0.1
2
+
3
+ ## Status
4
+ Draft
5
+
6
+ ## Purpose
7
+
8
+ This specification defines how INK agents rotate signing and encryption keys without breaking:
9
+ - active message exchange
10
+ - historical verification
11
+ - witness verification
12
+ - counterparty discovery
13
+
14
+ Core principle:
15
+
16
+ **An INK agent's identity must remain stable across key changes, while its active and historical keys remain verifiable.**
17
+
18
+ ---
19
+
20
+ ## 1. Problem
21
+
22
+ Today Tulpa implementations derive `agentId` from the signing public key.
23
+
24
+ That creates a protocol problem:
25
+ - rotating the signing key changes the apparent agent identity
26
+ - counterparties cannot safely distinguish key rotation from impersonation
27
+ - old receipts, audit events, and witness records still need verification
28
+
29
+ Therefore key rotation MUST be handled as a protocol concern, not a local storage concern.
30
+
31
+ ---
32
+
33
+ ## 2. Goals
34
+
35
+ INK key rotation SHALL:
36
+ - preserve a stable logical agent identity
37
+ - allow new transport/auth signatures to verify under a new key
38
+ - preserve verification of historical artifacts signed by prior keys
39
+ - let counterparties discover key changes safely
40
+ - support overlap, retirement, and emergency revocation
41
+
42
+ INK key rotation SHALL NOT:
43
+ - require breaking message history
44
+ - require rewriting old receipts or audit events
45
+ - rely on out-of-band manual key distribution
46
+
47
+ ---
48
+
49
+ ## 3. Non-Goals
50
+
51
+ This spec does not define:
52
+ - human DID key rotation for ATP itself
53
+ - extension delegation token rotation
54
+ - witness service key rotation beyond discovery advertisement
55
+
56
+ Those may reuse the same patterns later, but are not required here.
57
+
58
+ ---
59
+
60
+ ## 4. Identity Model
61
+
62
+ ## 4.1 Stable Agent Identity
63
+
64
+ INK v1 SHALL treat `agentId` as a stable logical identifier, not as a direct encoding of the current signing key.
65
+
66
+ `agentId` MUST remain stable across key rotation.
67
+
68
+ ## 4.2 Key Material
69
+
70
+ Each agent SHALL advertise one or more keys by role:
71
+ - signing keys
72
+ - encryption keys
73
+
74
+ Each key SHALL have:
75
+ - a stable `keyId`
76
+ - an algorithm
77
+ - a public key
78
+ - a lifecycle status
79
+ - validity timestamps
80
+
81
+ ---
82
+
83
+ ## 5. Agent Card Additions
84
+
85
+ ## 5.1 Key Set Advertisement
86
+
87
+ The Agent Card SHALL advertise key sets explicitly.
88
+
89
+ Recommended shape:
90
+
91
+ ```json
92
+ {
93
+ "agentId": "did:plc:alice#agent/tulpa-main",
94
+ "protocol": "ink/0.1",
95
+ "keys": {
96
+ "signing": [
97
+ {
98
+ "keyId": "sig-2026-03",
99
+ "algorithm": "Ed25519",
100
+ "publicKeyMultibase": "z...",
101
+ "status": "active",
102
+ "validFrom": "2026-03-25T00:00:00Z"
103
+ },
104
+ {
105
+ "keyId": "sig-2025-11",
106
+ "algorithm": "Ed25519",
107
+ "publicKeyMultibase": "z...",
108
+ "status": "retired",
109
+ "validFrom": "2025-11-01T00:00:00Z",
110
+ "validUntil": "2026-04-01T00:00:00Z"
111
+ }
112
+ ],
113
+ "encryption": [
114
+ {
115
+ "keyId": "enc-2026-03",
116
+ "algorithm": "X25519",
117
+ "publicKeyMultibase": "z...",
118
+ "status": "active",
119
+ "validFrom": "2026-03-25T00:00:00Z"
120
+ }
121
+ ]
122
+ },
123
+ "currentSigningKeyId": "sig-2026-03",
124
+ "currentEncryptionKeyId": "enc-2026-03",
125
+ "keySetVersion": 7,
126
+ "updatedAt": "2026-03-25T00:00:00Z"
127
+ }
128
+ ```
129
+
130
+ ## 5.2 Required Fields
131
+
132
+ Each key entry MUST include:
133
+ - `keyId`
134
+ - `algorithm`
135
+ - `publicKeyMultibase`
136
+ - `status`
137
+ - `validFrom`
138
+
139
+ Optional but recommended:
140
+ - `validUntil`
141
+ - `revokedAt`
142
+ - `revokeReason`
143
+
144
+ ## 5.3 Status Values
145
+
146
+ Allowed statuses:
147
+ - `active`
148
+ - `retired`
149
+ - `revoked`
150
+
151
+ Meaning:
152
+ - `active`: valid for new outbound messages and inbound verification
153
+ - `retired`: not used for new outbound messages, but still valid for historical verification
154
+ - `revoked`: no longer trusted for new signatures after `revokedAt`
155
+
156
+ ---
157
+
158
+ ## 6. Signing Verification Rules
159
+
160
+ ## 6.1 Current Messages
161
+
162
+ For current inbound messages, receivers MUST:
163
+ - resolve the sender's Agent Card
164
+ - attempt verification against active signing keys first
165
+
166
+ ## 6.2 Historical Verification
167
+
168
+ For receipts, audit events, witness submissions, and previously stored messages, receivers MUST:
169
+ - permit verification against retired keys if the artifact timestamp falls within that key's validity window
170
+
171
+ ## 6.3 Revoked Keys
172
+
173
+ Receivers MUST NOT verify signatures with a revoked key, even for artifacts whose timestamp predates `revokedAt`. Revocation is a trust statement: the key is compromised or must not be trusted, and pre-revocation artifacts cannot be distinguished from forgeries made after compromise.
174
+
175
+ This is the normative rule, see [`docs/key-rotation-rule.md`](../docs/key-rotation-rule.md). Retired is the correct status for keys that should remain verifiable for historical traffic.
176
+
177
+ ## 6.4 Verification Order
178
+
179
+ Recommended verification order:
180
+ 1. current active key by `currentSigningKeyId`
181
+ 2. other active signing keys
182
+ 3. retired signing keys
183
+ 4. reject if no valid candidate verifies
184
+
185
+ ---
186
+
187
+ ## 7. Encryption Verification Rules
188
+
189
+ ## 7.1 New Messages
190
+
191
+ Senders MUST encrypt to the recipient's current active encryption key.
192
+
193
+ ## 7.2 Overlap Window
194
+
195
+ During rotation overlap, receivers SHOULD support decryption with:
196
+ - current active encryption key
197
+ - immediately previous retired encryption key
198
+
199
+ This allows delivery continuity during cache lag.
200
+
201
+ ## 7.3 Retirement
202
+
203
+ An encryption key SHOULD NOT move to `revoked` until counterparties have had a documented overlap period to refresh the Agent Card.
204
+
205
+ Recommended minimum overlap:
206
+ - 7 days for planned rotation
207
+
208
+ Emergency revocation MAY be immediate.
209
+
210
+ ---
211
+
212
+ ## 8. Rotation Flow
213
+
214
+ ## 8.1 Planned Rotation
215
+
216
+ Recommended planned rotation flow:
217
+
218
+ 1. Generate new keypair(s)
219
+ 2. Publish updated Agent Card with:
220
+ - new key(s) marked `active`
221
+ - previous current key(s) marked `retired`
222
+ - incremented `keySetVersion`
223
+ 3. Start signing new outbound messages with the new signing key
224
+ 4. Start encrypting to the new encryption key
225
+ 5. Accept verification/decryption with prior keys during overlap
226
+ 6. After overlap, leave prior signing keys `retired` for historical verification
227
+ 7. Revoke old encryption key if necessary
228
+
229
+ ## 8.2 Emergency Rotation
230
+
231
+ For suspected compromise:
232
+
233
+ 1. Publish updated Agent Card immediately
234
+ 2. Mark compromised key `revoked`
235
+ 3. Increment `keySetVersion`
236
+ 4. Begin signing with new key immediately
237
+ 5. Counterparties MUST refresh on verification miss or newer card version detection
238
+
239
+ Emergency revocation MAY break some in-flight encrypted delivery and this is acceptable.
240
+
241
+ ---
242
+
243
+ ## 9. Discovery and Cache Invalidation
244
+
245
+ ## 9.1 Canonical Discovery Surface
246
+
247
+ The Agent Card SHALL be the canonical discovery surface for current and historical INK keys.
248
+
249
+ If ATP-linked identity records or DID-linked materials are also used, they MUST be consistent with the Agent Card.
250
+
251
+ ## 9.2 Cache Behavior
252
+
253
+ Implementations SHOULD cache discovered key sets, but MUST refresh when:
254
+ - signature verification fails for all cached active keys
255
+ - a message references an unknown `keyId`
256
+ - a newer `keySetVersion` is observed
257
+ - encryption to the current key fails due to key mismatch
258
+
259
+ ## 9.3 Refresh Policy
260
+
261
+ Recommended cache TTL:
262
+ - 1 hour default
263
+
264
+ Recommended forced refresh triggers:
265
+ - verification miss
266
+ - explicit rotation signal
267
+ - card version monotonic increase
268
+
269
+ ---
270
+
271
+ ## 10. Optional Rotation Signal
272
+
273
+ INK MAY define an advisory message type:
274
+ - `network.tulpa.key_rotation`
275
+
276
+ Purpose:
277
+ - accelerate counterparty refresh
278
+ - reduce verification misses after planned rotation
279
+
280
+ This message MUST NOT be the sole source of truth.
281
+
282
+ The Agent Card remains canonical.
283
+
284
+ Recommended fields:
285
+ - `from`
286
+ - `to`
287
+ - `newKeySetVersion`
288
+ - `rotatedSigningKeyIds`
289
+ - `rotatedEncryptionKeyIds`
290
+ - `timestamp`
291
+ - `nonce`
292
+
293
+ Receivers SHOULD treat it as a hint to refresh discovery state.
294
+
295
+ ---
296
+
297
+ ## 11. Historical Verification
298
+
299
+ ## 11.1 Requirement
300
+
301
+ INK implementations MUST preserve the ability to verify:
302
+ - stored messages
303
+ - receipts
304
+ - bilateral audit events
305
+ - witness submissions
306
+ - witness inclusion references
307
+
308
+ ## 11.2 Historical Key Retention
309
+
310
+ Historical keys used for verification SHOULD remain available for at least:
311
+ - 90 days minimum
312
+
313
+ Recommended:
314
+ - retain indefinitely while marking status appropriately
315
+
316
+ If a system cannot retain historical keys indefinitely in the live Agent Card, it MUST provide a documented verified history surface.
317
+
318
+ ---
319
+
320
+ ## 12. Witness Interaction
321
+
322
+ ## 12.1 Submit Verification
323
+
324
+ Witness services MUST be able to verify audit submissions against:
325
+ - current active keys
326
+ - retired keys when validating older events or delayed submissions
327
+
328
+ ## 12.2 Query Verification
329
+
330
+ Signed witness query verification MUST use the same rotation-aware signing-key lookup rules as other INK transport verification.
331
+
332
+ ## 12.3 Retention
333
+
334
+ Witness implementations SHOULD cache or resolve historical keys in a way that preserves later verification of valid older events.
335
+
336
+ ---
337
+
338
+ ## 13. Key IDs
339
+
340
+ ## 13.1 Requirement
341
+
342
+ New INK signed messages SHOULD include the signing `keyId`.
343
+
344
+ This avoids trial-verifying across many candidate keys.
345
+
346
+ Recommended location:
347
+ - transport metadata or signed body field, depending on final wire design
348
+
349
+ If omitted, verifiers MAY try all candidate keys.
350
+
351
+ ## 13.2 Format
352
+
353
+ `keyId` MAY be any stable opaque string.
354
+
355
+ Recommended:
356
+ - `sig-YYYY-MM`
357
+ - `enc-YYYY-MM`
358
+ - or ULID-based identifiers
359
+
360
+ It MUST be unique within the agent's key set.
361
+
362
+ ---
363
+
364
+ ## 14. Data Model
365
+
366
+ Recommended local store:
367
+ - `agent_keys`
368
+
369
+ Recommended fields:
370
+ - `agent_id`
371
+ - `key_id`
372
+ - `role`
373
+ - `algorithm`
374
+ - `public_key_multibase`
375
+ - `private_key_encrypted`
376
+ - `status`
377
+ - `valid_from`
378
+ - `valid_until`
379
+ - `revoked_at`
380
+ - `created_at`
381
+ - `updated_at`
382
+
383
+ Recommended identity metadata:
384
+ - `current_signing_key_id`
385
+ - `current_encryption_key_id`
386
+ - `key_set_version`
387
+
388
+ ---
389
+
390
+ ## 15. API / Runtime Changes
391
+
392
+ Recommended runtime changes:
393
+ - key lookup by `agentId + role + status`
394
+ - verification helper that accepts candidate historical keys
395
+ - Agent Card generation from key set, not single key fields
396
+ - maintenance support for overlap transitions
397
+ - rotation admin/owner API
398
+
399
+ Recommended owner/admin APIs:
400
+ - `POST /api/tulpa/keys/rotate`
401
+ - `GET /api/tulpa/keys`
402
+ - `POST /api/tulpa/keys/:keyId/revoke`
403
+
404
+ These APIs are product/runtime concerns, not protocol requirements, but are strongly recommended.
405
+
406
+ ---
407
+
408
+ ## 16. Compatibility and Migration
409
+
410
+ ## 16.1 Backward Compatibility
411
+
412
+ During migration from single-key agents:
413
+ - Agent Cards MAY advertise both legacy single-key fields and the new key-set structure
414
+ - receivers SHOULD support both during transition
415
+
416
+ ## 16.2 Migration Path
417
+
418
+ 1. add key-set fields to Agent Card
419
+ 2. support rotation-aware verification in receivers
420
+ 3. emit `keyId` on outbound messages
421
+ 4. migrate storage from single current key to role-based key set
422
+ 5. remove assumptions that `agentId` encodes current signing key
423
+
424
+ ## 16.3 Legacy Agents
425
+
426
+ Receivers MUST continue to support legacy single-key agents during the migration window.
427
+
428
+ ---
429
+
430
+ ## 17. Security Considerations
431
+
432
+ ## 17.1 Compromise
433
+
434
+ If a signing key is compromised:
435
+ - rotation MUST support immediate revocation
436
+ - counterparties MUST refresh discovery data on verification miss
437
+
438
+ ## 17.2 Replay
439
+
440
+ Key rotation does not replace nonce/timestamp replay protections.
441
+
442
+ Those protections remain mandatory.
443
+
444
+ ## 17.3 Historical Trust
445
+
446
+ Historical verification does not imply ongoing trust.
447
+
448
+ Retired-key acceptance MUST be scoped to historical artifact verification, not new live messages.
449
+
450
+ ## 17.4 Drift
451
+
452
+ All key-role logic MUST remain consistent across:
453
+ - the primary INK runtime
454
+ - the witness/auditability runtime
455
+ - test vectors
456
+ - lexicons
457
+ - docs
458
+
459
+ ---
460
+
461
+ ## 18. Test Vectors
462
+
463
+ This spec requires new vector families for:
464
+ - active-key verification
465
+ - retired-key verification
466
+ - revoked-key rejection
467
+ - key-set version refresh behavior
468
+ - encrypted message decryption during overlap window
469
+
470
+ Minimum required cases:
471
+ - message signed by current key verifies
472
+ - message signed by retired key verifies as historical
473
+ - message signed by revoked key after `revokedAt` fails
474
+ - witness submit/query verifies against rotated key set
475
+ - stale cached key set refreshes successfully
476
+
477
+ ---
478
+
479
+ ## 19. Rollout Plan
480
+
481
+ ## Phase 1 ✓ (implemented 2026-03-25)
482
+ - ✓ `KeyEntry`, `KeyStatus`, `CandidateKey` types + Zod schemas (`src/models/key-entry.ts`)
483
+ - ✓ `AgentCardSchema` extended with optional `keys`, `currentSigningKeyId`, `currentEncryptionKeyId`, `keySetVersion`
484
+ - ✓ `agent_keys` SQLite table with lifecycle status, `identity` table gains key-set tracking columns
485
+ - ✓ `KeyStore` equivalent for agent_keys CRUD (implementer-specific path)
486
+ - ✓ `verifyInkSignatureWithKeys()` multi-key verification helper (`src/crypto/multi-key-verify.ts`)
487
+ - ✓ `verifyInkAuth` gains `resolveKeySet` parameter for multi-key transport auth, and `nonceStore: NonceStore | "deferred"` (required, fail-closed) for single-use nonce enforcement
488
+ - ✓ `PipelineContext.resolveKeySet` for multi-key message signature verification
489
+ - ✓ Receipt verification uses candidate key lists with active → retired ordering
490
+ - ✓ `extractCandidateKeys()` for Agent Card key extraction (`src/discovery/agent-card.ts`)
491
+ - ✓ `getAgentCard()` builds `keys` block from `KeyStore`
492
+ - ✓ Auto-migration: `seedFromIdentity()` on first wake-up
493
+ - ✓ `initialize()` inserts key entries alongside identity row
494
+ - ✓ Witness `verifyInkTransportAuth` signature accepts `resolveKeySet` (not yet wired)
495
+ - ✓ Test coverage: key-set schema, KeyStore CRUD, multi-key verification, end-to-end rotation vectors (see `test/ink-key-rotation.test.ts`)
496
+
497
+ ## Phase 2 ✓ (implemented 2026-03-25)
498
+ - ✓ Key rotation APIs: `POST /tulpa/keys/rotate`, `GET /tulpa/keys`, `POST /tulpa/keys/:keyId/revoke`
499
+ - ✓ `keyId` emitted on outbound INK messages (auth header `keyId=` param + envelope `signingKeyId`)
500
+ - ✓ `hintKeyId` verification: try hinted key first, fallback to active → retired scan
501
+ - ✓ Agent Card cache with SQLite-backed TTL (1 hour default) and refresh-on-miss
502
+ - ✓ Integration tests for full rotated-message paths (6 e2e tests)
503
+
504
+ ## Phase 3 ✓ (implemented 2026-03-25)
505
+ - ✓ Witness integration: `signingKeyId` passed to transport auth on witness submit
506
+ - ✓ `signingKeyId` recorded as a top-level field on `InkAuditEventSchema` for historical verification
507
+ - ✓ keyId semantics: auth header takes precedence, unknown keyId falls through, revoked keyId rejected
508
+ - ✓ Rotation observability: `signature.verified_retired`, `signature.revoked_rejected`, `key.rotated`, `key.revoked` audit event types
509
+ - ✓ `keyStatus` in `MultiKeyVerifyResult` for retired-key observability
510
+ - ✓ Audit bridge mappings: `key_rotated` → `key.rotated`, `key_revoked` → `key.revoked`
511
+ - ✓ Interop test vectors: 8 scenarios in `test-vectors/key-rotation.json`
512
+ - ✓ Phase 3 test cases in `test/ink-key-rotation.test.ts` (covers historical verification, revoked rejection, audit-event types)
513
+
514
+ ---
515
+
516
+ ## 20. Open Questions
517
+
518
+ - Should `agentId` become DID-fragment-based, handle-based, or another stable logical identifier?
519
+ - Should historical keys live only in Agent Card, or also in ATP-linked records for verifiable history?
520
+ - Should `keyId` live in the signed JSON body or an authenticated transport header?
521
+ - What exact overlap duration should be mandatory for planned encryption-key rotation?
522
+ - Should retired signing keys remain indefinitely discoverable or move to a separate verified history surface?
523
+
524
+ ---
525
+
526
+ ## 21. Recommendation
527
+
528
+ The recommended v1 direction is:
529
+ - stable logical `agentId`
530
+ - explicit role-based key sets in the Agent Card
531
+ - current + retired + revoked key lifecycle states
532
+ - rotation-aware verification
533
+ - historical verification continuity
534
+
535
+ This is the main remaining protocol design required to make INK feel finished.