openapi: 3.0.3
info:
  title: TenantPilot AI Governance Foundation (Conceptual)
  version: 0.1.0
  description: |
    Conceptual contract for the existing workspace settings page, the existing
    system operational-controls page, and the in-process governed AI decision
    schema planned by Spec 248.

    NOTE: The settings and controls actions are implemented as existing Filament
    (Livewire) pages/actions. No new customer-facing AI route or external
    provider execution endpoint is introduced in v1.
servers:
  - url: /
paths:
  /admin/settings/workspace:
    get:
      summary: View workspace settings page
      description: |
        Existing singleton workspace settings route.
        The AI policy section is planned to render on this page without adding a
        second AI admin surface.
      responses:
        '200':
          description: Workspace settings page rendered
          content:
            text/html:
              schema:
                type: string
        '404':
          description: Not found (wrong workspace or non-member)
        '403':
          description: Forbidden (member without view capability)

  /admin/settings/workspace/ai-policy:
    post:
      summary: Save workspace AI policy
      description: |
        Logical action on the existing Filament workspace settings page.
        Non-members or wrong-workspace actors receive 404 semantics before any
        policy detail is revealed. Members without
        `workspace_settings.manage` receive 403 on mutation.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [policy_mode]
              properties:
                policy_mode:
                  $ref: '#/components/schemas/WorkspaceAiPolicyMode'
      responses:
        '204':
          description: Policy saved
        '403':
          description: Forbidden (member lacks manage capability)
        '404':
          description: Not found (wrong workspace or non-member)

  /system/ops/controls:
    get:
      summary: View system operational controls page
      description: |
        Existing system control-center route. The AI execution control is added
        here rather than on a new AI console. Wrong-plane or non-platform
        actors keep deny-as-not-found semantics before any system control detail
        is revealed.
      responses:
        '200':
          description: Controls page rendered
          content:
            text/html:
              schema:
                type: string
        '404':
          description: Not found (wrong plane or non-platform actor)
        '403':
          description: Forbidden (platform actor lacks required system capability)

  /system/ops/controls/ai.execution/pause:
    post:
      summary: Pause AI execution globally
      description: |
        Logical control action on the existing system controls page.
        Wrong-plane or non-platform actors receive 404 semantics before any
        control detail is revealed.
        Must require confirmation in the UI and enforce
        `platform.access_system_panel` plus `platform.ops.controls.manage`
        server-side. Spec 248 keeps `ai.execution` global-only in v1.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [reason_text]
              properties:
                reason_text:
                  type: string
                expires_at:
                  type: string
                  format: date-time
                  nullable: true
      responses:
        '204':
          description: Control activated
        '404':
          description: Not found (wrong plane or non-platform actor)
        '403':
          description: Forbidden (platform actor lacks required control capability)

  /system/ops/controls/ai.execution/resume:
    post:
      summary: Resume AI execution globally
      description: |
        Logical control action on the existing system controls page.
        Wrong-plane or non-platform actors receive 404 semantics before any
        control detail is revealed.
        Removes an active `ai.execution` pause using the existing control-center
        confirmation and audit flow. Spec 248 keeps `ai.execution`
        global-only in v1.
      responses:
        '204':
          description: Control resumed
        '404':
          description: Not found (wrong plane or non-platform actor)
        '403':
          description: Forbidden (platform actor lacks required control capability)

components:
  schemas:
    WorkspaceAiPolicyMode:
      type: string
      enum: [disabled, private_only]

    ProviderClass:
      type: string
      enum: [local_private, external_public]

    AiDataClassification:
      type: string
      enum:
        - product_knowledge
        - operational_metadata
        - redacted_support_summary
        - personal_data
        - customer_confidential
        - raw_provider_payload

    ApprovedAiUseCaseKey:
      type: string
      enum:
        - product_knowledge.answer_draft
        - support_diagnostics.summary_draft

    GovernedAiExecutionRequest:
      type: object
      description: |
        In-process service contract, not a public HTTP endpoint in v1.
        This is the preflight envelope evaluated before any provider resolution
        or model execution is attempted. The host surface must already have
        resolved authorization and scope entitlement before this request is
        constructed.
      required:
        - workspace_id
        - actor_type
        - actor_id
        - use_case_key
        - requested_provider_class
        - data_classifications
        - source_family
      properties:
        workspace_id:
          type: integer
        tenant_id:
          type: integer
          nullable: true
        actor_type:
          type: string
        actor_id:
          type: integer
        use_case_key:
          $ref: '#/components/schemas/ApprovedAiUseCaseKey'
        requested_provider_class:
          $ref: '#/components/schemas/ProviderClass'
        data_classifications:
          type: array
          items:
            $ref: '#/components/schemas/AiDataClassification'
        source_family:
          type: string
        caller_surface:
          type: string
          nullable: true
        context_fingerprint:
          type: string
          nullable: true

    GovernedAiExecutionDecision:
      type: object
      required:
        - outcome
        - reason_code
        - workspace_ai_policy_mode
        - use_case_key
        - requested_provider_class
        - data_classifications
        - source_family
      properties:
        outcome:
          type: string
          enum: [allowed, blocked]
        reason_code:
          type: string
        workspace_ai_policy_mode:
          $ref: '#/components/schemas/WorkspaceAiPolicyMode'
        matched_operational_control_scope:
          type: string
          enum: [global]
          nullable: true
        use_case_key:
          $ref: '#/components/schemas/ApprovedAiUseCaseKey'
        requested_provider_class:
          $ref: '#/components/schemas/ProviderClass'
        data_classifications:
          type: array
          items:
            $ref: '#/components/schemas/AiDataClassification'
        source_family:
          type: string
        audit_action:
          type: string
        audit_metadata:
          $ref: '#/components/schemas/AiDecisionAuditMetadata'

    AiDecisionAuditMetadata:
      type: object
      required:
        - use_case_key
        - decision_outcome
        - decision_reason
        - workspace_ai_policy_mode
        - requested_provider_class
        - data_classifications
        - source_family
        - workspace_id
      properties:
        use_case_key:
          $ref: '#/components/schemas/ApprovedAiUseCaseKey'
        decision_outcome:
          type: string
          enum: [allowed, blocked]
        decision_reason:
          type: string
        workspace_ai_policy_mode:
          $ref: '#/components/schemas/WorkspaceAiPolicyMode'
        requested_provider_class:
          $ref: '#/components/schemas/ProviderClass'
        data_classifications:
          type: array
          items:
            $ref: '#/components/schemas/AiDataClassification'
        source_family:
          type: string
        workspace_id:
          type: integer
        tenant_id:
          type: integer
          nullable: true
        context_fingerprint:
          type: string
          nullable: true
        matched_operational_control_scope:
          type: string
          enum: [global]
          nullable: true