openapi: 3.1.0
info:
  title: Portfolio Triage Arrival Context Internal Surface Contract
  version: 0.1.0
  summary: Internal logical contract for preserving portfolio triage intent into tenant arrival surfaces
  description: |
    This contract is an internal planning artifact for Spec 187. The affected routes still
    return HTML. The schemas below describe the bounded request data and rendered continuity
    models that must be derivable before the tenant dashboard or downstream backup/restore
    destinations are rendered. No public API is introduced.
servers:
  - url: /internal
x-arrival-context-consumers:
  - surface: workspace.overview.triage
    sourceFiles:
      - apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php
      - apps/platform/app/Filament/Widgets/Workspace/WorkspaceNeedsAttention.php
      - apps/platform/app/Filament/Widgets/Workspace/WorkspaceSummaryStats.php
    mustEmit:
      - reason_context
      - destination
      - arrival_context_token
  - surface: tenant.registry.triage
    sourceFiles:
      - apps/platform/app/Filament/Resources/TenantResource.php
      - apps/platform/app/Filament/Resources/TenantResource/Pages/ListTenants.php
    mustPreserve:
      - backup_posture
      - recovery_evidence
      - triage_sort
      - arrival_context_token
  - surface: tenant.dashboard.arrival
    sourceFiles:
      - apps/platform/app/Filament/Pages/TenantDashboard.php
      - apps/platform/app/Filament/Widgets/Tenant/TenantTriageArrivalContinuity.php
    mustRender:
      - source_surface
      - concern_family
      - concern_state
      - next_step
      - return_target
paths:
  /admin/w/{workspace}:
    get:
      summary: Workspace overview recovery triage surfaces emit bounded tenant-arrival context
      operationId: viewWorkspaceOverviewWithArrivalContext
      parameters:
        - name: workspace
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Rendered workspace overview with triage destinations
          content:
            text/html:
              schema:
                type: string
            application/vnd.tenantpilot.workspace-triage+json:
              schema:
                $ref: '#/components/schemas/WorkspaceTriageBundle'
        '404':
          description: Workspace is outside the actor's entitlement scope
  /admin/tenants:
    get:
      summary: Tenant registry triage accepts allowlisted filters and can preserve portfolio return context
      operationId: viewTenantRegistryWithTriageContext
      parameters:
        - name: backup_posture
          in: query
          required: false
          schema:
            type: array
            items:
              $ref: '#/components/schemas/BackupConcernState'
        - name: recovery_evidence
          in: query
          required: false
          schema:
            type: array
            items:
              $ref: '#/components/schemas/RecoveryConcernState'
        - name: triage_sort
          in: query
          required: false
          schema:
            $ref: '#/components/schemas/TriageSort'
      responses:
        '200':
          description: Rendered tenant registry with optional triage filter context
          content:
            text/html:
              schema:
                type: string
            application/vnd.tenantpilot.tenant-registry-triage+json:
              schema:
                $ref: '#/components/schemas/TenantRegistryTriageBundle'
        '404':
          description: Workspace scope is not available to the actor
  /admin/t/{tenant}:
    get:
      summary: Tenant dashboard renders a continuity block only when a valid arrival token is present
      operationId: viewTenantDashboardWithArrivalContext
      parameters:
        - name: tenant
          in: path
          required: true
          schema:
            type: string
        - name: arrival
          in: query
          required: false
          schema:
            type: string
          description: Versioned base64url token carrying bounded portfolio-arrival metadata.
      responses:
        '200':
          description: Rendered tenant dashboard with optional arrival continuity block
          content:
            text/html:
              schema:
                type: string
            application/vnd.tenantpilot.tenant-dashboard-arrival+json:
              schema:
                $ref: '#/components/schemas/TenantDashboardArrivalBundle'
        '403':
          description: Actor is in scope but lacks the capability required to open a deeper next-step destination
        '404':
          description: Tenant is outside workspace or tenant entitlement scope
