{
  "openapi": "3.0.0",
  "info": {
    "title": "CUIT SaaS API",
    "version": "0.1.0",
    "description": "The CUIT data plane API. Customer recorders POST captured sessions; the warehouse auto-generates regression specs; insights expose flake rate and similar-session search. Used by the @cuit-saas/mcp MCP server, the @cuit/cli (future), and direct REST integrations.",
    "contact": {
      "name": "CUIT",
      "url": "https://complex-ui-tester.vercel.app"
    },
    "license": {
      "name": "Proprietary — see speechlabinc/cuit-saas README"
    }
  },
  "servers": [
    {
      "url": "https://cuit-saas-pilot.fly.dev",
      "description": "Pilot — LIVE today on Fly.io (IAD) + Neon (us-east-1)"
    },
    {
      "url": "http://localhost:7710",
      "description": "Local development"
    },
    {
      "url": "https://api.cuit.dev",
      "description": "Production — sprint week 8 (AWS ECS Fargate + Aurora)"
    }
  ],
  "tags": [
    {
      "name": "ops",
      "description": "Health and operations endpoints (no auth)"
    },
    {
      "name": "admin",
      "description": "Tenant + token management. Admin or tenant-bearer auth."
    },
    {
      "name": "sessions",
      "description": "Capture session upload and retrieval"
    },
    {
      "name": "specs",
      "description": "Generated regression specs"
    },
    {
      "name": "runs",
      "description": "Spec executions against customer URLs"
    },
    {
      "name": "instrument",
      "description": "App-shape detection and instrumentation proposals (powers /cuit-instrument skill)"
    },
    {
      "name": "insights",
      "description": "Per-tenant analytics (flake rate, bug-class distribution)"
    },
    {
      "name": "billing",
      "description": "Usage stats and Stripe subscription details"
    },
    {
      "name": "public",
      "description": "Unauthenticated endpoints — no bearer token required"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Per-tenant bearer token. Issued by the cuit-saas admin during onboarding. Pass as `Authorization: Bearer <token>`."
      },
      "adminAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "CUIT admin bearer token. Issued by the CUIT operations team for tenant management. Customers do not have this."
      }
    },
    "schemas": {
      "SessionUploadResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant": {
            "type": "string"
          },
          "event_count": {
            "type": "integer"
          },
          "spec_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid"
          },
          "confidence": {
            "type": "number",
            "nullable": true,
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "id",
          "tenant",
          "event_count",
          "spec_id",
          "confidence"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "issues": {
            "type": "array",
            "items": {
              "nullable": true
            }
          }
        },
        "required": [
          "error"
        ]
      },
      "SessionEvent": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer",
            "example": 7
          },
          "vendor": {
            "type": "string",
            "example": "cuit"
          },
          "vendorEventId": {
            "type": "string",
            "example": "tur-001-p-10"
          },
          "ts": {
            "type": "number",
            "example": 1200
          },
          "wallClock": {
            "type": "number",
            "example": 1748952001200
          },
          "type": {
            "type": "string",
            "example": "pointer"
          }
        },
        "required": [
          "seq",
          "vendor",
          "vendorEventId",
          "ts",
          "wallClock",
          "type"
        ]
      },
      "SessionUpload": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "minLength": 1,
            "example": "tur-live-1717459200000"
          },
          "vendor": {
            "type": "string",
            "enum": [
              "cuit",
              "jam",
              "logrocket",
              "sentry-replay",
              "fullstory",
              "datadog-rum"
            ],
            "example": "cuit"
          },
          "createdAt": {
            "type": "number"
          },
          "url": {
            "type": "string",
            "example": "http://localhost:3000/projects/abc?cuitRecorder=1"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SessionEvent"
            },
            "minItems": 1
          },
          "gitSha": {
            "type": "string",
            "example": "abc1234"
          },
          "gitBranch": {
            "type": "string",
            "example": "developNoWaveFormFinal"
          },
          "capturedByUserId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "sessionId",
          "vendor",
          "url",
          "events"
        ]
      },
      "SessionListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "session_id": {
            "type": "string"
          },
          "vendor": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "event_count": {
            "type": "integer"
          },
          "pointer_count": {
            "type": "integer"
          },
          "snapshot_count": {
            "type": "integer"
          },
          "git_sha": {
            "type": "string",
            "nullable": true
          },
          "git_branch": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "session_id",
          "vendor",
          "url",
          "event_count",
          "pointer_count",
          "snapshot_count",
          "git_sha",
          "git_branch",
          "created_at"
        ]
      },
      "SessionListResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "string"
          },
          "sessions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SessionListItem"
            }
          },
          "count": {
            "type": "integer"
          }
        },
        "required": [
          "tenant",
          "sessions",
          "count"
        ]
      },
      "SpecListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "session_id": {
            "type": "string",
            "format": "uuid"
          },
          "model_version": {
            "type": "string"
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "auto_pr_eligible": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "session_id",
          "model_version",
          "confidence",
          "auto_pr_eligible",
          "created_at"
        ]
      },
      "FlakeRateResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "string"
          },
          "window": {
            "type": "string"
          },
          "flake_rates": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "spec_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "runs": {
                  "type": "integer"
                },
                "reds": {
                  "type": "integer"
                }
              },
              "required": [
                "spec_id",
                "runs",
                "reds"
              ]
            }
          }
        },
        "required": [
          "tenant",
          "window",
          "flake_rates"
        ]
      },
      "Tenant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "tier": {
            "type": "string",
            "enum": [
              "team",
              "business",
              "enterprise"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          }
        },
        "required": [
          "id",
          "slug",
          "display_name",
          "tier",
          "created_at",
          "settings"
        ]
      },
      "TokenIssueResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Plaintext bearer token. Shown ONCE; we store only a hash. Save it now.",
            "example": "cuit_tk_live_8f9a3c2e1b..."
          },
          "token_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "token",
          "token_id",
          "label",
          "created_at",
          "expires_at"
        ]
      },
      "TenantCreateRequest": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "minLength": 2,
            "maxLength": 64,
            "example": "acme-corp"
          },
          "display_name": {
            "type": "string",
            "minLength": 1,
            "example": "Acme Corp"
          },
          "tier": {
            "type": "string",
            "enum": [
              "team",
              "business",
              "enterprise"
            ],
            "example": "business"
          },
          "pii_redaction": {
            "type": "boolean",
            "default": true
          },
          "retention_days": {
            "type": "integer",
            "minimum": 30,
            "maximum": 3650,
            "default": 365
          }
        },
        "required": [
          "slug",
          "display_name",
          "tier"
        ]
      },
      "TokenIssueRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "example": "github-actions-ci"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "example": "2027-01-01T00:00:00Z"
          }
        },
        "required": [
          "label"
        ]
      },
      "Primitive": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "goto",
              "setClock",
              "getStateSnapshot",
              "dispatchDrag",
              "dispatchResize",
              "dispatchKey",
              "dispatchScroll",
              "assertStateEquals",
              "assertStateMatches"
            ]
          }
        },
        "required": [
          "kind"
        ]
      },
      "SpecDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "session_id": {
            "type": "string",
            "format": "uuid"
          },
          "model_version": {
            "type": "string"
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "auto_pr_eligible": {
            "type": "boolean"
          },
          "primitives": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Primitive"
            }
          },
          "serialized": {
            "type": "string",
            "description": "The rendered .spec.ts source code."
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "session_id",
          "model_version",
          "confidence",
          "auto_pr_eligible",
          "primitives",
          "serialized",
          "created_at"
        ]
      },
      "SpecGenerateRequest": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "format": "uuid",
            "description": "Existing session UUID OR session payload below."
          },
          "session": {
            "$ref": "#/components/schemas/SessionUpload"
          },
          "model_tier": {
            "type": "string",
            "enum": [
              "rule-based",
              "haiku",
              "sonnet",
              "opus",
              "auto"
            ],
            "default": "auto"
          },
          "force_regenerate": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "StepAnnotation": {
        "type": "object",
        "properties": {
          "step_index": {
            "type": "integer"
          },
          "primitive": {
            "$ref": "#/components/schemas/Primitive"
          },
          "ts_ms": {
            "type": "number"
          },
          "state_snapshot": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          },
          "pointer_event": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            }
          }
        },
        "required": [
          "step_index",
          "primitive",
          "ts_ms"
        ]
      },
      "RunResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "spec_id": {
            "type": "string",
            "format": "uuid"
          },
          "outcome": {
            "type": "string",
            "enum": [
              "red",
              "green",
              "error"
            ]
          },
          "browser": {
            "type": "string"
          },
          "duration_ms": {
            "type": "integer"
          },
          "git_sha_at_run": {
            "type": "string",
            "nullable": true
          },
          "is_flake": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          },
          "state_at_assertion": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "nullable": true
            }
          },
          "failed_at_primitive": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Primitive"
              },
              {
                "nullable": true,
                "description": "When outcome=red: the harness primitive whose assertion failed."
              }
            ]
          },
          "last_snapshot": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "nullable": true
            },
            "description": "When outcome=red: the state snapshot at the moment of failure."
          },
          "preceding_events": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "nullable": true
              }
            },
            "description": "When outcome=red: the last N events before failure for context."
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StepAnnotation"
            }
          }
        },
        "required": [
          "id",
          "spec_id",
          "outcome",
          "browser",
          "duration_ms",
          "git_sha_at_run",
          "is_flake",
          "created_at"
        ]
      },
      "RunRequest": {
        "type": "object",
        "properties": {
          "target_url": {
            "type": "string",
            "format": "uri",
            "example": "http://localhost:3000/projects/abc?cuitRecorder=1"
          },
          "browser": {
            "type": "string",
            "enum": [
              "chromium",
              "firefox",
              "webkit",
              "jsdom"
            ],
            "default": "chromium"
          },
          "expected_outcome": {
            "type": "string",
            "enum": [
              "red",
              "green",
              "either"
            ],
            "default": "either"
          }
        },
        "required": [
          "target_url"
        ]
      },
      "SimilarSessionsResponse": {
        "type": "object",
        "properties": {
          "reference_session_id": {
            "type": "string",
            "format": "uuid"
          },
          "threshold": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "similar": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "session_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "cosine_similarity": {
                  "type": "number"
                },
                "created_at": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                }
              },
              "required": [
                "session_id",
                "cosine_similarity",
                "created_at",
                "url"
              ]
            }
          }
        },
        "required": [
          "reference_session_id",
          "threshold",
          "similar"
        ]
      },
      "BugClassDistributionResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "string"
          },
          "window": {
            "type": "string"
          },
          "classes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "most_recent_at": {
                  "type": "string"
                },
                "example_spec_id": {
                  "type": "string",
                  "nullable": true,
                  "format": "uuid"
                }
              },
              "required": [
                "label",
                "count",
                "most_recent_at",
                "example_spec_id"
              ]
            }
          }
        },
        "required": [
          "tenant",
          "window",
          "classes"
        ]
      },
      "AppShapeResponse": {
        "type": "object",
        "properties": {
          "framework": {
            "type": "string",
            "enum": [
              "next.js",
              "vite",
              "cra",
              "remix",
              "astro",
              "sveltekit",
              "unknown"
            ]
          },
          "router": {
            "type": "string",
            "nullable": true
          },
          "state_libs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ui_libs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "test_runner": {
            "type": "string",
            "nullable": true
          },
          "pkg_manager": {
            "type": "string",
            "enum": [
              "pnpm",
              "npm",
              "yarn",
              "bun"
            ]
          },
          "selectors_in_use": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "candidate_state_files": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "candidate_root_files": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "framework",
          "router",
          "state_libs",
          "ui_libs",
          "test_runner",
          "pkg_manager",
          "selectors_in_use",
          "candidate_state_files",
          "candidate_root_files"
        ]
      },
      "InstrumentationOperation": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "create",
              "edit",
              "noop"
            ]
          },
          "file": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "before": {
            "type": "string"
          },
          "after": {
            "type": "string"
          }
        },
        "required": [
          "action",
          "file"
        ]
      },
      "InstrumentationProposal": {
        "type": "object",
        "properties": {
          "operations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstrumentationOperation"
            }
          },
          "npm_dependencies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "github_actions_secrets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "estimated_minutes": {
            "type": "integer"
          },
          "rationale": {
            "type": "string"
          }
        },
        "required": [
          "operations",
          "npm_dependencies",
          "github_actions_secrets",
          "estimated_minutes",
          "rationale"
        ]
      },
      "BillingUsageResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "string"
          },
          "period_start": {
            "type": "string"
          },
          "period_end": {
            "type": "string"
          },
          "seats_active": {
            "type": "integer"
          },
          "sessions_uploaded": {
            "type": "integer"
          },
          "specs_generated": {
            "type": "integer"
          },
          "specs_run": {
            "type": "integer"
          },
          "inference_tokens": {
            "type": "integer"
          },
          "estimated_cost_usd": {
            "type": "number"
          },
          "tier": {
            "type": "string",
            "enum": [
              "team",
              "business",
              "enterprise"
            ]
          }
        },
        "required": [
          "tenant",
          "period_start",
          "period_end",
          "seats_active",
          "sessions_uploaded",
          "specs_generated",
          "specs_run",
          "inference_tokens",
          "estimated_cost_usd",
          "tier"
        ]
      },
      "SubscriptionResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "string"
          },
          "stripe_subscription_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "past_due",
              "canceled",
              "trialing"
            ]
          },
          "tier": {
            "type": "string",
            "enum": [
              "team",
              "business",
              "enterprise"
            ]
          },
          "current_period_end": {
            "type": "string"
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "customer_portal_url": {
            "type": "string"
          }
        },
        "required": [
          "tenant",
          "stripe_subscription_id",
          "status",
          "tier",
          "current_period_end",
          "cancel_at_period_end",
          "customer_portal_url"
        ]
      },
      "StripeWebhookBody": {
        "type": "object",
        "properties": {}
      },
      "PublicSignupTenant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "tier": {
            "type": "string",
            "enum": [
              "team"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "properties": {
              "pii_redaction": {
                "type": "boolean"
              },
              "retention_days": {
                "type": "integer"
              }
            },
            "required": [
              "pii_redaction",
              "retention_days"
            ]
          }
        },
        "required": [
          "id",
          "slug",
          "display_name",
          "tier",
          "created_at",
          "settings"
        ]
      },
      "PublicSignupToken": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Plaintext bearer token. Shown ONCE; store it now.",
            "example": "cuit_tk_a1b2c3d4e5f6..."
          },
          "token_prefix": {
            "type": "string",
            "example": "cuit_tk_a1b2"
          },
          "label": {
            "type": "string",
            "enum": [
              "self-signup"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "expires_at": {
            "nullable": true
          }
        },
        "required": [
          "token",
          "token_prefix",
          "label",
          "created_at",
          "expires_at"
        ]
      },
      "PublicSignupResponse": {
        "type": "object",
        "properties": {
          "tenant": {
            "$ref": "#/components/schemas/PublicSignupTenant"
          },
          "initial_token": {
            "$ref": "#/components/schemas/PublicSignupToken"
          },
          "getting_started_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "tenant",
          "initial_token",
          "getting_started_url"
        ]
      },
      "RateLimitError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "retry_after_seconds": {
            "type": "integer"
          }
        },
        "required": [
          "error",
          "retry_after_seconds"
        ]
      },
      "PublicSignupRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "example": "dev@acme.com"
          },
          "company_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "example": "Acme Corp"
          },
          "requested_slug": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9-]{1,62}$",
            "description": "Lowercase slug for your tenant. Must start with a letter.",
            "example": "acme-corp"
          }
        },
        "required": [
          "email",
          "company_name",
          "requested_slug"
        ]
      },
      "LoopTrace": {
        "type": "object",
        "nullable": true,
        "properties": {
          "turns_to_green": {
            "type": "integer"
          },
          "tool_calls": {
            "type": "integer"
          },
          "tokens": {
            "type": "integer"
          },
          "wall_ms": {
            "type": "integer"
          }
        },
        "required": [
          "turns_to_green",
          "tool_calls",
          "tokens",
          "wall_ms"
        ]
      },
      "LoopCloseResponse": {
        "type": "object",
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "green",
              "red",
              "error"
            ]
          },
          "summary": {
            "type": "string"
          },
          "next_actions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "details_ref": {
            "type": "string",
            "nullable": true
          },
          "data": {
            "type": "object",
            "nullable": true,
            "properties": {
              "session_id": {
                "type": "string",
                "format": "uuid"
              },
              "spec_id": {
                "type": "string",
                "format": "uuid"
              },
              "run_id": {
                "type": "string",
                "format": "uuid"
              },
              "confidence": {
                "type": "number"
              },
              "steps_count": {
                "type": "integer"
              }
            },
            "required": [
              "session_id",
              "spec_id",
              "run_id",
              "confidence",
              "steps_count"
            ]
          },
          "trace": {
            "$ref": "#/components/schemas/LoopTrace"
          }
        },
        "required": [
          "outcome",
          "summary",
          "next_actions",
          "details_ref",
          "data",
          "trace"
        ]
      },
      "LoopCloseRequest": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid",
            "description": "sessions.id UUID. Mutually exclusive with session."
          },
          "session": {
            "type": "object",
            "properties": {
              "sessionId": {
                "type": "string",
                "minLength": 1
              },
              "vendor": {
                "type": "string",
                "enum": [
                  "cuit",
                  "jam",
                  "logrocket",
                  "sentry-replay",
                  "fullstory",
                  "datadog-rum"
                ]
              },
              "url": {
                "type": "string"
              },
              "events": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SessionEvent"
                },
                "minItems": 1
              },
              "gitSha": {
                "type": "string"
              },
              "gitBranch": {
                "type": "string"
              },
              "capturedByUserId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "sessionId",
              "vendor",
              "url",
              "events"
            ],
            "description": "Inline session payload. Mutually exclusive with session_id."
          },
          "target_url": {
            "type": "string",
            "format": "uri",
            "description": "URL the spec runner will navigate to.",
            "example": "http://localhost:3000/projects/abc"
          }
        },
        "required": [
          "target_url"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "ops"
        ],
        "summary": "Health check",
        "description": "Returns 200 OK if the API process is alive. No auth required.",
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "ts": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "ts"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions": {
      "post": {
        "tags": [
          "sessions"
        ],
        "summary": "Upload a captured session",
        "description": "Accepts a SessionEvent[] captured by the recorder. Auto-generates a regression spec when feasible (rule-based today; LLM pipeline ships sprint week 5). Idempotent on (tenant_id, session_id).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionUpload"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session stored. Spec may have been generated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionUploadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "List sessions for the authenticated tenant",
        "description": "Returns up to `limit` most-recent sessions ordered by created_at DESC.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "50"
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}": {
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "Fetch one session by id",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "type": "string"
                    },
                    "session": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/SessionListItem"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "events": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/SessionEvent"
                              }
                            }
                          },
                          "required": [
                            "events"
                          ]
                        }
                      ]
                    }
                  },
                  "required": [
                    "tenant",
                    "session"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Session not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/specs": {
      "get": {
        "tags": [
          "specs"
        ],
        "summary": "List generated specs for the authenticated tenant",
        "description": "Returns up to 100 most-recent specs ordered by created_at DESC.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "type": "string"
                    },
                    "specs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SpecListItem"
                      }
                    }
                  },
                  "required": [
                    "tenant",
                    "specs"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/insights/flake-rate": {
      "get": {
        "tags": [
          "insights"
        ],
        "summary": "Per-spec flake rate over the last 28 days",
        "description": "Returns up to 20 specs ordered by flake rate descending. A spec with `reds`/`runs` close to 1.0 is highly unstable.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlakeRateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/tenants": {
      "post": {
        "tags": [
          "admin"
        ],
        "summary": "Create a new tenant",
        "description": "Admin-only. Issues an initial bearer token returned in the response. Token is shown ONCE; we store only its hash. Customer onboarding flow uses this endpoint.",
        "security": [
          {
            "adminAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tenant created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    },
                    "initial_token": {
                      "$ref": "#/components/schemas/TokenIssueResponse"
                    }
                  },
                  "required": [
                    "tenant",
                    "initial_token"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Admin auth required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Slug already in use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/tokens": {
      "post": {
        "tags": [
          "admin"
        ],
        "summary": "Issue a new bearer token for the current tenant",
        "description": "Used to rotate tokens or to issue scoped tokens for specific environments (CI vs. dev). Token shown ONCE in the response.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenIssueRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenIssueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "tags": [
          "admin"
        ],
        "summary": "Current tenant info",
        "description": "Returns the tenant resolved from the bearer token. Useful for the dashboard.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    }
                  },
                  "required": [
                    "tenant"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/specs/generate": {
      "post": {
        "tags": [
          "specs"
        ],
        "summary": "Generate a spec synchronously from a session payload OR session id",
        "description": "POST /v1/sessions auto-generates a spec asynchronously. Use this endpoint when you want the spec back in the same HTTP response — typical for CI integrations or the /cuit-loop skill. Calls the LLM 3-pass pipeline (Haiku normalize → Sonnet ground → Opus materialize) with prompt caching; falls back to rule-based when model_tier=rule-based.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpecGenerateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Spec generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpecDetail"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Generator could not produce a confident spec from this session",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/specs/{id}": {
      "get": {
        "tags": [
          "specs"
        ],
        "summary": "Fetch one spec by id (with full primitives + source)",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpecDetail"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/specs/{id}/run": {
      "post": {
        "tags": [
          "runs"
        ],
        "summary": "Run a spec against a customer URL; returns RED or GREEN with step-level annotations",
        "description": "The runner spins up a vitest-in-process worker (or headless Playwright per `browser`), executes the spec, and returns the structured outcome. On RED: the response includes `failed_at_primitive`, `last_snapshot`, and the preceding event window so an agent can reason about the failure without re-reading the spec source.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run complete",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Spec not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "408": {
            "description": "Run timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs": {
      "get": {
        "tags": [
          "runs"
        ],
        "summary": "List runs across all specs for this tenant",
        "description": "Filterable by `spec_id`, `outcome`, `since`, `until`. Default: last 100 runs across the tenant.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": false,
            "name": "spec_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "red",
                "green",
                "error"
              ]
            },
            "required": false,
            "name": "outcome",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "since",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "until",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "type": "string"
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RunResult"
                      }
                    }
                  },
                  "required": [
                    "tenant",
                    "runs"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/similar": {
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "Find sessions vector-similar to this one",
        "description": "Backed by pgvector cosine similarity over per-session embeddings (voyage-3-lite). The MCP tool `cuit__find_similar_sessions` is a thin wrapper around this endpoint.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "0.85"
            },
            "required": false,
            "name": "threshold",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimilarSessionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Reference session not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/insights/bug-class-distribution": {
      "get": {
        "tags": [
          "insights"
        ],
        "summary": "Aggregate bug-class stats by component over a time window",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "7d / 28d / 90d / 365d",
              "example": "28d"
            },
            "required": false,
            "name": "window",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BugClassDistributionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/instrument/detect-shape": {
      "post": {
        "tags": [
          "instrument"
        ],
        "summary": "Detect customer app shape (framework, state libs, selectors)",
        "description": "Used by the `/cuit-instrument` skill via the `cuit__detect_app_shape` MCP tool. Returns the structured shape so the proposal step can target the right files.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "package_json": {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    },
                    "description": "Contents of the customer repo package.json"
                  },
                  "file_tree": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Flat list of source file paths."
                  },
                  "sample_files": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Optional map of path → content for AST hints."
                  }
                },
                "required": [
                  "package_json"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppShapeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/instrument/propose": {
      "post": {
        "tags": [
          "instrument"
        ],
        "summary": "Given an app shape, propose the instrumentation diff",
        "description": "Used by the `/cuit-instrument` skill via `cuit__propose_instrumentation`. The returned operations[] is consumed by Claude Code's Edit/Write tools to apply the diff.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "app_shape": {
                    "$ref": "#/components/schemas/AppShapeResponse"
                  },
                  "overrides": {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  }
                },
                "required": [
                  "app_shape"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstrumentationProposal"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audit": {
      "get": {
        "tags": [
          "admin"
        ],
        "summary": "Stream audit log as CSV / JSON / NDJSON",
        "description": "Compliance export. Returns a streaming response in the requested format. For large windows, prefer NDJSON for line-by-line consumption.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2026-06-01T00:00:00Z"
            },
            "required": true,
            "name": "since",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2026-06-30T23:59:59Z"
            },
            "required": true,
            "name": "until",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "json",
                "ndjson"
              ],
              "example": "csv"
            },
            "required": false,
            "name": "format",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Streamed export",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": {
                      "nullable": true
                    }
                  }
                }
              },
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/usage": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Current-period usage stats",
        "description": "Returns sessions, specs, runs, inference tokens, and estimated cost for the current billing period.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingUsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/subscription": {
      "get": {
        "tags": [
          "billing"
        ],
        "summary": "Stripe subscription details for the current tenant",
        "description": "Returns subscription status + a link to the Stripe customer portal for self-service.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/tenant": {
      "delete": {
        "tags": [
          "admin"
        ],
        "summary": "Purge all tenant data (GDPR right-to-delete)",
        "description": "Hard-deletes sessions, specs, runs, signals, audit log for the authenticated tenant. Asynchronous: completes within 30 days. Returns a purge job id.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "responses": {
          "202": {
            "description": "Purge job accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "purge_job_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "eta_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "purge_job_id",
                    "eta_at"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/stripe": {
      "post": {
        "tags": [
          "billing"
        ],
        "summary": "Stripe webhook receiver",
        "description": "Stripe webhook receiver. NOT bearer-authenticated — signature verified via HMAC-SHA256 of the raw body against STRIPE_WEBHOOK_SECRET. Routes customer.subscription.created/deleted and invoice.payment_failed events to tenant updates and audit log entries.",
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Stripe-Signature header set by Stripe on every webhook delivery. Required for HMAC-SHA256 verification.",
              "example": "t=1749000000,v1=abc123..."
            },
            "required": true,
            "name": "stripe-signature",
            "in": "header"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StripeWebhookBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event received and queued for processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "received"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid Stripe-Signature header, or webhook misconfigured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/signup": {
      "post": {
        "tags": [
          "public"
        ],
        "summary": "Self-serve tenant signup",
        "description": "No authentication required. Creates a tenant (tier=team) and returns an initial bearer token in a single round-trip. Rate-limited to 3 signups per IP per rolling hour. The token is shown ONCE in the response — store it securely. PII (email, IP) is stored server-side for compliance and is never echoed back.",
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSignupRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tenant created. Contains the tenant object and a one-time-visible bearer token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicSignupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload (missing fields, bad slug format, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Requested slug (and up to 9 auto-suffixed variants) are all taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — more than 3 signups from this IP in the past hour",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/events": {
      "get": {
        "tags": [
          "sessions"
        ],
        "summary": "Fetch the full events array for a single session",
        "description": "Returns the JSONB events column for a session. This is the AX-compliant drill-down counterpart to GET /v1/sessions, which returns only compact id+summary rows to stay within token budget (ADR-011 Rule 2). Pass the returned events to cuit__close_loop to generate and run a regression spec.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "AX ok envelope with full events array",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "events": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/SessionEvent"
                          }
                        }
                      },
                      "required": [
                        "events"
                      ]
                    }
                  },
                  "required": [
                    "outcome",
                    "summary",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Non-UUID id path param",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Session not found (AX error envelope)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "error"
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "fix_hint": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "outcome",
                    "error",
                    "fix_hint"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/loop/close": {
      "post": {
        "tags": [
          "runs"
        ],
        "summary": "One-shot loop close: generate spec → run spec → persist trace",
        "description": "ADR-011 Rule 6 (one-shot composition) + Rule 7 (self-measuring). Runs generate→run→report in ONE call inside a single DB transaction (spec row + run row + loop_trace row + audit row). Returns the loop AX envelope with outcome green|red|error and a trace {turns_to_green, tool_calls, tokens, wall_ms}. Always returns HTTP 200 — the envelope carries the outcome. NOTE: not deduplicated in v0 (each call inserts a new spec row; non-destructive).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cuit-status": "live",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoopCloseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Loop close complete. outcome green|red|error in envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoopCloseResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Session not found (when session_id supplied)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoopCloseResponse"
                }
              }
            }
          },
          "422": {
            "description": "No spec could be generated from the session events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoopCloseResponse"
                }
              }
            }
          }
        }
      }
    }
  }
}
