openapi: 3.0.3
info:
  title: TenantPilot Drift (Golden Master) UI endpoints
  version: "1.0"
  description: |
    Minimal contract describing the drift entry point and findings surfaces after Spec 119 cutover.

    Note: These are Filament (server-rendered / Livewire) endpoints, not a public JSON API.
servers:
  - url: /
paths:
  /admin/t/{tenant}/baseline-compare-landing:
    get:
      summary: Drift entry point (Baseline Compare landing)
      description: |
        Tenant-scoped landing page used as the Drift entry point post-cutover.
      parameters:
        - name: tenant
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: HTML page
          content:
            text/html:
              schema:
                type: string
        "403":
          description: Tenant member but missing capability
        "404":
          description: Not entitled to tenant/workspace scope (deny-as-not-found)
        "302":
          description: Redirect to login

  /admin/t/{tenant}/findings:
    get:
      summary: Findings list (tenant-scoped)
      description: |
        Tenant-scoped Findings list. Drift findings post-cutover must have `source = baseline.compare`.
      parameters:
        - name: tenant
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: HTML page
          content:
            text/html:
              schema:
                type: string
        "403":
          description: Tenant member but missing capability
        "404":
          description: Not entitled to tenant/workspace scope (deny-as-not-found)
        "302":
          description: Redirect to login

  /admin/t/{tenant}/findings/{record}:
    get:
      summary: Finding detail view (tenant-scoped)
      description: |
        Tenant-scoped finding detail view. Diff rendering depends on evidence keys:
        - `summary.kind`
        - `baseline.policy_version_id`
        - `current.policy_version_id`
      parameters:
        - name: tenant
          in: path
          required: true
          schema:
            type: integer
        - name: record
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: HTML page
          content:
            text/html:
              schema:
                type: string
        "403":
          description: Tenant member but missing capability
        "404":
          description: Not entitled to tenant/workspace scope (deny-as-not-found)
        "302":
          description: Redirect to login

  /admin/operations/{runId}:
    get:
      summary: Operation run detail (canonical)
      description: Canonical tenantless run viewer (Monitoring → Operations → Run Detail).
      parameters:
        - name: runId
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: HTML page
          content:
            text/html:
              schema:
                type: string
        "403":
          description: Workspace member but missing capability
        "404":
          description: Not entitled to workspace scope (deny-as-not-found)
        "302":
          description: Redirect to login

components:
  schemas:
    DriftSource:
      type: string
      enum: [baseline.compare]

    DriftEvidenceSummaryKind:
      type: string
      enum: [policy_snapshot, policy_assignments, policy_scope_tags]

    DriftEvidenceFidelity:
      type: string
      enum: [content, meta, mixed]

    DriftFindingEvidence:
      type: object
      description: Evidence payload stored in `findings.evidence_jsonb` for drift findings.
      required: [change_type, policy_type, subject_key, summary, baseline, current, fidelity, provenance]
      properties:
        change_type:
          type: string
          enum: [missing_policy, unexpected_policy, different_version]
        policy_type:
          type: string
        subject_key:
          type: string
        summary:
          type: object
          required: [kind]
          properties:
            kind:
              $ref: "#/components/schemas/DriftEvidenceSummaryKind"
            note:
              type: string
              nullable: true
        fidelity:
          $ref: "#/components/schemas/DriftEvidenceFidelity"
        provenance:
          type: object
          required: [baseline_profile_id, baseline_snapshot_id, compare_operation_run_id]
          properties:
            baseline_profile_id:
              type: integer
            baseline_snapshot_id:
              type: integer
            compare_operation_run_id:
              type: integer
            inventory_sync_run_id:
              type: integer
              nullable: true
            tenant_id:
              type: integer
              nullable: true
        baseline:
          type: object
          required: [policy_version_id]
          properties:
            policy_version_id:
              type: integer
              nullable: true
            hash:
              type: string
              nullable: true
            provenance:
              type: object
              additionalProperties: true
        current:
          type: object
          required: [policy_version_id]
          properties:
            policy_version_id:
              type: integer
              nullable: true
            hash:
              type: string
              nullable: true
            provenance:
              type: object
              additionalProperties: true