components:
  schemas:
    SourceSurface:
      type: string
      enum:
        - workspace_overview
        - tenant_registry
    ConcernFamily:
      type: string
      enum:
        - backup_health
        - recovery_evidence
    BackupConcernState:
      type: string
      enum:
        - absent
        - stale
        - degraded
    RecoveryConcernState:
      type: string
      enum:
        - unvalidated
        - weakened
    ConcernState:
      type: string
      enum:
        - absent
        - stale
        - degraded
        - unvalidated
        - weakened
    TriageSort:
      type: string
      enum:
        - worst_first
    NavigationTargetKind:
      type: string
      enum:
        - tenant_dashboard
        - backup_sets
        - restore_runs
        - restore_run_detail
        - workspace_overview
        - tenant_registry
    NavigationTarget:
      type: object
      additionalProperties: false
      required:
        - kind
        - label
        - disabled
      properties:
        kind:
          $ref: '#/components/schemas/NavigationTargetKind'
        label:
          type: string
        url:
          type:
            - string
            - 'null'
        disabled:
          type: boolean
        helperText:
          type:
            - string
            - 'null'
        filters:
          type:
            - object
            - 'null'
          additionalProperties: true
    ArrivalTokenState:
      type: object
      additionalProperties: false
      required:
        - v
        - sourceSurface
        - concernFamily
        - concernState
      properties:
        v:
          type: integer
          const: 1
        sourceSurface:
          $ref: '#/components/schemas/SourceSurface'
        tenantRouteKey:
          type:
            - string
            - 'null'
        workspaceId:
          type:
            - integer
            - 'null'
        concernFamily:
          $ref: '#/components/schemas/ConcernFamily'
        concernState:
          $ref: '#/components/schemas/ConcernState'
        concernReason:
          type:
            - string
            - 'null'
        returnFilters:
          type:
            - object
            - 'null'
          additionalProperties: true
    PortfolioArrivalContext:
      type: object
      additionalProperties: false
      required:
        - sourceSurface
        - concernFamily
        - concernState
        - nextStep
        - returnTarget
      properties:
        sourceSurface:
          $ref: '#/components/schemas/SourceSurface'
        concernFamily:
          $ref: '#/components/schemas/ConcernFamily'
        concernState:
          $ref: '#/components/schemas/ConcernState'
        concernReason:
          type:
            - string
            - 'null'
        arrivalSummary:
          type: string
        claimBoundary:
          type:
            - string
            - 'null'
        currentTruthDelta:
          type:
            - string
            - 'null'
        nextStep:
          $ref: '#/components/schemas/NavigationTarget'
        returnTarget:
          $ref: '#/components/schemas/NavigationTarget'
    WorkspaceAttentionItem:
      type: object
      additionalProperties: false
      required:
        - tenantRouteKey
        - family
        - destination
      properties:
        tenantRouteKey:
          type: string
        family:
          $ref: '#/components/schemas/ConcernFamily'
        reasonContext:
          type: object
          additionalProperties: false
          properties:
            family:
              $ref: '#/components/schemas/ConcernFamily'
            state:
              $ref: '#/components/schemas/ConcernState'
            reason:
              type:
                - string
                - 'null'
        destination:
          $ref: '#/components/schemas/NavigationTarget'
        arrivalToken:
          type:
            - string
            - 'null'
    WorkspaceTriageBundle:
      type: object
      additionalProperties: false
      required:
        - attentionItems
      properties:
        attentionItems:
          type: array
          items:
            $ref: '#/components/schemas/WorkspaceAttentionItem'
    TenantRegistryTriageBundle:
      type: object
      additionalProperties: false
      required:
        - activeFilters
      properties:
        activeFilters:
          type: object
          additionalProperties: true
        tenantOpenArrivalToken:
          type:
            - string
            - 'null'
    TenantDashboardArrivalBundle:
      type: object
      additionalProperties: false
      required:
        - arrivalContextPresent
      properties:
        arrivalContextPresent:
          type: boolean
        arrivalContext:
          oneOf:
            - $ref: '#/components/schemas/PortfolioArrivalContext'
            - type: 'null'