openapi: 3.1.0
info:
  title: Operation Run Lifecycle Monitoring Contract
  version: 0.1.0
  summary: Canonical Monitoring data contract for lifecycle freshness and reconciliation semantics on covered OperationRun records.
servers:
  - url: https://tenantpilot.local
paths:
  /api/admin/operations:
    get:
      summary: List operation runs with lifecycle freshness semantics
      operationId: listOperationRuns
      parameters:
        - in: query
          name: status
          schema:
            type: string
            enum: [queued, running, completed]
        - in: query
          name: outcome
          schema:
            type: string
            enum: [pending, succeeded, partially_succeeded, blocked, failed]
        - in: query
          name: type
          schema:
            type: string
        - in: query
          name: tenant_id
          schema:
            type: integer
        - in: query
          name: freshness_state
          schema:
            type: string
            enum: [fresh_active, likely_stale, reconciled_failed, terminal_normal]
        - in: query
          name: reconciled
          schema:
            type: boolean
      responses:
        '200':
          description: Paginated collection of operation runs
          content:
            application/json:
              schema:
                type: object
                required: [data]
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/OperationRunListItem'
  /api/admin/operations/{operationRun}:
    get:
      summary: Get one operation run with lifecycle reconciliation detail
      operationId: getOperationRun
      parameters:
        - in: path
          name: operationRun
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Operation run detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationRunDetail'
        '404':
          description: Run not found or caller not entitled to the run scope
components:
  schemas:
    OperationRunListItem:
      type: object
      required:
        - id
        - type
        - status
        - outcome
        - freshness_state
        - reconciled
        - created_at
      properties:
        id:
          type: integer
        type:
          type: string
        type_label:
          type: string
        status:
          type: string
          enum: [queued, running, completed]
        outcome:
          type: string
          enum: [pending, succeeded, partially_succeeded, blocked, failed]
        freshness_state:
          type: string
          enum: [fresh_active, likely_stale, reconciled_failed, terminal_normal]
        reconciled:
          type: boolean
        tenant_id:
          type: integer
          nullable: true
        initiator_name:
          type: string
          nullable: true
        operator_message:
          type: string
          description: Operator-safe summary line shown by default on Monitoring surfaces.
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true
    OperationRunDetail:
      allOf:
        - $ref: '#/components/schemas/OperationRunListItem'
        - type: object
          properties:
            summary_counts:
              type: object
              additionalProperties:
                type: number
            failure_summary:
              type: array
              items:
                $ref: '#/components/schemas/FailureSummaryItem'
            reconciliation:
              $ref: '#/components/schemas/ReconciliationRecord'
            diagnostics:
              type: object
              description: Secondary lifecycle evidence shown only when diagnostics are revealed.
              properties:
                threshold_seconds:
                  type: integer
                evidence:
                  type: object
                  additionalProperties: true
    FailureSummaryItem:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string
    ReconciliationRecord:
      type: object
      nullable: true
      properties:
        reconciled_at:
          type: string
          format: date-time
        source:
          type: string
          enum: [failed_callback, scheduled_reconciler, adapter_reconciler]
        reason_code:
          type: string
        reason_message:
          type: string
        evidence:
          type: object
          additionalProperties: true