{
  "$type": "ConformanceProfile",
  "$id": "https://apis.ax/conformance/profile",
  "standard": "agent-first-api",
  "protocol": "https://apis.ax/axp",
  "version": "0.3.0",
  "verifier": "api.qa",
  "spec": "./apis-ax-standard.spec.json",
  "description": "Machine-readable mapping from each AXP (PROTOCOL.md) clause to at least one independent api.qa verification. Every RFC-2119 MUST clause maps to its OWN discriminating requirement (a specific api.qa check or a behavioral probe) — no MUST rides only a coarse aggregate, which tolerates its violation. Behavioral probes are resolved from the target's own card-declared probe manifest (agents.json `probes`, PROTOCOL.md Appendix A.3) and fail closed when the manifest is absent or invalid. Conformance is judged by api.qa, held outside the building fleet's write access. A Listing is admitted to the apis.ax catalog iff it passes the pinned spec.",
  "clauses": [
    {
      "id": "openapi-3-1",
      "clause": 1,
      "normative": "MUST",
      "requirement": "Publish a valid OpenAPI contract whose declared version is 3.1.x and which declares at least one operation, describing every callable operation and its typed responses.",
      "verifiedBy": { "verifier": "api.qa", "check": "openapi", "pinnedRequirement": "openapi-valid" }
    },
    {
      "id": "llms-txt",
      "clause": 2,
      "normative": "MUST",
      "requirement": "Serve llms.txt at /llms.txt as agent-actionable markdown, not HTML.",
      "verifiedBy": { "verifier": "api.qa", "check": "llms-txt", "pinnedRequirement": "llms-present" }
    },
    {
      "id": "machine-legible",
      "clause": 3,
      "normative": "MUST",
      "requirement": "Answer machine-legible (JSON for typed bodies, markdown for docs) to EVERY client: both Accept: */* and Accept: text/html get non-HTML on the home and typed bodies — HTML is a page concern, never an API representation (ADR-0018).",
      "verifiedBy": { "verifier": "api.qa", "check": "machine-legible-home", "pinnedRequirement": "check-machine-legible-home" }
    },
    {
      "id": "typed-errors",
      "clause": 4,
      "normative": "MUST",
      "requirement": "Return typed BLOCKED/EMPTY outcomes and never fake success: EMPTY carries an explicit type, BLOCKED is non-2xx, no 200 success envelope for a real BLOCKED/EMPTY. Verified across the card-declared known-empty and known-forbidden probes (at least two distinct of each, on pathnames also observed answering 200 OK in the same run), so a dedicated always-EMPTY/always-BLOCKED decoy endpoint cannot satisfy honesty — the probed path must demonstrably branch on its query.",
      "verifiedBy": { "verifier": "api.qa", "check": "claims-honesty", "pinnedRequirement": ["typed-empty", "typed-blocked"] }
    },
    {
      "id": "hard-ceiling",
      "clause": 5,
      "normative": "MUST",
      "requirement": "Every API declares a Pricing Document (probes.pricing, model free|metered) so worst-case exposure is known before the first call; a free API is admissible by declaring model:free. A metered API additionally publishes a hard-ceiling strictly greater than zero, declares monetization.offers plus a monetization.probe that answers payment boundaries as typed 402 OFFER bodies, stops a request at a verifier-derived amount above the observed ceiling with a 402 OFFER re-authorization boundary rather than metering it silently, and serves (HTTP 200) the same operation at verifier-derived amounts of zero and half the ceiling — a wall at every amount is theater. The metering requirements apply only when model:metered (appliesWhen), so a free API passes them as not applicable.",
      "verifiedBy": { "verifier": "api.qa", "check": "offers-402", "pinnedRequirement": ["check-offers-402", "pricing-declared", "hard-ceiling-positive", "hard-ceiling-enforced", "hard-ceiling-below", "hard-ceiling-not-premature"] }
    },
    {
      "id": "resolver-addressable",
      "clause": 6,
      "normative": "MUST",
      "requirement": "Have a resolver-addressable home: a resolvable capability card at /.well-known/agents.json that names the surface and its interfaces (interfaces.http and/or interfaces.mcp, non-empty), cross-links its sibling surfaces (llms.txt, agents.json, and the OpenAPI contract mutually reference each other), and carries a valid AXP probe manifest (same-origin, GET-only, contract-declared non-templated paths) plus the monetization.probe declaration.",
      "verifiedBy": { "verifier": "api.qa", "check": "agents-json", "pinnedRequirement": ["check-agents-json", "check-card-interfaces-linked", "agents-present", "probe-manifest-valid"] }
    },
    {
      "id": "keyless-first-value",
      "clause": 7,
      "normative": "MUST",
      "requirement": "Deliver first value with no key, no signup, no account: the card-declared keyless probe answers 200 with a typed OK envelope to an anonymous agent on first contact.",
      "verifiedBy": { "verifier": "api.qa", "check": "keyless-flow", "pinnedRequirement": ["check-keyless-flow", "keyless-first-value"] }
    }
  ]
}
