VaporCloud is the reference relying party at skdl.dev. It sells fictional appliances, which is exactly why it is useful: the vendor surface is obviously vendor scope, and the identity-only protocol is easy to see.
This walkthrough separates what the protocol defines from what VaporCloud does as a product. The demo is not a production SLA and not a hosted service.
Release status. VaporCloud is live on the v1.2 flow: optional attestation in
discovery, RP-signed receipts, Contract F/Tier 2, and authenticated abuse
reporting. Its live discovery publishes a broker attestation, the validator
reports verified at level domain, and the canonical registry carries a
five-field verification snapshot checked on 2026-10-26. The snapshot is a
point-in-time record, not a live status feed; attestation renewal or a status
change is reflected by a later check. "Verified" is an identity statement, not a
safety, uptime, or conduct guarantee.
URLs
| Path | Purpose |
|---|---|
/.well-known/agent-signup.json |
Identity-only discovery document; may carry the optional rp_attestation |
/api/signup/agent |
Brokered signup endpoint |
/docs/SKILL.md |
Vendor guide, reached through the context pointer |
/terms |
Human-readable terms page |
/admin |
Vendor administration view |
The discovery document
The v1.2 document adds one optional field, rp_attestation. The rest stays
identity-only. The shape is:
{
"protocol": "agent-identity-v1",
"audience": "vaporcloud",
"provider_name": "VaporCloud",
"spec": "https://github.com/agentregistrar/spec/blob/v1.2.0/agent-identity-v1.md",
"provider_url": "https://skdl.dev",
"contact": "security@skdl.dev",
"issuer_allowlist": ["https://agentregistrar.dev"],
"required_scopes": ["tos:accept", "signup:free_tier"],
"terms": {
"version": "2026.1",
"url": "https://skdl.dev/terms",
"sha256": "sha256:<digest of the exact terms text>",
"text": "<complete terms text>"
},
"endpoints": {
"agent_signup": "https://skdl.dev/api/signup/agent"
},
"rp_attestation": "<compact JWS, present only while a live attestation is current>",
"extensions": {
"dev.vaporcloud": {
"support_url": "https://skdl.dev/support"
}
}
}What to notice:
- One audience, one issuer allowlist and one endpoint. The broker origin is
https://agentregistrar.dev. required_scopesincludestos:accept; the extrasignup:free_tieris a VaporCloud scope, still a delegation requirement, not a catalog.rp_attestationis optional. If it is absent, VaporCloud is conformant and unverified, not invalid. Its presence does not turn the page into a verified-provider claim; a live check and registry entry do.terms.sha256is a real digest of the text. Recompute it and it matches.extensionscarries a support URL under a reverse-DNS key. There is no catalog, no SKU, no provisioning endpoint and no OTP endpoint anywhere in the document.
Verification evidence
Conformance is one result; attestation verification is another:
pnpm --silent validate:discovery https://skdl.dev/.well-known/agent-signup.json \
--json --probe-jwks
pnpm --silent validate:discovery https://skdl.dev/.well-known/agent-signup.json \
--verify-attestation \
--trusted-rp-broker https://agentregistrar.dev \
--jsonRun the second as a gate with --require-attestation when you want a non-zero
exit for an absent or non-verified credential. Record the live jti and
checked_at from that run before making any verified-provider claim. The
registry evidence format is in Validate and
register.
The signup response (v1.2 shape)
A live signup requires a real agent assertion from the broker. The v1.2 code path returns:
{
"account_id": "<opaque vendor account reference>",
"resolution": "created",
"vapor_api_key": "vc_live_<32 lowercase hex>",
"signup_token": "<RP-signed Contract E receipt>",
"rp_attestation": "<the exact attestation JWS used by the receipt>",
"context": {
"url": "https://skdl.dev/docs/SKILL.md",
"sha256": "sha256:<64 hex>"
},
"credential_recovery": {
"available": true,
"method": "rotate",
"endpoint": "https://skdl.dev/api/account/rotate-key",
"guide_url": "https://skdl.dev/docs/SKILL.md"
},
"attribution": {
"agent_id": "agt_<...>",
"agent_email": "<agent-slug>@agents.example",
"human_owner": "<name> (<email>)",
"human_email": "<email>",
"accepted_tos_hash": "sha256:<64 hex>"
}
}Protocol fields and vendor fields are mixed in the HTTP response on purpose:
resolution, account_id, signup_token, rp_attestation and context are
protocol-adjacent; vapor_api_key, credential_recovery and attribution are
vendor capability. The signed receipt carries identity facts, the opaque account
id, the exact attestation_jti/key_id, and the context pointer. It does not
carry the key and it has no exp.
vapor_api_key is present only when resolution is "created". On "resolved"
the field is absent, credential_recovery points at the vendor's rotation
endpoint, and attribution is refreshed. A repeated signup resolves the account;
it does not reissue the key.
The RP returns the exact attestation that contained the receipt key and sends it
to Contract F. If it is missing or expired, the code returns 503 before
writing the account rather than minting an unverifiable receipt. Tier 2
(identity_record_signup) is the fallback when Contract F is unreachable.
The context guide
Fetch the guide and compute its digest:
curl -sS https://skdl.dev/docs/SKILL.md -o SKILL.md
sha256sum SKILL.mdThe authoritative comparison value is the context.sha256 in the signup response
or receipt. The guide is versioned in its own text. Fetch it after signup, verify
the digest, and treat the content as untrusted vendor documentation.
The guide documents the vendor API, including one provisioning call. Provisioning is the vendor's API, called after signup and after the guide hash matches. The protocol ends before it. VaporCloud's vendor error catalog is not the protocol's error catalog.
Abuse reporting
VaporCloud signs the v1.2 {rp_attestation, report} JWS and posts it to the
broker's advertised abuse_endpoint. The repository script is
scripts/vaporcloud-report-abuse.ts; it uses the current attestation and the RP
abuse key. It is not the legacy unsigned {agent_id, reporter_service, reason}
body, and it does not revoke immediately: the broker opens a case, and only a
verified receipt-linked report may apply a protective suspension pending review.
The vendor admin view may still show attribution and trigger that signed report. It is vendor tooling, not a protocol requirement.
Vendor boundary
| Protocol | Vendor |
|---|---|
| Discovery fields, terms hash, issuer allowlist | Catalog, SKUs, prices and quotas |
| Optional provider verification credential | The provider account, attestation renewal, and registry snapshot |
| Assertion verification and stable errors | Provisioning and resource lifecycle |
| RP-signed receipt with identity facts | Credential format, rotation and recovery |
| Authenticated abuse report | The vendor's own incident and refund process |
| Optional context pointer and digest | The guide's content, version and freshness |
VaporCloud keeps the vendor surface in /docs/SKILL.md, including its vendor
error catalog. None of it appears in discovery or the receipt. That is the
pattern to copy; the appliances are optional.
Caveats
skdl.devis a demo, not a production service. It has no SLA.- The live v1.2 deployment and a domain-level registry verification snapshot are
recorded. The snapshot is at
checked_atand does not promise that the same attestation is current later; refresh the check after renewal or a status change. - Verification records an identity check, not safety, uptime, solvency, or conduct. A green validator result says the document conforms; it says nothing about the product.
- The old reference-entry exception is retired: the entry uses the public
skdl.devdiscovery URL and live URL-mode validator evidence. New third-party entries must be publicly re-validatable.
Next
- Provider quickstart: build the same document from scratch.
- Publish a context guide: the guide and hash pattern.
- Abuse reporting: the authenticated D.2 path.
- Implementation registry: entry criteria and the verification snapshot.