version: 1
kind: operational-controls

catalog:
  control_keys:
    findings.lifecycle.backfill:
      label: Findings lifecycle backfill
      supported_scopes:
        - global
        - workspace
      operation_types:
        - findings.lifecycle.backfill
      affected_surfaces:
        - system.ops.runbooks
        - tenant.findings.list
    restore.execute:
      label: Restore execution
      supported_scopes:
        - global
        - workspace
      operation_types:
        - restore.execute
      affected_surfaces:
        - tenant.restore_runs.create

activation_record:
  table: operational_control_activations
  fields:
    id: integer
    control_key: string
    scope_type:
      type: string
      allowed:
        - global
        - workspace
    workspace_id:
      type: integer
      nullable: true
    reason_text: string
    expires_at:
      type: datetime
      nullable: true
    created_by_platform_user_id: integer
    updated_by_platform_user_id:
      type: integer
      nullable: true
  display_rules:
    owner_actor: updated_by_platform_user_id when present, otherwise created_by_platform_user_id
  invariants:
    - one active row per control_key + scope_type + workspace_id
    - workspace_id is null for global rows
    - enabled state is derived from no active matching row
  persistence_notes:
    - enforce one active global row per control_key with a partial unique index where scope_type = global
    - enforce one active workspace row per control_key + workspace_id with a partial unique index where scope_type = workspace
    - delete expired conflicting rows before inserting a new activation for the same control/scope
    - do not use this table as an archive of expired activations

management_commands:
  pause_control:
    required_platform_capabilities:
      - platform.access_system_panel
      - platform.ops.controls.manage
    safety_flow:
      - configure scope and reason
      - preview scope impact
      - confirm mutation
    input:
      control_key: string
      scope_type: global|workspace
      workspace_id: integer|null
      reason_text: string
      expires_at: datetime|null
    outcome:
      activation_created_or_updated: true
      audit_action: operational_control.paused|operational_control.updated

  resume_control:
    required_platform_capabilities:
      - platform.access_system_panel
      - platform.ops.controls.manage
    safety_flow:
      - review current scope impact
      - confirm mutation
    input:
      control_key: string
      scope_type: global|workspace
      workspace_id: integer|null
    outcome:
      activation_removed: true
      audit_action: operational_control.resumed

decision_output:
  fields:
    control_key: string
    effective_state: enabled|paused
    matched_scope_type: none|global|workspace
    workspace_id: integer|null
    reason_text: string|null
    expires_at: datetime|null
    source_activation_id: integer|null
  guarantees:
    - returned before any in-scope start is allowed to continue
    - blocked decisions create no queued execution OperationRun, no queued execution RestoreRun, no queued job, and no provider-backed execution
    - control activation governs new starts only and does not mutate previously accepted runs

evaluation_rules:
  precedence:
    - active global activation wins over any workspace activation for the same control key
    - workspace activation applies only when no active global activation matches
  expiry:
    - expired activations are ignored
  disclosure:
    - tenant/admin surfaces disclose control-state details only after membership and capability scope are resolved

enforcement_targets:
  - control_key: findings.lifecycle.backfill
    target:
      seam: service.runbooks.findings_lifecycle_backfill.start
      callers:
        - system.ops.runbooks
        - tenant.findings.list
        - console.tenantpilot.findings.backfill-lifecycle
        - console.tenantpilot.run-deploy-runbooks
      action: Start findings lifecycle backfill
      operation_type: findings.lifecycle.backfill
  - control_key: restore.execute
    target:
      surface: tenant.restore_runs.create
      action: Execute restore
      operation_type: restore.execute

audit_expectations:
  action_ids:
    - operational_control.paused
    - operational_control.updated
    - operational_control.resumed
    - operational_control.execution_blocked
  required_metadata:
    - control_key
    - scope_type
    - workspace_id
    - reason_text
    - expires_at
    - actor_id
  event_specific_metadata:
    blocked_system_all_tenant_execution_events:
      - requested_scope
  ownership:
    global_control_changes: platform-plane event with null workspace_id and null tenant_id
    workspace_control_changes: workspace-scoped event
    blocked_execution_events: scoped to the affected workspace and tenant when a tenant is in context
    blocked_system_all_tenant_execution_events: platform-plane event with null workspace_id and null tenant_id plus requested_scope metadata