TenantAtlas/specs/187-portfolio-triage-arrival-context/contracts/portfolio-triage-arrival-context.logical.openapi.yaml
ahmido 28e62bd22c feat: preserve portfolio triage arrival context (#218)
## Summary
- preserve portfolio triage arrival context from workspace overview and tenant registry drill-throughs
- add a tenant dashboard continuity widget plus bounded arrival token and resolver support
- add focused Pest coverage for arrival routing, return flow, RBAC degradation, and request-local performance
- include the Spec 187 spec, plan, research, data model, quickstart, contract, and tasks artifacts

## Validation
- integrated browser smoke: workspace overview -> tenant dashboard arrival -> backup sets CTA
- integrated browser smoke: tenant registry triage -> tenant dashboard arrival -> return to tenant triage
- branch includes focused automated test coverage for the new arrival-context surfaces

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #218
2026-04-09 21:38:31 +00:00

335 lines
9.4 KiB
YAML

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'