openapi: 3.0.3
info:
  title: TenantPilot Admin Run Orchestration (049)
  version: 0.1.0
  description: |
    Internal admin contracts for starting long-running backup/restore operations
    and reading run status/progress. These endpoints are tenant-scoped.

servers:
  - url: /admin

paths:
  /t/{tenantExternalId}/runs/{runType}:
    post:
      operationId: startRun
      summary: Start a background run
      description: |
        Starts an operation by creating (or reusing) a Run Record and enqueueing
        background work. Must return quickly.
      parameters:
        - in: path
          name: tenantExternalId
          required: true
          schema:
            type: string
        - in: path
          name: runType
          required: true
          schema:
            type: string
            enum:
              - backup_set_add_policies
              - restore_execute
              - restore_preview
              - snapshot_capture
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunStartRequest'
      responses:
        '201':
          description: Run created and queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunStartResponse'
        '200':
          description: Existing active run reused
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunStartResponse'
        '403':
          description: Forbidden

  /t/{tenantExternalId}/runs/{runType}/{runId}:
    get:
      operationId: getRun
      summary: Get run status and progress
      parameters:
        - in: path
          name: tenantExternalId
          required: true
          schema:
            type: string
        - in: path
          name: runType
          required: true
          schema:
            type: string
        - in: path
          name: runId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Run record
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunRecord'
        '404':
          description: Not found

components:
  schemas:
    RunStartRequest:
      type: object
      additionalProperties: false
      properties:
        targetObjectId:
          type: string
          nullable: true
          description: Operation target used for de-duplication.
        payloadHash:
          type: string
          nullable: true
          description: Optional stable hash of relevant payload to strengthen idempotency.
        itemIds:
          type: array
          items:
            type: string
          nullable: true
          description: Optional internal item ids to process.

    RunStartResponse:
      type: object
      required: [run]
      properties:
        reused:
          type: boolean
          default: false
        run:
          $ref: '#/components/schemas/RunRecord'

    RunRecord:
      type: object
      required:
        - id
        - tenantExternalId
        - type
        - status
      properties:
        id:
          type: string
        tenantExternalId:
          type: string
        type:
          type: string
        status:
          type: string
          enum: [queued, running, succeeded, failed, partial]
        createdAt:
          type: string
          format: date-time
        startedAt:
          type: string
          format: date-time
          nullable: true
        finishedAt:
          type: string
          format: date-time
          nullable: true
        counts:
          type: object
          additionalProperties: false
          properties:
            total:
              type: integer
              minimum: 0
            succeeded:
              type: integer
              minimum: 0
            failed:
              type: integer
              minimum: 0
        safeError:
          type: object
          nullable: true
          additionalProperties: false
          properties:
            code:
              type: string
            context:
              type: object
              additionalProperties: true
