@adastracomputing/ink 0.1.1 → 0.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/CHANGELOG.md +38 -0
- package/README.md +27 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +7 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,8 +8,46 @@ here. Pre-1.0 releases follow `0.Y.Z` semantics, see
|
|
|
8
8
|
|
|
9
9
|
No unreleased changes.
|
|
10
10
|
|
|
11
|
+
## 0.1.3, expose validateMessage and decodeEncryptionKeyMultibase from the package root
|
|
12
|
+
|
|
13
|
+
Pure additive release that re-exports two helpers from the package root so adopters no longer have to import them through a deep internal path:
|
|
14
|
+
|
|
15
|
+
- `validateMessage(raw)` runs the canonical `MessageEnvelopeSchema` parse plus the intent-specific payload schema. Receivers building from scratch were either re-implementing the schema check or pulling from `@adastracomputing/ink/dist/models/intent.js`, which is not a stable surface. The implementer-guide at https://ink.tulpa.network/guides/implementing-a-receiver/ documented this helper as if it were already exported; this release makes that documentation accurate.
|
|
16
|
+
- `decodeEncryptionKeyMultibase(multibase)` is the companion to the already-exported `decodePublicKeyMultibase`. The former handles X25519 keys (the Agent Card encryption-key prefix); the latter handles Ed25519. The encrypted-intents guide tells adopters to decode an Agent Card's `publicKeyMultibase` for use with `encryptInkPayload`, which expects hex; without the X25519 decoder exported, adopters had to inline the multicodec strip themselves.
|
|
17
|
+
|
|
18
|
+
Also re-exports the `MessageEnvelope` type and the `MessageEnvelopeSchema` constant so adopters can type their parser surface against the canonical schema. No wire-level changes. No behavior changes inside the existing functions. Receivers on 0.1.2 work unchanged on 0.1.3.
|
|
19
|
+
|
|
20
|
+
This release publishes under the npm `next` dist-tag per the pre-1.0 policy.
|
|
21
|
+
|
|
22
|
+
## 0.1.2, Python interop CLI emits canonical envelope
|
|
23
|
+
|
|
24
|
+
> **Maturity note.** v0.1.x is wire-compatible across patches (`ink/0.1` stays frozen) but the API surface and trust semantics remain alpha-quality. See [`docs/maturity.md`](docs/maturity.md). Starting with this release, pre-1.0 versions publish under npm's `next` dist-tag; `latest` only advances when a release is explicitly promoted. Adopters who want the current pre-1.0 line install with `npm install @adastracomputing/ink@next`; the bare `npm install @adastracomputing/ink` will resolve to the most recent release a maintainer has stamped adopter-grade.
|
|
25
|
+
|
|
26
|
+
Fixes the v0.1.1 erratum: the Python `examples/interop-cli/` shipped in v0.1.1 emitted a phantom envelope shape (`type`, `intentType`, `purpose`, `urgency` at top level, no `id`, no `correlationId`, no `createdAt`, no body-level `signature`) that no conforming receiver could accept. v0.1.2 rewrites the CLI's envelope builder to emit the canonical `MessageEnvelopeSchema` shape:
|
|
27
|
+
|
|
28
|
+
- `id` and `correlationId` are now generated as 26-char Crockford-base32 ULIDs.
|
|
29
|
+
- `createdAt` is the canonical envelope creation timestamp (ISO-8601 UTC); the body also carries a separate `timestamp` field that `verifyInkAuth()` uses for HTTP §3.3 freshness, distinct from `createdAt`.
|
|
30
|
+
- `intent` is the canonical enum value (`intro_request` for introductions); the legacy `intentType`/`purpose` flatten into `payload: { target, reason, urgency }` per `IntroRequestPayloadSchema`.
|
|
31
|
+
- Body-level `signature` is now produced by the canonical domain-separated signer (`Ed25519("tulpa/sign\n" + JCS(envelope-without-signature))`, base64url, no padding) — matches `src/crypto/sign.ts` byte-for-byte.
|
|
32
|
+
- `provenance` is omitted when absent (the field is `.optional()`; an explicit `null` would be rejected by Zod).
|
|
33
|
+
- HTTP §3.3 fields (`timestamp`, `nonce`) ride alongside the canonical fields so `verifyInkAuth()` still reads them.
|
|
34
|
+
|
|
35
|
+
**CLI now builds `connection_request` envelopes.** `ink-interop send/build --intent-type connection_request` (or the alias `connection`) constructs a `ConnectionRequestPayloadSchema`-conformant payload (`method`, `context`, `profileSnapshot`). This is the bootstrap intent for first contact between strangers: receivers that opt in to foreign senders verify the body signature against the inline key extracted from the sender's `did:key` (trust-on-first-use). Other intent types (`intro_request`, `ask`, `follow_up`) presume the sender is already a known contact and remain reserved for established relationships.
|
|
36
|
+
|
|
37
|
+
Verified end-to-end against `https://api.tulpa.network/ink/v1/<agentId>/intent`: a `did:key:` `connection_request` from `ink-interop send` lands as a pending action in the recipient's inbox (`status: 200`, `accepted: true`, `pendingActionId: 01KT…`). Coverage spans schema validation, body + transport signature verification, replay/freshness, identity resolution, routing, the foreign-DID policy gate, and shield risk-scoring. Tests pinned to the canonical shape (`tests/test_envelope.py`) prevent regression. The npm library itself is unchanged from v0.1.1.
|
|
38
|
+
|
|
39
|
+
**Example-helper API break.** `examples/interop-cli/`'s Python helper `build_intent_envelope()` now requires `keypair`, replaces `intent_type`/`purpose`/`timestamp` with canonical args (`target`, `reason`, `created_at`, etc.), and removes the `extra=` kwarg. Adopters who imported the old helper directly will need to update their calls — the previous signature emitted invalid wire data so no callable interop existed there to preserve. This is an example-only change; the npm library (`@adastracomputing/ink`) exports are unchanged.
|
|
40
|
+
|
|
11
41
|
## 0.1.1, discovery rename and normative SSRF floor
|
|
12
42
|
|
|
43
|
+
> **Erratum, 2026-06-01:** the bundled Python interop CLI at
|
|
44
|
+
> `examples/interop-cli/` shipped with this tag emits an envelope
|
|
45
|
+
> shape that does not match the canonical `MessageEnvelopeSchema`
|
|
46
|
+
> (`id`, `correlationId`, `createdAt`, `intent` enum, payload,
|
|
47
|
+
> body-level `signature`). The npm library is unaffected. End-to-end
|
|
48
|
+
> sends from the Python CLI to a conforming receiver fail with
|
|
49
|
+
> `invalid_envelope`. Fixed in v0.1.2.
|
|
50
|
+
|
|
13
51
|
This release is **wire-compatible with v0.1.0**; the wire version stays `ink/0.1`. Every change below is additive and accepts the prior shape for the duration of the v0.1.x line — implementations that emit and consume v0.1.0 cards / service entries continue to interoperate. One observable library behavior changes: the runtime emit value of the redacted Agent Card `type` field flips from `"tulpa.agent.card"` to `"ink.agent.card"` (see below). Consumers that pinned to the literal must accept either string; the TypeScript union has been widened accordingly.
|
|
14
52
|
|
|
15
53
|
**Service entry rename.** The DID Document service entry for INK endpoints is now `type: "INKAgentEndpoint"`. The legacy `"TulpaAgentEndpoint"` is still accepted by consumers during v0.1.x; new publishers SHOULD emit `INKAgentEndpoint`. When both are present, `INKAgentEndpoint` takes precedence. Removed at the next wire-version bump.
|
package/README.md
CHANGED
|
@@ -10,17 +10,34 @@ An open protocol for AI agents that need to send each other typed, signed messag
|
|
|
10
10
|
|---|---|
|
|
11
11
|
| Spec | [`specs/`](specs/) |
|
|
12
12
|
| Docs | [ink.tulpa.network](https://ink.tulpa.network) |
|
|
13
|
+
| npm | [`@adastracomputing/ink`](https://www.npmjs.com/package/@adastracomputing/ink) |
|
|
13
14
|
| Contributing | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
|
|
14
15
|
| Security | [`SECURITY.md`](SECURITY.md) |
|
|
15
16
|
| Code of Conduct | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) |
|
|
16
17
|
| Changelog | [`CHANGELOG.md`](CHANGELOG.md) |
|
|
17
18
|
|
|
19
|
+
## Contents
|
|
20
|
+
|
|
21
|
+
- [What's in the envelope](#whats-in-the-envelope)
|
|
22
|
+
- [Install](#install)
|
|
23
|
+
- [Agent-assisted implementation](#agent-assisted-implementation)
|
|
24
|
+
- [Tests](#tests)
|
|
25
|
+
- [Layout](#layout)
|
|
26
|
+
- [What's stable in v0.1](#whats-stable-in-v01)
|
|
27
|
+
- [Naming](#naming)
|
|
28
|
+
- [Relationship to Tulpa](#relationship-to-tulpa)
|
|
29
|
+
- [Interoperability](#interoperability)
|
|
30
|
+
- [Security](#security)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
18
33
|
## What's in the envelope
|
|
19
34
|
|
|
20
35
|
Every INK message is an Ed25519-signed envelope over a [JCS](https://datatracker.ietf.org/doc/html/rfc8785) (RFC 8785) canonical serialization. The signature base binds the protocol version, HTTP method, request path, recipient DID, body, and timestamp. Replay protection uses a per-sender nonce plus a timestamp freshness window of 5 minutes past and 30 seconds future.
|
|
21
36
|
|
|
22
37
|
Message types cover intents, challenges, resolutions, receipts, audit events, encrypted payloads, and authenticated agent-card queries. Handshake messages carry a correlation ID; audit and receipt messages do not. Key rotation is governed by an authority rule documented in [`docs/key-rotation-rule.md`](docs/key-rotation-rule.md): the Agent Card's published key set is canonical, revoked keys never verify, and a stale bootstrap key cannot bypass rotation.
|
|
23
38
|
|
|
39
|
+
A foreign sender's first envelope to an unestablished recipient is a `connection_request` — the bootstrap intent for first contact. Receivers that opt in to foreign senders verify the body signature against the inline key extracted from the sender's DID (trust-on-first-use) and SHOULD reject any other intent type from a sender they have no prior relationship with; richer intent types (`intro_request`, `ask`, `follow_up`, `schedule_meeting`) presume the sender is already a known contact. See the [Accepting Foreign Senders guide](https://ink.tulpa.network/guides/accepting-foreign-senders/) for the receive-side rules and [`examples/foreign-sender-receiver/`](examples/foreign-sender-receiver/) for a reference implementation.
|
|
40
|
+
|
|
24
41
|
INK assumes [AT Protocol](https://atproto.com) for identity by default but isn't coupled to it. Any system that can publish an Ed25519 signing key under a stable identifier can participate.
|
|
25
42
|
|
|
26
43
|
## Install
|
|
@@ -49,10 +66,18 @@ const input = {
|
|
|
49
66
|
recipientDid: "tulpa:zRecipient",
|
|
50
67
|
body: {
|
|
51
68
|
protocol: "ink/0.1",
|
|
52
|
-
|
|
69
|
+
id: crypto.randomUUID(),
|
|
70
|
+
correlationId: crypto.randomUUID(),
|
|
71
|
+
createdAt: new Date().toISOString(),
|
|
53
72
|
from: agentId,
|
|
54
73
|
to: "tulpa:zRecipient",
|
|
55
|
-
intent: "
|
|
74
|
+
intent: "schedule_meeting",
|
|
75
|
+
payload: {
|
|
76
|
+
proposedTimes: ["2026-06-15T14:00:00Z"],
|
|
77
|
+
topic: "Quick sync",
|
|
78
|
+
format: "video",
|
|
79
|
+
urgency: "normal",
|
|
80
|
+
},
|
|
56
81
|
timestamp: new Date().toISOString(),
|
|
57
82
|
nonce: crypto.randomUUID(),
|
|
58
83
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export { signInkMessage, verifyInkSignature, buildSignatureBase, buildAuthHeader, computeMessageHash, computeEventHash, computeAuditMerkleLeafHash, signAuditEvent, verifyAuditEventSignature, signAuditResponse, verifyAuditResponseSignature, verifyAuditEventChain, signAuditQueryResponse, verifyAuditQueryResponseSignature, encryptInkPayload, decryptInkPayload, checkReplay, base64urlEncode, base64urlDecode, hexToBytes, bytesToHex, jcsCanonicalize, MAX_TIMESTAMP_AGE_MS, MAX_FUTURE_TIMESTAMP_MS, } from "./crypto/ink.js";
|
|
2
2
|
export { signMessage, verifyMessage } from "./crypto/sign.js";
|
|
3
3
|
export { verifyInkSignatureWithKeys } from "./crypto/multi-key-verify.js";
|
|
4
|
-
export { generateKeypair, generateEncryptionKeypair, deriveAgentId, encodePublicKeyMultibase, decodePublicKeyMultibase, extractPublicKeyFromAgentId, } from "./crypto/keys.js";
|
|
4
|
+
export { generateKeypair, generateEncryptionKeypair, deriveAgentId, encodePublicKeyMultibase, decodePublicKeyMultibase, decodeEncryptionKeyMultibase, extractPublicKeyFromAgentId, } from "./crypto/keys.js";
|
|
5
5
|
export { fetchAgentCard, extractCandidateKeys, resolveBaseUrl, } from "./discovery/agent-card.js";
|
|
6
6
|
export { verifyInkAuth, type NonceStore } from "./middleware/ink-auth.js";
|
|
7
7
|
export { verifyInclusionReceipt, verifyAuditQueryResponse, type InclusionReceipt, type InclusionReceiptVerifyResult, type AuditQueryResponse, type AuditQueryResponseVerifyResult, type VerifyStep, } from "./audit/inclusion-receipt.js";
|
|
8
8
|
export { HandshakeBudgetTracker } from "./ink/handshake-budget.js";
|
|
9
|
+
export { validateMessage, MessageEnvelopeSchema } from "./models/intent.js";
|
|
10
|
+
export type { MessageEnvelope } from "./models/intent.js";
|
|
9
11
|
export type { InkSignInput } from "./crypto/ink.js";
|
|
10
12
|
export type { CandidateKey } from "./models/key-entry.js";
|
|
11
13
|
export { resolveAgentInbox } from "./models/agent-card.js";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export { signInkMessage, verifyInkSignature, buildSignatureBase, buildAuthHeader, computeMessageHash, computeEventHash, computeAuditMerkleLeafHash, signAuditEvent, verifyAuditEventSignature, signAuditResponse, verifyAuditResponseSignature, verifyAuditEventChain, signAuditQueryResponse, verifyAuditQueryResponseSignature, encryptInkPayload, decryptInkPayload, checkReplay, base64urlEncode, base64urlDecode, hexToBytes, bytesToHex, jcsCanonicalize, MAX_TIMESTAMP_AGE_MS, MAX_FUTURE_TIMESTAMP_MS, } from "./crypto/ink.js";
|
|
5
5
|
export { signMessage, verifyMessage } from "./crypto/sign.js";
|
|
6
6
|
export { verifyInkSignatureWithKeys } from "./crypto/multi-key-verify.js";
|
|
7
|
-
export { generateKeypair, generateEncryptionKeypair, deriveAgentId, encodePublicKeyMultibase, decodePublicKeyMultibase, extractPublicKeyFromAgentId, } from "./crypto/keys.js";
|
|
7
|
+
export { generateKeypair, generateEncryptionKeypair, deriveAgentId, encodePublicKeyMultibase, decodePublicKeyMultibase, decodeEncryptionKeyMultibase, extractPublicKeyFromAgentId, } from "./crypto/keys.js";
|
|
8
8
|
// Discovery: Agent Card fetch + candidate-key extraction
|
|
9
9
|
export { fetchAgentCard, extractCandidateKeys, resolveBaseUrl, } from "./discovery/agent-card.js";
|
|
10
10
|
// Middleware: transport-level INK auth
|
|
@@ -13,4 +13,10 @@ export { verifyInkAuth } from "./middleware/ink-auth.js";
|
|
|
13
13
|
export { verifyInclusionReceipt, verifyAuditQueryResponse, } from "./audit/inclusion-receipt.js";
|
|
14
14
|
// Optional containment / governance primitives
|
|
15
15
|
export { HandshakeBudgetTracker } from "./ink/handshake-budget.js";
|
|
16
|
+
// Envelope validation: full Zod-backed parse of the canonical
|
|
17
|
+
// MessageEnvelope shape. Adopters building receivers need this to
|
|
18
|
+
// reject malformed envelopes before signature verification; without
|
|
19
|
+
// it they have to re-implement the schema check or import from a
|
|
20
|
+
// non-public path.
|
|
21
|
+
export { validateMessage, MessageEnvelopeSchema } from "./models/intent.js";
|
|
16
22
|
export { resolveAgentInbox } from "./models/agent-card.js";
|
package/package.json
CHANGED