openapi: 3.0.3
info:
  title: System Ops Runbooks (Spec 113)
  version: 0.1.0
  description: |
    Conceptual contract for the operator control plane under /system.

    Note: The implementation is a Filament (Livewire) UI. These endpoints
    represent the stable user-facing routes + the logical actions (preflight/run)
    and their request/response shapes.

servers:
  - url: /

paths:
  /system/ops/runbooks:
    get:
      summary: Runbook catalog page
      responses:
        '200':
          description: HTML page
          content:
            text/html:
              schema:
                type: string

  /system/ops/runbooks/findings-lifecycle-backfill/preflight:
    post:
      summary: Preflight findings lifecycle backfill
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunbookPreflightRequest'
      responses:
        '200':
          description: Preflight result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunbookPreflightResponse'
        '403':
          description: Platform user lacks capability
        '404':
          description: Wrong plane / not platform-authenticated

  /system/ops/runbooks/findings-lifecycle-backfill/runs:
    post:
      summary: Start findings lifecycle backfill
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunbookStartRequest'
      responses:
        '201':
          description: Run accepted/queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunbookStartResponse'
        '409':
          description: Already queued / lock busy
        '422':
          description: Validation error (missing reason, missing typed confirmation, etc.)

  /system/ops/runs:
    get:
      summary: Operation runs list page
      responses:
        '200':
          description: HTML page
          content:
            text/html:
              schema:
                type: string

  /system/ops/runs/{runId}:
    get:
      summary: Operation run detail page
      parameters:
        - in: path
          name: runId
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: HTML page
          content:
            text/html:
              schema:
                type: string
        '404':
          description: Not found

components:
  schemas:
    RunbookScope:
      type: object
      required: [mode]
      properties:
        mode:
          type: string
          enum: [all_tenants, single_tenant]
        tenant_id:
          type: integer
          nullable: true

    RunbookPreflightRequest:
      type: object
      required: [scope]
      properties:
        scope:
          $ref: '#/components/schemas/RunbookScope'

    RunbookPreflightResponse:
      type: object
      required: [affected_count, total_count]
      properties:
        affected_count:
          type: integer
          minimum: 0
        total_count:
          type: integer
          minimum: 0

    RunbookReason:
      type: object
      required: [reason_code, reason_text]
      properties:
        reason_code:
          type: string
          enum: [DATA_REPAIR, INCIDENT, SUPPORT, SECURITY]
        reason_text:
          type: string
          maxLength: 500

    RunbookStartRequest:
      type: object
      required: [scope, preflight]
      properties:
        scope:
          $ref: '#/components/schemas/RunbookScope'
        preflight:
          type: object
          required: [affected_count]
          properties:
            affected_count:
              type: integer
              minimum: 0
        typed_confirmation:
          type: string
          nullable: true
          description: Required for all_tenants (must equal BACKFILL)
        reason:
          $ref: '#/components/schemas/RunbookReason'

    RunbookStartResponse:
      type: object
      required: [operation_run_id, view_run_url]
      properties:
        operation_run_id:
          type: integer
        view_run_url:
          type: string
