{
  "spec": "coderifts-proof-claims.v1",
  "scope": "The terminal blocks on https://coderifts.com/verify/ that a machine can run unattended, and what each one must produce. THE EXPECTED OUTPUT LIVES HERE, NOT IN THE HTML — the page renders a badge this file's runner writes, so a page can never say 'verified' about a run that disagreed with it.",

  "_why": "Ten blocks on /verify/ invite a reader to run a command and see a named result. Until 2026-09-23 nothing ran them. A proof nobody re-runs is a screenshot: it was true on the day it was pasted, and after that it is a claim about the past wearing the present tense.",

  "_measured": "Every expectation below was produced by running the command on 2026-09-23 and reading the result, not by copying the HTML. All ten ran keyless — no API key, no CI secret.",

  "_expect_kinds": {
    "json_fields": "parse stdout as JSON, then compare each dotted path to its value. Used where the response carries per-call fields (ts, receipt bytes, correlation ids) that MUST vary — pinning those would make the proof fail for being alive.",
    "contains": "every string must appear in stdout, in any order.",
    "line_count": "stdout must have exactly this many non-empty lines.",
    "outputs_agree": "the proof runs two commands and asserts their outputs are EQUAL TO EACH OTHER. No value is pinned here on purpose: the digest moves on a served-schema change with no source commit behind it, so a pinned digest would be a false failure, and the check that matters is that the two sources still agree."
  },

  "rate_limit": {
    "_measured": "2026-09-23, from live X-RateLimit headers and src/middleware/rateLimit.js in the app.",
    "anonymous_per_ip_per_minute": 30,
    "anonymous_per_ip_per_day": 50,
    "agent_endpoints_per_ip_per_minute": 60,
    "agent_endpoints_daily_cap": null,
    "agent_endpoints": ["/api/v1/demo", "/api/v1/public/preflight", "/api/v1/public/actionguard-check", "/api/v1/public/migraguard-check", "/api/v1/badge/agent-readiness", "/snippets"],
    "mcp_endpoint": "no X-RateLimit headers on /mcp — measured 2026-09-23, the limiter is not on that path",
    "capped_calls_per_run": 3,
    "verdict": "A DAILY run is inside every cap: 3 capped calls against 50/day and 30/minute per IP. The two /mcp calls are uncapped. ⚠ THE CAP IS PER IP AND CI RUNNERS SHARE ADDRESSES — a hosted runner can arrive with the day's budget partly spent by somebody else. That is why a 429 is recorded as SKIPPED with its reason and never as a failed proof: a rate limit is not a disagreement about what the surface does.",
    "if_it_ever_bites": "Move the run to an agent endpoint (no daily cap), or drop to weekly. Do NOT raise the cap to make a gate green."
  },

  "proofs": [
    {
      "id": "signed-decision",
      "article": "signed-decision",
      "title": "A signed decision, verified offline",
      "keyless": true,
      "steps": [
        "curl -sS -X POST https://app.coderifts.com/api/v1/action-verdict -H 'Content-Type: application/json' -d '{\"action_type\":\"tool_call\",\"tool\":{\"name\":\"get_customer\",\"capabilities\":[\"read\"]}}'"
      ],
      "post": "extract .chain_receipt into receipt.txt, then: node receipt-verifier/cli.js \"$(cat receipt.txt)\"",
      "expect": {
        "kind": "json_fields",
        "fields": {
          "valid": true,
          "status": "VERIFIED_CURRENT",
          "payload.v": 2,
          "payload.caller": "anon"
        }
      },
      "_not_pinned": "payload.ts is per-call and payload.kid rotates by design. Pinning either would make a live, correct run red."
    },
    {
      "id": "valid-not-authz",
      "article": "valid-not-authz",
      "title": "A valid signature is not authorization",
      "keyless": true,
      "steps": [
        "curl -sS -X POST https://app.coderifts.com/api/v1/verify-receipt -H 'Content-Type: application/json' -d \"{\\\"token\\\":\\\"$(cat receipt.txt)\\\"}\""
      ],
      "expect": {
        "kind": "json_fields",
        "fields": {
          "valid": true,
          "status": "VERIFIED_CURRENT",
          "currently_authorized": null
        }
      },
      "_the_point": "currently_authorized must be null — not false, not true. If it ever comes back a boolean from a token alone, this page's central claim has changed and the badge must say so."
    },
    {
      "id": "limits-as-data",
      "article": "limits-as-data",
      "title": "The limits, as data",
      "keyless": true,
      "steps": [
        "curl -sS https://coderifts.com/.well-known/coderifts.json"
      ],
      "expect": {
        "kind": "contains",
        "strings": [
          "The grant does not bind the canonical tool-call bytes",
          "delegation attenuation is not available",
          "No DSSE or in-toto envelope is emitted by any published artifact"
        ]
      },
      "_not_pinned": "the COUNT is check-limits-count.mjs's job and is derived there. This proof asserts the three hardest entries are still published, not how many there are."
    },
    {
      "id": "surface-selfcheck",
      "article": "surface-selfcheck",
      "title": "The tool text, two sources, one digest",
      "keyless": true,
      "steps": [
        "curl -sS -X POST https://app.coderifts.com/mcp -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' | canonical-digest",
        "curl -sS https://coderifts.com/.well-known/mcp/server-card.json | .surface.tools_sha256"
      ],
      "expect": { "kind": "outputs_agree" }
    },
    {
      "id": "unknown-method",
      "article": "unknown-method",
      "title": "An unknown method is refused, not guessed",
      "keyless": true,
      "steps": [
        "curl -sS -X POST https://app.coderifts.com/mcp -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"server/discover\"}'"
      ],
      "expect": {
        "kind": "json_fields",
        "fields": {
          "error.code": -32601,
          "error.message": "Method not found: server/discover"
        }
      }
    },
    {
      "id": "guarded-table",
      "article": "guarded-table",
      "title": "GUARDED_TOOL_TABLE",
      "keyless": true,
      "steps": ["npx --yes @coderifts/conformance --assurance GUARDED_TOOL_TABLE"],
      "expect": {
        "kind": "contains",
        "strings": ["GUARDED_TOOL_TABLE: COVERED / LIVE"]
      },
      "_not_pinned": "the vector count is in the release manifest's conformance block and moves with a profile change; COVERED / LIVE is the claim this page makes."
    },
    {
      "id": "one-grant",
      "article": "one-grant",
      "title": "ATOMIC_COMMIT",
      "keyless": true,
      "steps": ["npx --yes @coderifts/conformance --assurance ATOMIC_COMMIT"],
      "expect": {
        "kind": "contains",
        "strings": ["ATOMIC_COMMIT: COVERED / RECORDED"]
      }
    },
    {
      "id": "decision-branches",
      "article": "decision-branches",
      "title": "The reference subject passes",
      "keyless": true,
      "steps": ["npx --yes @coderifts/conformance --subject reference"],
      "expect": {
        "kind": "contains",
        "strings": ["reference profile=normative:", "0 failed"]
      }
    },
    {
      "id": "reproduce-evidence",
      "article": "reproduce-evidence",
      "title": "END_TO_END",
      "keyless": true,
      "steps": ["npx --yes @coderifts/conformance --assurance END_TO_END"],
      "expect": {
        "kind": "contains",
        "strings": ["END_TO_END: COVERED / RECORDED"]
      }
    },
    {
      "id": "analysis-is-not-permission",
      "article": "analysis-is-not-permission",
      "title": "Analysis is not permission",
      "keyless": true,
      "steps": [
        "curl -sS https://coderifts.com/examples/description-drift.json | curl -sS -X POST https://app.coderifts.com/api/v1/preflight -H 'Content-Type: application/json' -d @-"
      ],
      "expect": {
        "kind": "json_fields",
        "fields": {
          "analysis_outcome": "BREAKS_DETECTED",
          "may_execute": false,
          "authorization_effect": "NONE",
          "receipt_kind": "NONE",
          "verdict_fingerprint": "sha256:5096f53df0967e44ed7d6229c9f28ed7a68633beee2ab9cdd3a72a4ca006209c"
        }
      },
      "_pinned_on_purpose": "verdict_fingerprint IS pinned here. This is the one proof whose input is a fixed file we publish, so the verdict over it must be deterministic. If the fingerprint moves, either the analyser changed or the fixture did, and both are things a reader of this page should be told."
    }
  ]
}
