Use this before you take live traffic and again after any change to keys, terms or account handling. It is a checklist, not a second specification; each item links to the rule or the guide.
Transport and discovery
-
GET /.well-known/agent-signup.jsonreturns200,application/json, no redirect and no authentication. - The origin is HTTPS.
localhostis development only. -
Cache-Controlispublic, max-age=60or another value within the 300-second maximum. -
Access-Control-Allow-Origin: *is set where browser inspectors need it. - The body is under 1 MiB and contains no secrets, internal hostnames or personal data.
- Unsupported deployments return
404or410, not401or403. -
issuer_allowlistcontains exact origins with no path, query, fragment or wildcard. - The validator passes in CI or in a documented manual step.
Terms lifecycle
-
terms.textis the complete agreement the agent accepts, not a summary. -
terms.sha256is over the exact UTF-8 bytes and was recomputed after the last edit. -
terms.versionchanges whenever the text changes materially. -
terms.urlserves the same text to a human and is on a stable host. - Text, hash, version and URL ship atomically.
- Any grace period for in-flight assertions is bounded and documented outside discovery.
- A stale hash returns
409 tos_hash_mismatch; it is never accepted silently.
Assertion verification
- Signature verification uses the issuer's
/.well-known/jwks.json, not ajku/x5uheader. -
algisEdDSA, thekidselects the key andtypisagent-id+jwt. -
issis compared against the allowlist exactly. -
audis compared against the published audience. -
expis enforced with at most 60 seconds of clock skew. - Assertion lifetime is capped at five minutes.
-
delegation.scopescovers everyrequired_scopesentry. -
human.verifiedistrue. -
delegation.accepted_rp_tos_hashequals the current terms hash. - A repeated
jtiin the same context resolves; a conflicting one isassertion_replayed.
Keys, attestation and rotation
- You know that the receipt is signed by your RP key, named by
service.key_idand present in the exact attestation. The broker does not sign v1.2 receipts. - The RP private key is in a secret store, never in the repository, logs or a build artifact. It has an owner, a rotation date and a compromise procedure.
- The attestation is renewed on a 12-hour target against a 24-hour expiry
with 60-second skew. Serve the cached attestation until
exp; omit it after expiry (the provider becomes unverified, not invalid). - The exact attestation that contained the receipt key is retained for every receipt, and Contract F receives that exact JWS. Never substitute the current attestation.
- Key rotation uses the 30-day overlap; revocation removes the key from new attestations while old receipts remain verifiable through the snapshot.
-
/.well-known/agent-broker.jsonmetadata and the signedattestation_status_uriare implemented if you operate a broker; caching is at most 1 hour for metadata and 5 minutes for status. - If you claim verification in the registry, the entry records
broker,level,attestation_jti,checked_at, andstatus:"active"from a live check. The badge is a snapshot; onlyactivegets it.
Accounts, replay and credentials
- Account keys follow
(iss, human.id)or(iss, agent.id)and are namespaced by issuer. - A
jtican be used for one account creation only; a unique constraint backs the check. - A resolve returns no credential and sends no duplicate welcome or legal mail.
- Credentials are returned only on creation and are never stored in the receipt, logs or broker.
- A credential recovery path exists in the context guide.
- Rate limits protect signup and return
429 rate_limitedwith an honest delay.
Receipts and Contract F
- The receipt header is
alg: EdDSA,typ: agent-signup-receipt+jwt, andkidequalsservice.key_id. - The payload has no
exp;iatandsigned_up_atfall inside the named attestation's[iat, exp]window. -
issequalsservice.originand the attestationrp.origin;audis the broker issuer. -
service.attestation_jtinames the exact attestation that contained the key;service.audienceequals the attestationrp.audience. - Contract F sends
{signup_token, rp_attestation}with both fields; Tier 2 is the fallback. A missing exact attestation returnsattestation_unavailable; a transient outage is retryablerp_broker_unavailable. - A duplicate
jtiwith the same body dedupes; a different body issignup_conflict. A different account for the same soft key is flagged, not overwritten. - A self-report is only used for an RP that issued no receipt and is
visibly weaker (
agent_self_reported).
Logging and retention
- Logs record the assertion
jti,agent.id,human.id, account id, terms version and hash, andsigned_up_at. - Logs do not record provider credentials, raw assertions beyond the audit window, or unnecessary personal data.
- Error monitoring groups by stable code, not by prose.
- Retention is documented and follows your legal obligations.
- A request id or trace id links the agent request to the account event.
Context and abuse
-
context.urlstays on the signup endpoint's registrable domain. -
context.sha256matches the bytes served and is updated in the same deploy as the guide. - The guide contains no credentials and no protocol fields.
- The broker is never asked to fetch the guide.
- Abuse reporting uses
{rp_attestation, report}with a five-minute JWS and a current attestation. The legacy{agent_id, reporter_service, reason}body is gone. - You understand that a verified, receipt-linked report may apply a protective suspension pending review; an unverified report opens a case and does not suspend.
- A human report about a provider uses the portal path, not D.2.
Abuse, support and incidents
-
contactin discovery is monitored and reaches a human. - The abuse reporting path is tested with a synthetic signed report and the exact current attestation.
- Support knows the difference between a protocol error, a broker error and a vendor API error.
- An incident plan covers: disable signup, rotate keys or revoke the attestation, invalidate credentials, contact the broker, update the registry.
- The provider does not retaliate automatically against an agent; revocation and account action are separate decisions.
- Known limits are stated to customers:
human.verifiedis email verification, verification is identity not safety, revocation does not delete your account, and the protocol does not prevent abuse.
Test plan
- A staging discovery URL exists and is not in the registry.
- Synthetic assertions cover every row in Verify assertions.
- The optional credential is tested absent, valid
domain, validentity, expired, invalid, untrusted, and unavailable. - A create and a resolve are both exercised, including the no-credential rule.
- The validator runs against staging before release, once without and once with
--require-attestation. - Contract F is exercised with the exact historical attestation and with a renewed current attestation (must not substitute).
- A terms change is rehearsed end to end, including
tos_hash_mismatch. - A guide change is rehearsed, including the hash update.
Next
- Stable error codes: the envelope and retry rules.
- Abuse reporting: Contract D.2.
- Troubleshooting: symptom, cause and fix.