Releases: ThirdKeyAI/AgentPin
Releases · ThirdKeyAI/AgentPin
v0.3.0 — A2A AgentCard + DNS TXT, four-language parity
[0.3.0] - 2026-05-14
Added
Four-language parity (Rust, JavaScript, Python, Go) for the A2A AgentCard
extension surface and DNS TXT cross-verification. Cards signed in any of the
four SDKs verify cleanly in the other three; signature canonicalisation is
byte-identical across implementations.
A2A AgentCard extension types, signed builder, and verifier
A2aAgentCard+ supporting types — minimal A2A AgentCard subset
(A2aAgentCard,A2aAgentCapabilities,A2aAgentSkill) plus the
AgentPin-specificAgentpinExtensionpayload (agentpin_endpoint,
public_key_jwk,signature). Inline definition rather than depending on
the upstreama2a-typescrate while the A2A spec is still draft.A2aAgentCardBuilder(Rust) /buildAndSignAgentCard(JS) /
build_and_sign_agent_card(Python) /a2a.BuildAndSignAgentCard(Go) —
turns an AgentDeclaration into a signedA2aAgentCard. Maps capabilities
to skills viacapability_to_skill; propagatesallowed_domainsfrom the
source constraints intoA2aAgentCapabilities.allowed_domains. Detached
ECDSA P-256 signature covers the canonical bytes of the AgentCard with the
extension cleared.verify_agentpin_extension(card)— verifies the AgentPin extension
signature against the JWK embedded in the extension. Sorted-key canonical
JSON shared across all four SDKs; mirrors the canonicalisation pattern
used by SchemaPin.AllowedDomainstyped wrapper — extracted from
Constraints::allowed_domainsand exposed for cross-protocol use
(SchemaPin v1.4'sA2aVerificationContextscopes tool verification to the
intersection of caller and provider domains). Empty list = no restriction
(all domains trusted) by convention;intersect(unrestricted, X) = X.a2a_endpointfield onDiscoveryDocument— optional URL of the
entity's A2A AgentCard endpoint, enabling cross-protocol discovery.
Discovery resolvers for A2A AgentCards
LocalAgentCardStore(all SDKs) — in-memory store of pre-registered
AgentCards keyed by their AgentPin discovery domain. Verifies the
AgentPin extension signature at registration time and pre-derives a
DiscoveryDocumentso the rest of the AgentPin verification stack runs
unchanged. Supports Symbiont's push-based external-agent registration
flow where the coordinator receives AgentCard JSON inline rather than
fetching it from a.well-knownendpoint.A2aAgentCardResolver(all SDKs; gated onfetchin Rust) — fetches
https://{domain}/.well-known/agent-card.json, verifies the AgentPin
extension, cross-checks that the embeddedagentpin_endpointhost
matches the fetched domain, and derives aDiscoveryDocument. Exposes
the original A2A representation alongside the derived doc for callers
that want both.
DNS TXT cross-verification at _agentpin.{domain}
dnsmodule (all SDKs) —parse_txt_record,verify_dns_match,
txt_record_name. Wire format mirrors SchemaPin's_schemapin.{domain}
record with the version tag changed:
"v=agentpin1; kid=...; fp=sha256:<hex>". Whitespace-tolerant parser,
case-insensitive onfp, ignores unknown fields for forward
compatibility.fetch_dns_txt(domain)— Rust: async lookup behind the newdns
Cargo feature (hickory-resolver,tokio,async-trait). JavaScript:
uses Node's built-indns/promises. Python: uses the optional
dnspythonpackage. Go:dns.LookupTxt(ctx, resolver, domain)over the
standard-librarynet.Resolver.- Multi-key match semantics — AgentPin discovery docs may carry several
keys for rotation; a published TXT record need only match one of them.
When the TXT carries an explicitkid, the matching key MUST also carry
the samekid. - Fail-closed on mismatch — a publisher who intentionally publishes a
TXT record has signaled DNS is part of their trust chain. Divergence
between DNS and.well-knownindicates compromise of one channel and is
treated as a hard failure.
Go SDK (fourth-language port)
- Initial
go/SDK — wire-compatible with Rust, JavaScript, and Python.
Mirrors the package layout of the SchemaPin Go SDK. Module path:
github.com/ThirdKeyAi/agentpin/go. - Packages:
crypto,jwk,jwt,types,discovery,credential,
verification,revocation,pinning,delegation,mutual,nonce,
bundle,resolver, plus the newa2aanddnspackages added in this
release. - CLI:
cmd/agentpinwithkeygen,issue,verify,bundle
subcommands matching the Rust binary. - ES256-only enforcement implemented inline using
crypto/ecdsa. The
JWT verifier rejectsnone,HS256,RS256,ES384, and any other
algorithm before any signature work. No third-party JWT dependency. - CI:
.github/workflows/go.ymlrunsgo test,go vet, and
gofmt -lon every PR touchinggo/**. The version-consistency check
in.github/workflows/release.ymlvalidates the Go SDK's declared
version against the Rust/JavaScript/Python versions.
Changed
- Cross-SDK version coordination — Rust, JavaScript, Python, and Go SDKs
all release as 0.3.0 together. The earlier0.3.0-alpha.1Rust
preview is superseded by this entry. - Rust MSRV bumped from 1.70 to 1.86. Downstream ecosystem crates
(getrandom,clap_builder, theicu_*family) have moved to edition
2024 and/or to declared rust-version 1.86, making the previously-
declared 1.70 floor unbuildable from scratch in practice. The CI
matrix's MSRV row now tests against 1.86.
Notes
- This release is the unblock for Symbiont v1.8.0 Phase 3 (AgentPin-
verified AgentCards, A2A auth middleware) and SchemaPin v1.4.0's
A2aVerificationContext(which consumesAllowedDomainsfor tool-
verification scoping). Both downstream releases were waiting on this
surface. - DNS TXT defends against HTTPS-origin compromise (compromised hosting
account, expired domain not removed from CDN, ACME ownership-validation
bypass) and TLS cert mis-issuance — the DNS credential chain (registrar,
DNS provider, optionally DNSSEC) is independent of the HTTPS hosting
chain. Spec § 4.8.3 reserved this slot in v0.1; this release ships the
implementation across all SDKs. - All additions are purely additive — v0.2.0 callers are unaffected.
Discovery documents withouta2a_endpoint, AgentCards without an
agentpinextension, and absent_agentpinTXT records all behave
exactly as before.