change(ard): drop the trust-manifest signature; publish the catalogue unsigned#123
Open
jdevalk wants to merge 1 commit into
Open
change(ard): drop the trust-manifest signature; publish the catalogue unsigned#123jdevalk wants to merge 1 commit into
jdevalk wants to merge 1 commit into
Conversation
… unsigned
The signature could not do the job it existed for, and no amount of tooling
around it would have changed that.
What it protected: three static fields — `identity`, `identityType`,
`privacyPolicyUrl`. What verified it: a JWK Set at /.well-known/jwks.json, on
the same origin as the catalogue it vouched for. Anyone able to rewrite
ai-catalog.json could rewrite jwks.json in the same breath, substitute their own
key, and produce a manifest that verifies perfectly. For a static site the
origin IS the threat model, so the signature folded to exactly the compromise it
was meant to detect.
It also covered host.trustManifest only, not `entries` — documented as a feature
("entries change without re-signing"), but `entries` is where the MCP and A2A
endpoint URLs live. Redirecting an agent to a hostile endpoint left the
signature intact and valid.
Against that: an offline key on one machine, a re-sign step on every catalogue
edit, a CI check, and a contributor footgun — an outside contributor editing
ai-catalog.json cannot re-sign it and would hit a CI failure they structurally
cannot fix. The AI Catalog spec makes the trust manifest an optional extension,
so removing it leaves a valid catalogue. TLS already proves the bytes came from
the domain.
Removed: host.trustManifest, public/.well-known/jwks.json,
scripts/sign-ard-catalog.mjs, the sign:ard / check:ard npm scripts, the CI step,
the jwks entry in the api-catalog Linkset and its _headers block, and the bold
"re-run sign:ard or the signature breaks" warning in CLAUDE.md. The
.ard-signing-key.json gitignore line stays, with a comment: a leftover local key
must never become committable.
The reasoning is now on the spec page, which is the point. Under the rule change
in #121 we no longer need to ship a signed manifest to have a page that
discusses signing, so the page says the useful thing instead: sign only when the
verifying key is resolvable independently of the signed document — DNSSEC, an
out-of-band pin, or infrastructure an origin compromise would not reach — and
note that a same-origin JWK Set is not one of those. Also flags the unsigned-
`entries` trap, in Common mistakes and in Verification.
Historical notes (ops/notes/ard-adoption.md, docs/okf-recon.md) get a dated
superseded banner rather than a rewrite; they are point-in-time records and
falsifying them would be worse than marking them.
Changelog: `changed` on agentic-resource-discovery. `updated` bumped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying specification-website with
|
| Latest commit: |
6c5f7d7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://35090129.specification-website.pages.dev |
| Branch Preview URL: | https://change-drop-ard-signing.specification-website.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The signature could not do the job it existed for, and no amount of tooling around it would have changed that.
What it protected: three static fields —
identity,identityType,privacyPolicyUrl.What verified it: a JWK Set at
/.well-known/jwks.json— on the same origin as the catalogue it vouched for. Anyone able to rewriteai-catalog.jsoncould rewritejwks.jsonin the same breath, substitute their own key, and produce a manifest that verifies perfectly. For a static site the origin is the threat model, so the signature folded to exactly the compromise it was meant to detect.It also covered
host.trustManifestonly, notentries— documented as a feature ("entries change without re-signing"). Butentriesis where the MCP and A2A endpoint URLs live. Redirecting an agent to a hostile endpoint left the signature intact and valid. We were paying to sign the boring part.Against that, the running cost: an offline key on one machine, a re-sign step on every catalogue edit, a CI check, and a contributor footgun — an outside contributor editing
ai-catalog.jsoncannot re-sign it, and would hit a CI failure they structurally cannot fix.The AI Catalog spec makes the trust manifest an optional extension, so removing it leaves a valid catalogue. TLS already proves the bytes came from the domain.
Removed
host.trustManifest·public/.well-known/jwks.json·scripts/sign-ard-catalog.mjs· thesign:ard/check:ardnpm scripts · the CI step · the jwks entry in the api-catalog Linkset and its_headersblock · the bold "re-runnpm run sign:ardor the signature breaks" warning in CLAUDE.md.The
.ard-signing-key.jsongitignore line stays, now with a comment explaining why: a leftover local key must never become committable.What replaces it
The reasoning, on the page — which is the point. Under the rule change in #121 we no longer need to ship a signed manifest in order to have a page that discusses signing, so the page now says the useful thing:
Plus the unsigned-
entriestrap, in both Common mistakes and Verification. Nobody else is writing this down, and it's the kind of thing an implementer gets wrong by default because signing feels like security.Notes
Historical docs (
ops/notes/ard-adoption.md,docs/okf-recon.md) get a dated superseded banner rather than a rewrite — they're point-in-time records and falsifying them would be worse than marking them.Changelog:
changedentry on agentic-resource-discovery,updatedbumped. This one clearly warrants an entry — the page's guidance genuinely reverses.Checks
npm run build✓ ·npm run check✓ (0 errors) ·npm run lint✓ ·npm run format:check✓ ·npm run check:skill✓ · catalogue still parses as valid JSON with 4 entries.If you ever want signing back
Only one variant is worth the machinery: publish the JWK thumbprint in a DNSSEC-signed TXT record — we already publish DNS-AID records and have a DNSSEC page, so the zone and the precedent both exist — and extend the signature to cover
entries. Signing in CI with a repo secret is not a middle ground: it fixes the ergonomics and none of the security.🤖 Generated with Claude Code