openapi: 3.1.0
info:
  title: Tenant Review Layer Internal Contract
  version: 0.1.0
  description: |
    Internal admin-plane contract for tenant review library, review lifecycle actions,
    and executive-pack export based on the Tenant Review Layer spec.
servers:
  - url: /admin
paths:
  /t/{tenant}/reviews:
    get:
      summary: List tenant reviews
      operationId: listTenantReviews
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewStatusFilter'
        - $ref: '#/components/parameters/PublicationStateFilter'
      responses:
        '200':
          description: Tenant review library
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TenantReviewSummary'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      summary: Create tenant review from evidence basis
      operationId: createTenantReview
      parameters:
        - $ref: '#/components/parameters/TenantPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [evidence_snapshot_id]
              properties:
                evidence_snapshot_id:
                  type: integer
                include_operations_summary:
                  type: boolean
                  default: true
      responses:
        '202':
          description: Review composition accepted or queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantReviewMutationResult'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
  /t/{tenant}/reviews/{review}:
    get:
      summary: View tenant review detail
      operationId: viewTenantReview
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewPath'
      responses:
        '200':
          description: Tenant review detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantReviewDetail'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /t/{tenant}/reviews/{review}/refresh:
    post:
      summary: Refresh review into a successor draft
      operationId: refreshTenantReview
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewPath'
      responses:
        '202':
          description: Review refresh accepted or queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantReviewMutationResult'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Review cannot be refreshed in current state
  /t/{tenant}/reviews/{review}/publish:
    post:
      summary: Publish review
      operationId: publishTenantReview
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewPath'
      responses:
        '200':
          description: Review published
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantReviewMutationResult'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Review not publication-ready
  /t/{tenant}/reviews/{review}/archive:
    post:
      summary: Archive review
      operationId: archiveTenantReview
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewPath'
      responses:
        '200':
          description: Review archived
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantReviewMutationResult'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Review cannot be archived in current state
  /t/{tenant}/reviews/{review}/export:
    post:
      summary: Generate executive review pack
      operationId: exportExecutiveReviewPack
      parameters:
        - $ref: '#/components/parameters/TenantPath'
        - $ref: '#/components/parameters/ReviewPath'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                include_pii:
                  type: boolean
                  default: true
      responses:
        '202':
          description: Executive pack generation accepted or queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReviewPackMutationResult'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Review export blocked by readiness rules
  /reviews:
    get:
      summary: List canonical workspace review register
      operationId: listWorkspaceReviews
      parameters:
        - $ref: '#/components/parameters/TenantFilter'
        - $ref: '#/components/parameters/ReviewStatusFilter'
        - $ref: '#/components/parameters/PublicationStateFilter'
      responses:
        '200':
          description: Canonical workspace review register
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TenantReviewRegisterRow'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    TenantPath:
      name: tenant
      in: path
      required: true
      schema:
        type: string
    ReviewPath:
      name: review
      in: path
      required: true
      schema:
        type: integer
    TenantFilter:
      name: tenant_id
      in: query
      required: false
      schema:
        type: integer
    ReviewStatusFilter:
      name: status
      in: query
      required: false
      schema:
        type: string
        enum: [draft, ready, published, archived, superseded, failed]
    PublicationStateFilter:
      name: publication_state
      in: query
      required: false
      schema:
        type: string
        enum: [unpublished, published]
  responses:
    Forbidden:
      description: Member lacks required capability
    NotFound:
      description: Workspace or tenant scope not visible to caller
    ValidationError:
      description: Request validation failed
  schemas:
    TenantReviewSummary:
      type: object
      required: [id, tenant_id, status, completeness_state]
      properties:
        id:
          type: integer
        tenant_id:
          type: integer
        evidence_snapshot_id:
          type: integer
        status:
          type: string
        completeness_state:
          type: string
        generated_at:
          type: string
          format: date-time
          nullable: true
        published_at:
          type: string
          format: date-time
          nullable: true
    TenantReviewRegisterRow:
      allOf:
        - $ref: '#/components/schemas/TenantReviewSummary'
        - type: object
          properties:
            tenant_name:
              type: string
            has_ready_export:
              type: boolean
            publish_blockers_count:
              type: integer
    TenantReviewDetail:
      allOf:
        - $ref: '#/components/schemas/TenantReviewSummary'
        - type: object
          properties:
            executive_summary:
              type: object
              additionalProperties: true
            sections:
              type: array
              items:
                $ref: '#/components/schemas/TenantReviewSection'
            latest_export:
              $ref: '#/components/schemas/ReviewPackSummary'
    TenantReviewSection:
      type: object
      required: [section_key, title, sort_order, completeness_state]
      properties:
        section_key:
          type: string
        title:
          type: string
        sort_order:
          type: integer
        completeness_state:
          type: string
        summary_payload:
          type: object
          additionalProperties: true
    ReviewPackSummary:
      type: object
      properties:
        id:
          type: integer
        status:
          type: string
        generated_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
    TenantReviewMutationResult:
      type: object
      required: [review_id, status]
      properties:
        review_id:
          type: integer
        status:
          type: string
        operation_run_id:
          type: integer
          nullable: true
        message:
          type: string
    ReviewPackMutationResult:
      type: object
      required: [review_pack_id, status]
      properties:
        review_pack_id:
          type: integer
        status:
          type: string
        operation_run_id:
          type: integer
          nullable: true
        message:
          type: string