## Summary - add a dedicated Recovery Readiness dashboard widget for backup posture and recovery evidence - group Needs Attention items by domain and elevate the recovery call-to-action - align restore-run and recovery posture tests with the extracted widget and continuity flows - include the related spec artifacts for 184-dashboard-recovery-honesty ## Verification - `cd /Users/ahmeddarrazi/Documents/projects/TenantAtlas/apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `cd /Users/ahmeddarrazi/Documents/projects/TenantAtlas/apps/platform && ./vendor/bin/sail artisan test --compact --filter="DashboardKpisWidget|DashboardRecoveryPosture|TenantDashboardDbOnly|TenantpilotSeedBackupHealthBrowserFixtureCommand|NeedsAttentionWidget"` - browser smoke verified on the calm, unvalidated, and weakened dashboard states ## Notes - Livewire v4.0+ compliant with Filament v5 - no panel provider changes; Laravel 11+ provider registration remains in `bootstrap/providers.php` - Recovery Readiness stays within the existing tenant dashboard asset strategy; no new Filament asset registration required Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #215
121 lines
6.4 KiB
Markdown
121 lines
6.4 KiB
Markdown
# Data Model: Dashboard Recovery Posture Honesty
|
|
|
|
## Existing Evidence Models
|
|
|
|
### TenantBackupHealthAssessment
|
|
|
|
Existing derived tenant-level backup-input assessment from `TenantBackupHealthResolver`.
|
|
|
|
| Field | Type | Meaning |
|
|
|------|------|---------|
|
|
| `tenantId` | integer | Tenant scope for the assessment |
|
|
| `posture` | string | `absent`, `stale`, `degraded`, or `healthy` backup-input posture |
|
|
| `primaryReason` | string nullable | Why the current backup-input posture is not calmly healthy |
|
|
| `headline` | string | Operator-facing headline for the backup-input truth |
|
|
| `supportingMessage` | string nullable | Supporting backup-health explanation |
|
|
| `healthyClaimAllowed` | boolean | Whether the surface may speak positively about backup-input health |
|
|
| `primaryActionTarget` | action target nullable | Canonical backup drillthrough |
|
|
| `positiveClaimBoundary` | string | Canonical statement that backup health reflects backup inputs only and does not prove restore success |
|
|
|
|
### RestoreRun
|
|
|
|
Existing tenant-owned operational record of restore activity.
|
|
|
|
| Field | Type | Meaning |
|
|
|------|------|---------|
|
|
| `id` | integer | Restore-run identity |
|
|
| `tenant_id` | integer | Tenant scope |
|
|
| `backup_set_id` | integer nullable | Backup set used for the run |
|
|
| `status` | string | Restore lifecycle status |
|
|
| `is_dry_run` | boolean | Whether the record is preview-only |
|
|
| `results` | array/json | Item-, foundation-, and assignment-level execution outcomes |
|
|
| `metadata` | array/json | Additional execution and preview metadata, including `non_applied` and scope basis |
|
|
| `completed_at` | datetime nullable | Terminal completion timestamp |
|
|
| `operationRun` | relation nullable | Linked `OperationRun` for umbrella execution outcome |
|
|
|
|
### RestoreResultAttention
|
|
|
|
Existing per-run derived truth from `RestoreSafetyResolver::resultAttentionForRun(...)`.
|
|
|
|
| State | Follow-up required | Meaning |
|
|
|------|--------------------|---------|
|
|
| `not_executed` | no | Preview-only or not-yet-executed record; proves preview truth only |
|
|
| `failed` | yes | Execution failed; no recovery claim can be made |
|
|
| `partial` | yes | Execution reached terminal state but some items or assignments failed or only partially applied |
|
|
| `completed_with_follow_up` | yes | Execution completed, but skipped or non-applied work still weakens confidence |
|
|
| `completed` | no | No visible follow-up remains, but tenant-wide recovery is still not proven |
|
|
|
|
Relevant fields carried by the value object:
|
|
|
|
| Field | Type | Meaning |
|
|
|------|------|---------|
|
|
| `state` | string | One of the five result-attention states above |
|
|
| `summary` | string | Operator-facing explanation of the outcome |
|
|
| `followUpRequired` | boolean | Whether the result weakens confidence or needs action |
|
|
| `primaryNextAction` | string | Recommended next action for the run |
|
|
| `recoveryClaimBoundary` | string | Canonical claim-boundary identifier for the run outcome |
|
|
| `tone` | string | Summary tone for UI presentation |
|
|
|
|
## Derived Surface Projection
|
|
|
|
### Recovery Evidence Summary
|
|
|
|
This spec does **not** add a new persisted entity. It adds a derived tenant-level dashboard projection that combines existing backup health and restore evidence at render time.
|
|
|
|
| Field | Type | Persisted | Meaning |
|
|
|------|------|-----------|---------|
|
|
| `tenantId` | integer | no | Tenant scope |
|
|
| `backupPosture` | string | no | Current `TenantBackupHealthAssessment.posture` |
|
|
| `relevantRestoreHistoryPresent` | boolean | no | Whether the tenant has any executed, non-preview restore history |
|
|
| `latestRelevantRestoreRunId` | integer nullable | no | The most recent executed restore run relevant to overview continuity |
|
|
| `latestRelevantAttentionState` | string nullable | no | Result-attention state for the latest relevant run |
|
|
| `overviewState` | string | no | Canonical state key: `unvalidated`, `weakened`, or `no_recent_issues_visible` |
|
|
| `headline` | string | no | Operator-facing dashboard headline for the recovery-evidence condition |
|
|
| `summary` | string | no | Supporting summary text for the state |
|
|
| `claimBoundary` | string | no | Text that prevents the summary from becoming a proof claim |
|
|
| `action` | object nullable | no | Nested action payload with `label`, `url`, `disabled`, and `helperText`, matching the contract `ActionLink` shape |
|
|
|
|
### Overview State Rules
|
|
|
|
| Overview state | Entry rule | Required surface effect |
|
|
|------|------------|-------------------------|
|
|
| `unvalidated` | No executed, non-preview restore history exists for the tenant | Dashboard must show that recovery confidence is unvalidated and provide a next action into restore history |
|
|
| `weakened` | Latest relevant restore history resolves to `failed`, `partial`, or `completed_with_follow_up` | Needs Attention must surface the weakened condition and link to the exact run or canonical restore-run list fallback |
|
|
| `no_recent_issues_visible` | Relevant restore history exists and the latest relevant attention is `completed` | The dashboard may say no recent restore issues are visible, but must preserve the non-proof boundary |
|
|
|
|
Operator-facing copy may say that recovery evidence is not yet known, but the canonical derived state remains `unvalidated`.
|
|
|
|
### Non-qualifying restore records
|
|
|
|
The following records do **not** count as relevant restore history for overview confidence:
|
|
|
|
- `is_dry_run = true`
|
|
- `status in [draft, scoped, checked, previewed]`
|
|
- Any record whose `RestoreResultAttention.state` is `not_executed`
|
|
|
|
## Relationships
|
|
|
|
| Source | Relationship | Target | Use in this spec |
|
|
|------|--------------|--------|------------------|
|
|
| Tenant | has many | BackupSet | Existing backup-input truth via `TenantBackupHealthResolver` |
|
|
| Tenant | has many | RestoreRun | Existing restore-history truth used for overview evidence |
|
|
| RestoreRun | belongs to | BackupSet | Supports drillthrough context |
|
|
| RestoreRun | optionally belongs to | OperationRun | Contributes operation outcome to `RestoreResultAttention` |
|
|
|
|
## Derived Continuity Context
|
|
|
|
The canonical restore-run list receives a **non-persisted page context** from the dashboard for fallback continuity.
|
|
|
|
| Field | Type | Meaning |
|
|
|------|------|---------|
|
|
| `recovery_posture_reason` | query string | Why the user arrived on the restore-run list from the dashboard |
|
|
|
|
Suggested reason values:
|
|
|
|
- `no_history`
|
|
- `failed`
|
|
- `partial`
|
|
- `completed_with_follow_up`
|
|
- `no_recent_issues_visible`
|
|
|
|
These are list-continuity reasons only. They are not new persisted domain states. |