openapi: 3.1.0
info:
  title: Baseline Snapshot Structured Rendering Contract
  version: 1.0.0
  description: >-
    Behavioral contract for the workspace-scoped Baseline Snapshot detail surface
    after Spec 130. These are HTML/admin-panel endpoints, but the response shape
    is modeled here so summary-first rendering, grouped-browser behavior, and
    authorization semantics stay explicit.
servers:
  - url: https://tenantpilot.test
paths:
  /admin/baseline-snapshots:
    get:
      summary: Open the workspace-scoped baseline snapshot list
      operationId: listBaselineSnapshots
      tags:
        - Baseline Snapshot Rendering
      responses:
        '200':
          description: Snapshot list rendered for an authenticated actor entitled to the active workspace scope
        '302':
          description: Redirect to workspace chooser because no workspace is selected
          headers:
            Location:
              schema:
                type: string
                enum:
                  - /admin/choose-workspace
        '403':
          description: Actor is in the active workspace scope but lacks the baseline-view capability required for snapshot list inspection
        '404':
          description: Actor is not entitled to the admin workspace plane or active workspace scope
  /admin/baseline-snapshots/{snapshot}:
    get:
      summary: Open the structured baseline snapshot detail page
      operationId: openBaselineSnapshotDetail
      tags:
        - Baseline Snapshot Rendering
      parameters:
        - name: snapshot
          in: path
          required: true
          schema:
            type: integer
          description: Workspace-owned baseline snapshot identifier
      responses:
        '200':
          description: Structured snapshot detail rendered with metadata, summary, groups, and secondary technical detail
          content:
            text/html:
              schema:
                $ref: '#/components/schemas/BaselineSnapshotDetailPage'
        '302':
          description: Redirect to workspace chooser because no workspace is selected
          headers:
            Location:
              schema:
                type: string
                enum:
                  - /admin/choose-workspace
        '403':
          description: Actor is in the active workspace scope but lacks the baseline-view capability required for protected detail rendering
        '404':
          description: Actor is not entitled to the workspace scope or the snapshot is outside the active workspace boundary
components:
  schemas:
    BaselineSnapshotDetailPage:
      type: object
      required:
        - page
        - snapshot
        - summaryRows
        - groups
      properties:
        page:
          type: string
          const: baseline-snapshot-detail
        snapshot:
          $ref: '#/components/schemas/SnapshotMeta'
        summaryRows:
          type: array
          items:
            $ref: '#/components/schemas/SnapshotSummaryRow'
        groups:
          type: array
          items:
            $ref: '#/components/schemas/SnapshotGroup'
        technicalDetail:
          description: Optional secondary disclosure shown only when technical payload inspection is retained and authorized.
          $ref: '#/components/schemas/TechnicalDetailDisclosure'
    SnapshotMeta:
      type: object
      required:
        - snapshotId
        - capturedAt
        - overallFidelity
        - overallGapCount
      properties:
        snapshotId:
          type: integer
        baselineProfileName:
          type:
            - string
            - 'null'
        capturedAt:
          type:
            - string
            - 'null'
          format: date-time
        snapshotIdentityHash:
          type:
            - string
            - 'null'
        overallFidelity:
          $ref: '#/components/schemas/FidelityState'
        overallGapCount:
          type: integer
    SnapshotSummaryRow:
      type: object
      required:
        - policyType
        - label
        - itemCount
        - fidelity
        - gapCount
      properties:
        policyType:
          type: string
        label:
          type: string
        itemCount:
          type: integer
        fidelity:
          $ref: '#/components/schemas/FidelityState'
        gapCount:
          type: integer
        capturedAt:
          type:
            - string
            - 'null'
          format: date-time
        coverageHint:
          type:
            - string
            - 'null'
    SnapshotGroup:
      type: object
      required:
        - policyType
        - label
        - itemCount
        - fidelity
        - gapSummary
        - initiallyCollapsed
        - items
      properties:
        policyType:
          type: string
        label:
          type: string
        itemCount:
          type: integer
        fidelity:
          $ref: '#/components/schemas/FidelityState'
        gapSummary:
          $ref: '#/components/schemas/GapSummary'
        initiallyCollapsed:
          type: boolean
          const: true
        renderingError:
          type:
            - string
            - 'null'
        items:
          type: array
          items:
            $ref: '#/components/schemas/SnapshotItem'
    SnapshotItem:
      type: object
      required:
        - label
        - typeLabel
        - identityHint
        - referenceStatus
        - fidelity
        - gapSummary
        - structuredAttributes
      properties:
        label:
          type: string
        typeLabel:
          type: string
        identityHint:
          type: string
        referenceStatus:
          type: string
        fidelity:
          $ref: '#/components/schemas/FidelityState'
        gapSummary:
          $ref: '#/components/schemas/GapSummary'
        observedAt:
          type:
            - string
            - 'null'
          format: date-time
        sourceReference:
          type:
            - string
            - 'null'
        structuredAttributes:
          type: array
          items:
            $ref: '#/components/schemas/StructuredAttribute'
    StructuredAttribute:
      type: object
      required:
        - label
        - value
        - priority
      properties:
        label:
          type: string
        value:
          oneOf:
            - type: string
            - type: number
            - type: integer
            - type: boolean
        priority:
          type: string
          enum:
            - primary
            - secondary
    GapSummary:
      type: object
      required:
        - count
        - hasGaps
        - messages
      properties:
        count:
          type: integer
        hasGaps:
          type: boolean
        messages:
          type: array
          items:
            type: string
    TechnicalDetailDisclosure:
      type: object
      required:
        - label
        - defaultCollapsed
      properties:
        label:
          type: string
          const: Technical detail
        defaultCollapsed:
          type: boolean
          const: true
        summaryPayloadAvailable:
          type: boolean
        groupPayloadsAvailable:
          type: boolean
    FidelityState:
      type: string
      enum:
        - full
        - partial
        - reference_only
        - unsupported