Summary
Today POST /resources does static validation only (src/validate.ts):
- https-only host + SSRF guards (no IP literals / localhost / internal TLDs, fixed well-known path, no redirects, timeout, 64 KB cap)
issuer === https://{host} (anti-spoof)
description present + length-bounded
access_mode is a valid enum or absent (defaults to agent-token)
That proves the host serves a well-formed aauth-resource.json and controls its own issuer — but not that it's a working AAuth resource.
Ask
Add a deeper verification pass that checks everything an AAuth resource needs is present and actually responds. Split into two tiers:
Lint (static, hard-fail on accept)
jwks_uri present + fetchable + contains ≥1 valid key (e.g. OKP/Ed25519) when the resource issues tokens / makes signed calls
- If
authorization_endpoint is declared, it's an https URL on the same origin
- If
r3_vocabularies is declared, each referenced doc (e.g. openapi.json) is fetchable and parses
logo_uri (if present) is https and reachable (soft)
Probe (live calls, recorded as health — don't hard-fail, probes can be flaky)
- Unsigned request to the resource → expect
401 + Accept-Signature (confirms it actually speaks AAuth)
- Optionally a signed agent-token call to confirm behavior matches the declared
access_mode
- Record per-check pass/fail + last-checked timestamp on the entry (e.g.
health: { checks, last_checked })
Where it runs
- On
POST /resources: lint gates acceptance; probe results attached to the new entry.
- In
reconcile() re-validation: re-run lint + probe to keep health fresh and flag resources that have gone bad (beyond the current 404/410 prune).
Notes
- Keep all live calls inside the existing SSRF envelope (timeouts, no redirects, size caps).
- Surface granular errors (per-check) in the
422 response, like the current errors[].
Summary
Today
POST /resourcesdoes static validation only (src/validate.ts):issuer === https://{host}(anti-spoof)descriptionpresent + length-boundedaccess_modeis a valid enum or absent (defaults toagent-token)That proves the host serves a well-formed
aauth-resource.jsonand controls its own issuer — but not that it's a working AAuth resource.Ask
Add a deeper verification pass that checks everything an AAuth resource needs is present and actually responds. Split into two tiers:
Lint (static, hard-fail on accept)
jwks_uripresent + fetchable + contains ≥1 valid key (e.g. OKP/Ed25519) when the resource issues tokens / makes signed callsauthorization_endpointis declared, it's an https URL on the same originr3_vocabulariesis declared, each referenced doc (e.g.openapi.json) is fetchable and parseslogo_uri(if present) is https and reachable (soft)Probe (live calls, recorded as health — don't hard-fail, probes can be flaky)
401 + Accept-Signature(confirms it actually speaks AAuth)access_modehealth: { checks, last_checked })Where it runs
POST /resources: lint gates acceptance; probe results attached to the new entry.reconcile()re-validation: re-run lint + probe to keephealthfresh and flag resources that have gone bad (beyond the current 404/410 prune).Notes
422response, like the currenterrors[].