openapi: 3.1.0 info: title: Workspace Recovery Posture Visibility Internal Surface Contract version: 0.1.0 summary: Internal logical contract for backup-health and recovery-evidence visibility on the workspace overview description: | This contract is an internal planning artifact for Spec 185. It documents how the existing workspace overview must derive backup-health and recovery-evidence metrics, attention items, calmness, and tenant-dashboard drillthroughs from visible tenant truth. The rendered routes still return HTML. The structured schemas below describe the internal page and widget models that must be derivable before rendering. This does not add a public HTTP API. servers: - url: /internal x-overview-consumers: - surface: workspace.overview.summary_stats summarySource: - workspace_overview_builder - tenant_backup_health_resolver - restore_safety_resolver_dashboard_recovery_evidence - existing_governance_metrics - existing_activity_metrics guardScope: - app/Support/Workspaces/WorkspaceOverviewBuilder.php - app/Filament/Widgets/Workspace/WorkspaceSummaryStats.php expectedContract: - backup_attention_and_recovery_attention_are_separate_metrics - counts_are_visible_tenant_counts_not_raw_issue_totals - single_tenant_metric_destinations_may_open_that_tenant_dashboard - multi_tenant_metric_destinations_fall_back_to_choose_tenant - surface: workspace.overview.needs_attention summarySource: - workspace_overview_builder - tenant_backup_health_resolver - restore_safety_resolver_dashboard_recovery_evidence - existing_governance_attention - existing_operations_attention guardScope: - app/Support/Workspaces/WorkspaceOverviewBuilder.php - app/Filament/Widgets/Workspace/WorkspaceNeedsAttention.php - resources/views/filament/widgets/workspace/workspace-needs-attention.blade.php expectedContract: - backup_health_and_recovery_evidence_items_are_tenant_bound - new_items_use_tenant_dashboard_as_primary_destination - backup_and_recovery_items_rank_above_activity_only_signals - no_item_claims_workspace_recovery_is_proven - hidden_tenants_never_leak_through_labels_or_reason_text - surface: workspace.overview.calmness summarySource: - workspace_overview_builder - tenant_backup_health_resolver - restore_safety_resolver_dashboard_recovery_evidence - existing_workspace_calmness_inputs guardScope: - app/Support/Workspaces/WorkspaceOverviewBuilder.php - resources/views/filament/pages/workspace-overview.blade.php expectedContract: - checked_domains_include_backup_health_and_recovery_evidence - calmness_is_false_when_any_visible_backup_or_recovery_issue_exists - calmness_is_explicitly_bounded_to_visible_tenants paths: /admin: get: summary: Render the workspace overview with backup-health and recovery-evidence visibility operationId: viewWorkspaceRecoveryPostureOverview responses: '200': description: Workspace overview rendered with visible-tenant backup and recovery metrics, attention, and calmness semantics content: text/html: schema: type: string application/vnd.tenantpilot.workspace-recovery-posture-visibility+json: schema: $ref: '#/components/schemas/WorkspaceRecoveryOverviewBundle' '302': description: No workspace context is active yet, so the request redirects to `/admin/choose-workspace` '404': description: Workspace is outside entitlement scope /admin/choose-tenant: get: summary: Deliberate tenant-entry destination used by multi-tenant workspace backup or recovery metrics operationId: openChooseTenantFromWorkspaceRecoveryOverview responses: '200': description: Choose-tenant page opened inside the current workspace context so the operator can pick a tenant deliberately /admin/t/{tenant}: get: summary: Canonical tenant-dashboard drillthrough for workspace backup or recovery posture items operationId: openTenantDashboardFromWorkspaceRecoveryOverview parameters: - name: tenant in: path required: true schema: type: string responses: '200': description: Tenant dashboard opened for the visible tenant named by the workspace item '404': description: Tenant is outside entitlement scope components: schemas: MetricCategory: type: string enum: - scope - governance_risk - backup_health - recovery_evidence - activity - alerts WorkspaceMetricKey: type: string enum: - accessible_tenants - governance_attention_tenants - backup_attention_tenants - recovery_attention_tenants - active_operations - alert_failures AttentionFamily: type: string enum: - governance - findings - compare - backup_health - recovery_evidence - operations - alerts - evidence - review AttentionUrgency: type: string enum: - critical - high - medium - supporting DestinationKind: type: string enum: - choose_tenant - switch_workspace - tenant_dashboard - tenant_findings - baseline_compare_landing - operations_index - alerts_overview - tenant_evidence - tenant_reviews CalmnessCheckedDomain: type: string enum: - tenant_access - governance - findings - compare - backup_health - recovery_evidence - operations - alerts WorkspaceRecoveryOverviewBundle: type: object required: - accessible_tenant_count - summary_metrics - attention_items - calmness properties: accessible_tenant_count: type: integer minimum: 0 summary_metrics: type: array items: $ref: '#/components/schemas/WorkspaceSummaryMetric' attention_items: type: array items: $ref: '#/components/schemas/WorkspaceAttentionItem' calmness: $ref: '#/components/schemas/WorkspaceCalmness' WorkspaceSummaryMetric: type: object required: - key - label - value - category - description properties: key: $ref: '#/components/schemas/WorkspaceMetricKey' label: type: string value: type: integer minimum: 0 category: $ref: '#/components/schemas/MetricCategory' description: type: string destination: anyOf: - $ref: '#/components/schemas/Destination' - type: 'null' WorkspaceAttentionItem: type: object required: - key - tenant_id - tenant_label - family - urgency - title - body - destination properties: key: type: string tenant_id: type: integer tenant_label: type: string family: $ref: '#/components/schemas/AttentionFamily' urgency: $ref: '#/components/schemas/AttentionUrgency' title: type: string body: type: string supporting_message: anyOf: - type: string - type: 'null' reason_context: anyOf: - $ref: '#/components/schemas/ReasonContext' - type: 'null' destination: $ref: '#/components/schemas/Destination' ReasonContext: type: object required: - family - state properties: family: $ref: '#/components/schemas/AttentionFamily' state: type: string enum: - absent - stale - degraded - weakened - unvalidated reason: anyOf: - type: string - type: 'null' Destination: type: object required: - kind - label - disabled properties: kind: $ref: '#/components/schemas/DestinationKind' label: type: string url: anyOf: - type: string - type: 'null' disabled: type: boolean helper_text: anyOf: - type: string - type: 'null' WorkspaceCalmness: type: object required: - is_calm - checked_domains - title - body - next_action properties: is_calm: type: boolean checked_domains: type: array items: $ref: '#/components/schemas/CalmnessCheckedDomain' title: type: string body: type: string next_action: $ref: '#/components/schemas/Destination'