{
  "openapi": "3.1.0",
  "info": {
    "title": "CS2ED private canary origin",
    "version": "1.0.0",
    "description": "Private loopback origin BFF. Not a public partner API. The public Worker proxies these paths only when ORIGIN is bound; absent ORIGIN the Worker stays static-safe and fail-closed. Browser CSP connect-src is none."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:3001",
      "description": "Private origin. Not a public hostname."
    }
  ],
  "paths": {
    "/api/live": {
      "get": {
        "summary": "Process liveness",
        "description": "Unauthenticated process-only probe. Does not prove data-plane readiness.",
        "responses": {
          "200": {
            "description": "Origin process is up"
          }
        }
      }
    },
    "/api/ready": {
      "get": {
        "summary": "Authenticated data-plane readiness",
        "security": [{ "bearer": [] }],
        "description": "Boolean probe of the data-plane contract. No SQL from this product plane.",
        "responses": {
          "200": { "description": "Ready" },
          "401": { "description": "Unauthorized" },
          "503": { "description": "Unconfigured or not ready" }
        }
      }
    },
    "/api/canary/submit": {
      "post": {
        "summary": "Submit a canary parse workflow",
        "security": [{ "bearer": [] }],
        "description": "Caller match_identity is not treated as assigned identity. Acquisition receipt may be required by environment. Parser SUPPORTED_BUILDS empty blocks a complete chain even if this route is bound. Success includes presentJobSurface; accepted is queued, never a verified report.",
        "responses": {
          "200": { "description": "Campfire submit receipt with surface_state" },
          "401": { "description": "Unauthorized" },
          "400": { "description": "Rejected" }
        }
      }
    },
    "/api/canary/job": {
      "get": {
        "summary": "Read canary job lifecycle",
        "security": [{ "bearer": [] }],
        "description": "Campfire workflow status plus presentJobSurface. accepted or running past request_deadline is timeout, not parser_crash. Succeeded without confirmed publication is publishing, not ready.",
        "responses": {
          "200": { "description": "Job lifecycle with surface_state" },
          "401": { "description": "Unauthorized" }
        }
      }
    },
    "/api/canary/job/cancel": {
      "post": {
        "summary": "Cancel a canary job",
        "security": [{ "bearer": [] }],
        "description": "Campfire cancelParseWorkflow plus presentJobSurface.",
        "responses": {
          "200": { "description": "Cancel result with surface_state" }
        }
      }
    },
    "/api/canary/job/retry": {
      "post": {
        "summary": "Retry a canary job",
        "security": [{ "bearer": [] }],
        "description": "Campfire retryParseWorkflow plus presentJobSurface. SteamCloud acquire is not retryable after replay_expires_at.",
        "responses": {
          "200": { "description": "Retry result with surface_state" }
        }
      }
    },
    "/api/canary/report": {
      "get": {
        "summary": "Read a published canary report projection",
        "security": [{ "bearer": [] }],
        "description": "V1 retrieval checks run/source and non-empty revision fields. Unpublished or unbound reports are not returned. Fixtures are not substituted.",
        "responses": {
          "200": { "description": "Published projection" },
          "404": { "description": "Report not ready" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
