TenantAtlas/specs/186-tenant-registry-recovery-triage/data-model.md
ahmido 9fbd3e5ec7 Spec 186: implement tenant registry recovery triage (#217)
## Summary
- turn the tenant registry into a workspace-scoped recovery triage surface with backup posture and recovery evidence columns
- preserve workspace overview backup and recovery drilldown intent by routing multi-tenant cases into filtered tenant registry slices
- add the Spec 186 planning artifacts, focused regression coverage, and shared triage presentation helpers

## Testing
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantRegistryRecoveryTriageTest.php tests/Feature/Filament/WorkspaceOverviewSummaryMetricsTest.php tests/Feature/Filament/WorkspaceOverviewDrilldownContinuityTest.php tests/Feature/Filament/TenantResourceIndexIsWorkspaceScopedTest.php tests/Feature/Filament/WorkspaceOverviewAuthorizationTest.php tests/Feature/Guards/ActionSurfaceContractTest.php tests/Feature/Guards/FilamentTableStandardsGuardTest.php`

## Notes
- no schema change
- no new persisted recovery truth
- branch includes the full Spec 186 spec, plan, research, data model, contract, quickstart, and tasks artifacts

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #217
2026-04-09 19:20:48 +00:00

6.4 KiB
Raw Blame History

Data Model: Tenant Registry Recovery Triage

Overview

Spec 186 adds no new persisted entity. The feature is a derived registry-view slice over existing tenant, backup-health, and recovery-evidence truth.

Existing Persisted Inputs

Tenant

  • Purpose: Canonical tenant identity and lifecycle record for the workspace-scoped registry.
  • Key fields:
    • id
    • workspace_id
    • external_id
    • name
    • tenant_id
    • environment
    • status
    • domain
    • created_at
  • Derived fields already used by the registry:
    • policies_count
    • last_policy_sync_at
  • Relationships:
    • belongs to one workspace
    • has many memberships
    • has many policies
    • has many backup sets
    • has many restore runs

TenantBackupHealthAssessment

  • Purpose: Existing derived tenant backup-health truth used by dashboard and workspace overview.
  • Persistence: Not persisted.
  • Key fields:
    • tenantId
    • posture = absent | stale | degraded | healthy
    • primaryReason = no_backup_basis | latest_backup_stale | latest_backup_degraded | schedule_follow_up | null
    • headline
    • supportingMessage
    • latestRelevantBackupSetId
    • latestRelevantCompletedAt
    • positiveClaimBoundary
    • primaryActionTarget
  • Behavioral role in Spec 186:
    • provides the registrys Backup posture value
    • provides the backup-attention set for workspace drilldown intent
    • contributes to triage rank

Dashboard Recovery Evidence Payload

  • Purpose: Existing derived tenant recovery-evidence truth built from restore history.
  • Persistence: Not persisted.
  • Key fields:
    • backup_posture
    • overview_state = unvalidated | weakened | no_recent_issues_visible
    • headline
    • summary
    • claim_boundary
    • latest_relevant_restore_run_id
    • latest_relevant_attention_state
    • reason = no_history | failed | partial | completed_with_follow_up | no_recent_issues_visible
  • Behavioral role in Spec 186:
    • provides the registrys Recovery evidence value
    • provides the recovery-attention set for workspace drilldown intent
    • contributes to triage rank

New Derived Read Models

TenantRegistryTriageRow

  • Purpose: Request-scoped row projection for the tenant registry.
  • Persistence: Not persisted.
  • Fields:
    • tenant_id
    • tenant_route_key
    • tenant_name
    • environment
    • lifecycle_status
    • policies_count
    • last_policy_sync_at
    • backup_posture
    • backup_reason
    • recovery_evidence
    • recovery_reason
    • triage_rank
    • next_action_url
  • Validation rules:
    • backup_posture must come directly from TenantBackupHealthAssessment::posture
    • recovery_evidence must come directly from dashboardRecoveryEvidenceForTenants(...)[tenant]['overview_state']
    • triage_rank must be derived from the shared registry priority table, not hard-coded independently per column or filter
    • next_action_url must resolve to an allowed destination in the current workspace and tenant scope

TenantRegistryTriageIntent

  • Purpose: Query-string driven list intent for opening the registry in a prefiltered triage state.
  • Persistence: Not persisted.
  • Fields:
    • backup_posture[] optional array of absent | stale | degraded | healthy
    • recovery_evidence[] optional array of weakened | unvalidated | no_recent_issues_visible
    • triage_sort optional enum default | worst_first
  • Validation rules:
    • every backup_posture[] entry must be one of the canonical backup posture values
    • every recovery_evidence[] entry must be one of the canonical recovery-evidence values
    • if backup_posture[] is present for workspace backup attention, its intended set is absent, stale, and degraded
    • if recovery_evidence[] is present for workspace recovery attention, its intended set is weakened and unvalidated
    • workspace drilldowns that need weak-first behavior must set triage_sort=worst_first explicitly; manual registry filtering alone does not change the default calm-browsing sort

WorkspaceAttentionDestination

  • Purpose: Derived navigation target from workspace overview metrics or attention items.
  • Persistence: Not persisted.
  • Fields:
    • kind = existing workspace-drilldown contract value already used by the current widgets; unchanged by this feature
    • url
    • tenant_route_key optional
    • filters optional exact registry intent payload
  • Validation rules:
    • one affected visible tenant resolves to the existing single-tenant dashboard kind and opens /admin/t/{tenant}
    • more than one affected visible tenant preserves the existing multi-tenant admin-plane kind while url now opens filtered /admin/tenants
    • any registry destination must carry exact posture filter semantics, not a vague needs attention label

Relationships

  • Tenant has one derived TenantBackupHealthAssessment in registry context.
  • Tenant has one derived dashboard recovery-evidence payload in registry context.
  • TenantRegistryTriageRow combines one Tenant with one backup-health assessment and one recovery-evidence payload.
  • WorkspaceAttentionDestination references either one specific tenant or one registry triage intent, but never both at once.

Triage Ranking Model

Canonical rank tiers

  1. backup_posture = absent
  2. recovery_evidence = weakened
  3. backup_posture = stale
  4. recovery_evidence = unvalidated
  5. backup_posture = degraded
  6. calm rows: backup_posture = healthy and recovery_evidence = no_recent_issues_visible

Tie-breaker

  • Rows inside the same tier are secondarily ordered by tenant_name ascending.

Rule for dual-signal tenants

  • If a tenant is weak in both domains, the highest active tier governs its triage_rank, but both posture signals remain visible in the row.

State Transitions

There are no persisted state transitions in this feature.

Derived transition rules

  • A registry row moves between triage tiers only when the underlying backup-health or recovery-evidence truth changes.
  • Registry intent transitions are URL-driven:
    • unfiltered registry
    • backup-filtered registry
    • recovery-filtered registry
    • manually refined registry
    • cleared back to the default registry view

Notes

  • The registry continues to be the source of truth for tenant identity and lifecycle metadata in workspace context.
  • The registry does not become the source of truth for full backup diagnostics, restore proof, or overall recoverability.