@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.
- package/CHANGELOG.md +63 -0
- package/CODE_OF_CONDUCT.md +42 -0
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +133 -0
- package/SECURITY.md +57 -0
- package/docs/key-rotation-rule.md +108 -0
- package/docs/logo.svg +8 -0
- package/docs/maturity.md +81 -0
- package/docs/threat-model.md +150 -0
- package/package.json +72 -0
- package/specs/ink-agent-containment-and-governance-extension-spec.md +508 -0
- package/specs/ink-auditability.md +652 -0
- package/specs/ink-authorization-chain.md +242 -0
- package/specs/ink-compatibility-policy.md +263 -0
- package/specs/ink-compliance-checklist.md +309 -0
- package/specs/ink-containment-phase1-implementation-spec.md +593 -0
- package/specs/ink-introduction-receipts-extension.md +501 -0
- package/specs/ink-key-rotation-spec.md +535 -0
- package/src/crypto/ink.ts +902 -0
- package/src/crypto/keys.ts +211 -0
- package/src/crypto/multi-key-verify.ts +170 -0
- package/src/crypto/sign.ts +155 -0
- package/src/crypto/verify.ts +1 -0
- package/src/discovery/agent-card.ts +508 -0
- package/src/index.ts +59 -0
- package/src/ink/checkpoint.ts +75 -0
- package/src/ink/discovery-gating.ts +147 -0
- package/src/ink/handshake-budget.ts +413 -0
- package/src/ink/receipts.ts +114 -0
- package/src/ink/transport-auth.ts +96 -0
- package/src/middleware/ink-auth.ts +263 -0
- package/src/models/agent-card.ts +63 -0
- package/src/models/ink-audit.ts +205 -0
- package/src/models/ink-handshake.ts +123 -0
- package/src/models/intent.ts +201 -0
- package/src/models/key-entry.ts +52 -0
- package/src/models/profile.ts +31 -0
- package/test-vectors/README.md +129 -0
- package/test-vectors/encryption.json +90 -0
- package/test-vectors/handshake.json +482 -0
- package/test-vectors/jcs.json +30 -0
- package/test-vectors/key-rotation.json +101 -0
- package/test-vectors/keys.json +32 -0
- package/test-vectors/receipts-and-audit.json +142 -0
- package/test-vectors/replay.json +88 -0
- package/test-vectors/signing.json +61 -0
- package/test-vectors/witness.json +394 -0
package/docs/maturity.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Maturity Notice
|
|
2
|
+
|
|
3
|
+
> INK v0.1 is **experimental**. Wire formats, trust semantics and APIs
|
|
4
|
+
> may change without backward-compatible migration before v1.0. Do not
|
|
5
|
+
> use for load-bearing production traffic without your own review.
|
|
6
|
+
|
|
7
|
+
## What "experimental" means here
|
|
8
|
+
|
|
9
|
+
- The repository has **not** undergone an independent security audit.
|
|
10
|
+
It has been through structured internal review covering signature
|
|
11
|
+
handling, key rotation, replay protection, SSRF defenses on
|
|
12
|
+
agent-card fetch, and DoS-amplification surfaces. Internal review is
|
|
13
|
+
not a substitute for a third-party audit, treat the security
|
|
14
|
+
posture accordingly.
|
|
15
|
+
- Interop vectors (`../test-vectors/`) are authoritative for v0.1 but may
|
|
16
|
+
be added to or revised between v0.1 patch releases. Mismatched
|
|
17
|
+
implementations should report discrepancies as issues.
|
|
18
|
+
- The protocol is in use by one production integrator (Tulpa). That is
|
|
19
|
+
one data point, not a guarantee of robustness at scale.
|
|
20
|
+
- The reference implementation in `src/` runs on any runtime providing
|
|
21
|
+
standard Web Crypto (`crypto.subtle`) and `fetch`, modern Node, Deno,
|
|
22
|
+
Bun, and edge runtimes. Browser use is feasible but not exercised by
|
|
23
|
+
the maintainers.
|
|
24
|
+
|
|
25
|
+
## What is stable in v0.1
|
|
26
|
+
|
|
27
|
+
- Envelope structure (fields, canonicalization with JCS / RFC 8785)
|
|
28
|
+
- Ed25519 signing base: `ink/0.1\nMETHOD\nPATH\nrecipientDid\nJCS(body)\ntimestamp`
|
|
29
|
+
- Agent Card schema for `keys.signing` and `keys.encryption`
|
|
30
|
+
- Key rotation authority rule (see `key-rotation-rule.md`)
|
|
31
|
+
- Timestamp freshness semantics: 5 min past tolerance, 30 s future
|
|
32
|
+
tolerance. Nonce cache TTL is integrator-defined (the witness
|
|
33
|
+
reference uses 10 min); INK does not mandate it.
|
|
34
|
+
- Receipt envelope structure
|
|
35
|
+
|
|
36
|
+
## What may still change
|
|
37
|
+
|
|
38
|
+
- Authorization chain attenuation semantics, currently spec'd as
|
|
39
|
+
scope-subset-only delegation; may gain time-bounded or usage-bounded
|
|
40
|
+
variants.
|
|
41
|
+
- Containment vocabulary (capability-gated visibility, sender budgets,
|
|
42
|
+
backoff hints), the current shape is deliberately minimal; a v0.2
|
|
43
|
+
may formalize policy expression.
|
|
44
|
+
- Third-party witness submission API, currently a reference client
|
|
45
|
+
only. The submission envelope may move to a signed-bundle format in
|
|
46
|
+
the future.
|
|
47
|
+
- Encryption envelope AAD composition, the current AAD is
|
|
48
|
+
`ink/0.1:envelope\n` followed by the JCS canonicalization of
|
|
49
|
+
`{protocol, type, from, ephemeralKey, nonce, timestamp, messageNonce}`.
|
|
50
|
+
Future versions may include the recipient DID or evolve the field set.
|
|
51
|
+
|
|
52
|
+
## Versioning
|
|
53
|
+
|
|
54
|
+
Pre-1.0 releases follow `0.Y.Z` semantics:
|
|
55
|
+
|
|
56
|
+
- `0.Y.0`, Minor version bump indicates a wire-format change. Receivers
|
|
57
|
+
must support at least one prior minor during a transition window.
|
|
58
|
+
- `0.Y.Z` (Z > 0), Patch bumps fix bugs in the reference implementation
|
|
59
|
+
and update test vectors where needed. They do not change wire format.
|
|
60
|
+
|
|
61
|
+
Breaking changes before v1.0 will be announced in the repository
|
|
62
|
+
changelog with at least 30 days of overlap support in the reference
|
|
63
|
+
implementation.
|
|
64
|
+
|
|
65
|
+
## How to evaluate for your use
|
|
66
|
+
|
|
67
|
+
Before adopting INK for any use where signature forgery or replay would
|
|
68
|
+
be a real incident:
|
|
69
|
+
|
|
70
|
+
1. Read [`threat-model.md`](./threat-model.md). Make sure your use case
|
|
71
|
+
falls inside the in-scope protections and you accept the out-of-scope
|
|
72
|
+
limits.
|
|
73
|
+
2. Run `../test-vectors/*` against your implementation.
|
|
74
|
+
3. Fuzz your envelope parser. The reference implementation's tests are
|
|
75
|
+
not a substitute.
|
|
76
|
+
4. Pen-test the rotation and revocation flows specifically. The
|
|
77
|
+
authority rule is the single most security-sensitive piece and the
|
|
78
|
+
most common place to introduce a shadowing bug.
|
|
79
|
+
5. If your integration accepts delegation tokens or other capability
|
|
80
|
+
handoffs, design their trust model explicitly, INK v0.1 does not
|
|
81
|
+
specify one.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Threat Model
|
|
2
|
+
|
|
3
|
+
This document describes what INK v0.1 aims to protect against and what it
|
|
4
|
+
does not. It is deliberately conservative. Treat every "not protected"
|
|
5
|
+
statement as a real limit of the current design.
|
|
6
|
+
|
|
7
|
+
## In-scope protections
|
|
8
|
+
|
|
9
|
+
### 1. Request authenticity
|
|
10
|
+
A signed INK message cannot be forged without one of the sender's currently
|
|
11
|
+
accepted signing keys under the key-rotation authority rule: any `active`
|
|
12
|
+
or `retired` key inside the validity window verifies, revoked keys never
|
|
13
|
+
verify. Endpoints that require a still-trusted key (writes, capability
|
|
14
|
+
grants) can pass `requireActiveKey: true` to `verifyInkAuth` to reject
|
|
15
|
+
retired-key signatures. The signing base covers method, path, recipient
|
|
16
|
+
DID, canonical JSON of the body, and timestamp; an attacker who can
|
|
17
|
+
replay body bytes but mutate any of those fields cannot produce a valid
|
|
18
|
+
signature.
|
|
19
|
+
|
|
20
|
+
### 2. Replay protection (narrow window)
|
|
21
|
+
Each INK message body carries a `nonce` and `timestamp` (the latter is
|
|
22
|
+
also covered by the signing base). Receivers reject any timestamp more
|
|
23
|
+
than 5 minutes old or more than 30 seconds in the future (clock-skew
|
|
24
|
+
tolerance). Within that window, nonces are single-use per (sender,
|
|
25
|
+
receiver), a nonce that was already accepted is rejected. This means a
|
|
26
|
+
captured message can only be replayed within ~5 minutes on a receiver
|
|
27
|
+
that has not seen its nonce. Two enforcement paths are available:
|
|
28
|
+
`verifyInkAuth` enforces nonce single-use after signature verification
|
|
29
|
+
when passed a `NonceStore`; passing `"deferred"` is an explicit
|
|
30
|
+
acknowledgement that the caller will run `checkReplay` (or an
|
|
31
|
+
equivalent gate) elsewhere in the pipeline. Omitting `nonceStore`
|
|
32
|
+
returns `nonce_handling_required` so misconfigured deployments fail
|
|
33
|
+
loudly. Nonce backing storage and TTL policy are the integrator's
|
|
34
|
+
choice.
|
|
35
|
+
|
|
36
|
+
### 3. Key rotation authority
|
|
37
|
+
See [`key-rotation-rule.md`](./key-rotation-rule.md). Revoked keys can
|
|
38
|
+
never verify. Retired keys can verify only during grace periods. The Card
|
|
39
|
+
signing set wins over locally-cached copies. Bootstrap keys are
|
|
40
|
+
first-contact only.
|
|
41
|
+
|
|
42
|
+
### 4. Authorization chain integrity
|
|
43
|
+
A delegation from agent A to agent B is signed by A over A's identity,
|
|
44
|
+
B's identity, and the allowed scope. B cannot invent authorization B was
|
|
45
|
+
not given. See
|
|
46
|
+
[`../specs/ink-authorization-chain.md`](../specs/ink-authorization-chain.md).
|
|
47
|
+
|
|
48
|
+
### 5. Receipt / audit envelope integrity
|
|
49
|
+
Delivery and read receipts are Ed25519-signed by the agent that issued
|
|
50
|
+
them. A receiver that stores receipts for audit can later prove the
|
|
51
|
+
counterparty acknowledged delivery without needing to trust INK itself.
|
|
52
|
+
Receipts do not verify using `revoked` keys.
|
|
53
|
+
|
|
54
|
+
### 6. Capability-gated Agent Card discovery
|
|
55
|
+
An agent whose Card visibility is `network_only` or `capability_gated`
|
|
56
|
+
returns a redacted Card to anonymous queries. The redacted Card preserves
|
|
57
|
+
public signing keys (so rotation discovery still works) but hides
|
|
58
|
+
capabilities, endpoints, availability and profile.
|
|
59
|
+
|
|
60
|
+
### 7. Handshake-budget DoS resistance
|
|
61
|
+
Per-sender and per-recipient budgets throttle how many failing handshakes
|
|
62
|
+
an unknown sender can force a recipient to process. Over-budget senders
|
|
63
|
+
receive a signed backoff hint; persistently abusive senders are
|
|
64
|
+
rate-limited at the transport layer.
|
|
65
|
+
|
|
66
|
+
## Out of scope (known limits)
|
|
67
|
+
|
|
68
|
+
### Identity proof
|
|
69
|
+
INK does not prove *who* an agent is in the real world. Identity-system
|
|
70
|
+
compromise (a malicious PDS returning a fabricated DID document, a
|
|
71
|
+
compromised registration service) is the identity system's problem.
|
|
72
|
+
Receivers authenticate *the cryptographic continuity* of a senderId ↔
|
|
73
|
+
Agent Card binding; they cannot authenticate that the human behind the
|
|
74
|
+
agent is who they claim.
|
|
75
|
+
|
|
76
|
+
### Compromised endpoints
|
|
77
|
+
If a sender's private keys are exfiltrated, an attacker can sign anything
|
|
78
|
+
the legitimate sender could until the key is revoked. INK's rotation rule
|
|
79
|
+
bounds the damage window but does not eliminate it. Key custody is out of
|
|
80
|
+
scope.
|
|
81
|
+
|
|
82
|
+
### Malicious marketplace extensions (if you integrate one)
|
|
83
|
+
The reference implementation does not include an extension/marketplace
|
|
84
|
+
layer. A product that integrates INK and adds a delegation-token layer
|
|
85
|
+
(for third-party agents to act on behalf of users) must design its own
|
|
86
|
+
trust model for the marketplace, manifest review, and capability
|
|
87
|
+
attenuation. INK v0.1 deliberately excludes this surface.
|
|
88
|
+
|
|
89
|
+
### Timing side-channels
|
|
90
|
+
`@noble/ed25519` is believed to be constant-time, but this has not been
|
|
91
|
+
independently audited in the INK context. Attacks that rely on very
|
|
92
|
+
precise timing of verification against a candidate key set are not
|
|
93
|
+
currently mitigated beyond what the underlying library provides.
|
|
94
|
+
|
|
95
|
+
### Traffic analysis
|
|
96
|
+
INK messages reveal their type, sender, recipient, and approximate size
|
|
97
|
+
even when the payload is encrypted (`ink_encrypted`). A passive observer
|
|
98
|
+
on the network path can enumerate agent relationships over time. Mixnets,
|
|
99
|
+
onion routing, and other unlinkability mechanisms are not part of INK.
|
|
100
|
+
|
|
101
|
+
### Side-channels in the agent itself
|
|
102
|
+
An agent that signs an INK message has seen the full plaintext. If the
|
|
103
|
+
agent is compromised, no amount of INK-layer protection helps. This is
|
|
104
|
+
especially important for agents that delegate to LLMs, prompt-injection
|
|
105
|
+
attacks against the agent's model can result in INK messages that are
|
|
106
|
+
cryptographically valid but semantically wrong (the model sent what the
|
|
107
|
+
attacker coaxed, not what the user wanted). INK does not address this.
|
|
108
|
+
|
|
109
|
+
### Audit finality
|
|
110
|
+
INK supports witness submission for tamper-evident audit logs (see
|
|
111
|
+
[`../specs/ink-auditability.md`](../specs/ink-auditability.md)), but
|
|
112
|
+
does not by itself provide consensus or finality. Two honest receivers
|
|
113
|
+
that disagree about a message's receipt status cannot be reconciled by
|
|
114
|
+
INK alone.
|
|
115
|
+
|
|
116
|
+
### Denial of service at the TCP/IP layer
|
|
117
|
+
INK's handshake budget protects against L7 DoS from known-pending senders.
|
|
118
|
+
It does not protect against L3/L4 floods, resource-exhaustion attacks on
|
|
119
|
+
the HTTP stack, or amplification attacks. Those remain the transport
|
|
120
|
+
operator's responsibility.
|
|
121
|
+
|
|
122
|
+
### Cryptographic primitives
|
|
123
|
+
Ed25519 signatures, X25519 key exchange, AES-GCM for payload encryption.
|
|
124
|
+
If any of those primitives fails (future quantum attacks, implementation
|
|
125
|
+
flaws in `@noble/*` libraries), INK v0.1 has no fallback. A v1.0 might
|
|
126
|
+
specify algorithm agility.
|
|
127
|
+
|
|
128
|
+
## Assumptions the protocol relies on
|
|
129
|
+
|
|
130
|
+
- TLS to the transport endpoint is correctly configured. INK signs at
|
|
131
|
+
the application layer but assumes confidentiality during transport.
|
|
132
|
+
- Server clocks are within 5 minutes of real time. Both the ±5-minute
|
|
133
|
+
timestamp window and the nonce TTL depend on this.
|
|
134
|
+
- The identity-system `senderId → Agent Card` resolution returns the
|
|
135
|
+
current Card within acceptable latency (receivers may cache with a
|
|
136
|
+
reasonable TTL, typically minutes).
|
|
137
|
+
- Receivers persist nonces durably enough to enforce the no-replay
|
|
138
|
+
window. A receiver that loses its nonce cache during a restart MAY see
|
|
139
|
+
duplicate accepts, this is a transient failure, not a protocol break.
|
|
140
|
+
|
|
141
|
+
## Recommended receiver defaults
|
|
142
|
+
|
|
143
|
+
| Setting | Default |
|
|
144
|
+
|----------------------------------|------------------------|
|
|
145
|
+
| Timestamp max age | 5 minutes |
|
|
146
|
+
| Timestamp future skew tolerance | 30 seconds |
|
|
147
|
+
| Nonce TTL | 10 minutes |
|
|
148
|
+
| Agent Card cache TTL | 5 minutes |
|
|
149
|
+
| Unknown-sender handshake budget | 20 per hour per sender |
|
|
150
|
+
| Retired-key acceptance grace | Up to 30 days |
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adastracomputing/ink",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Reference implementation and specification of the INK (Inter-agent Networking Kernel) protocol",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"author": "Ad Astra Computing Inc.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/Ad-Astra-Computing/ink.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://ink.tulpa.network",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Ad-Astra-Computing/ink/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./src/index.ts",
|
|
17
|
+
"types": "./src/index.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./src/index.ts",
|
|
21
|
+
"default": "./src/index.ts"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"src/",
|
|
31
|
+
"specs/",
|
|
32
|
+
"docs/",
|
|
33
|
+
"test-vectors/",
|
|
34
|
+
"LICENSE-MIT",
|
|
35
|
+
"LICENSE-APACHE",
|
|
36
|
+
"README.md",
|
|
37
|
+
"SECURITY.md",
|
|
38
|
+
"CHANGELOG.md",
|
|
39
|
+
"CODE_OF_CONDUCT.md"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"lint": "eslint src/ test/ scripts/",
|
|
45
|
+
"check:surface": "tsx scripts/check-public-surface.ts"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@noble/curves": "^2.2.0",
|
|
49
|
+
"@noble/ed25519": "^2.1.0",
|
|
50
|
+
"@noble/hashes": "^1.8.0",
|
|
51
|
+
"canonicalize": "^2.1.0",
|
|
52
|
+
"zod": "^3.23.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@cloudflare/workers-types": "^4.20260418.1",
|
|
56
|
+
"@types/node": "^22.0.0",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
|
58
|
+
"@typescript-eslint/parser": "^8.60.0",
|
|
59
|
+
"eslint": "^10.4.0",
|
|
60
|
+
"tsx": "^4.22.3",
|
|
61
|
+
"typescript": "^5.6.0",
|
|
62
|
+
"vitest": "^4.1.7"
|
|
63
|
+
},
|
|
64
|
+
"keywords": [
|
|
65
|
+
"ink",
|
|
66
|
+
"agent-protocol",
|
|
67
|
+
"ed25519",
|
|
68
|
+
"atproto",
|
|
69
|
+
"agent-to-agent",
|
|
70
|
+
"reference-implementation"
|
|
71
|
+
]
|
|
72
|
+
}
|