TenantAtlas/specs/184-dashboard-recovery-honesty/tasks.md
2026-04-09 01:19:36 +02:00

205 lines
14 KiB
Markdown

# Tasks: Dashboard Recovery Posture Honesty
**Input**: Design documents from `/specs/184-dashboard-recovery-honesty/`
**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/dashboard-recovery-posture.openapi.yaml`, `quickstart.md`
**Tests**: Required. This feature changes runtime behavior on existing Filament and Livewire surfaces, so Pest coverage must be added or extended before implementation is considered complete.
**Organization**: Tasks are grouped by user story so each slice stays independently testable, with the recommended delivery order `US1 -> US2 -> US3` because all three stories touch the same dashboard and restore-history seams.
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Prepare reusable test data states shared by all dashboard recovery-posture scenarios.
- [X] T001 [P] Add preview-only, failed, partial, completed-with-follow-up, and completed recovery-posture fixture states in `apps/platform/database/factories/RestoreRunFactory.php`
- [X] T002 [P] Add recent and stale completed backup fixture states in `apps/platform/database/factories/BackupSetFactory.php`
**Checkpoint**: Shared test fixtures are ready for all stories.
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Build the single restore-history derivation seam that all dashboard recovery-posture surfaces depend on.
**⚠️ CRITICAL**: No user story work should start before this phase is complete.
- [X] T003 Add unit regressions for preview exclusion, latest-run precedence, weak-history precedence, and completed-history fallback in `apps/platform/tests/Unit/Support/RestoreSafety/RestoreResultAttentionTest.php`
- [X] T004 Implement tenant-scoped relevant restore-history selection and dashboard overview-state derivation in `apps/platform/app/Support/RestoreSafety/RestoreSafetyResolver.php`
**Checkpoint**: Relevant restore history is derived from one authoritative seam and covered by unit tests.
---
## Phase 3: User Story 1 - See Unvalidated Recovery Confidence Early (Priority: P1) 🎯 MVP
**Goal**: Make the tenant dashboard show that healthy backup inputs do not equal validated recovery posture when relevant restore history is absent.
**Independent Test**: Render the tenant dashboard with healthy backup fixtures and no executed, non-preview restore history, then verify the KPI strip and Needs Attention surfaces show an explicit unvalidated recovery signal instead of an all-clear.
### Tests for User Story 1
- [X] T005 [P] [US1] Add healthy-backups-with-no-history KPI regression coverage in `apps/platform/tests/Feature/Filament/DashboardKpisWidgetTest.php`
- [X] T006 [P] [US1] Add no-history healthy-boundary regression coverage in `apps/platform/tests/Feature/Filament/NeedsAttentionWidgetTest.php`
### Implementation for User Story 1
- [X] T007 [P] [US1] Update `apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php` to keep `Backup posture` limited to backup-input truth, append the positive claim boundary, and add an `unvalidated` recovery-evidence KPI with a restore-history drillthrough
- [X] T008 [P] [US1] Update `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php` to surface missing relevant restore history and suppress an unqualified healthy fallback when recovery evidence is absent
**Checkpoint**: User Story 1 is independently functional and shows honest no-history recovery posture on the tenant dashboard.
---
## Phase 4: User Story 2 - Escalate Weak Restore History on Overview (Priority: P2)
**Goal**: Make recent failed, partial, or follow-up restore outcomes affect overview trust immediately instead of hiding only in restore-history details.
**Independent Test**: Render the tenant dashboard with recent failed, partial, and completed-with-follow-up restore fixtures and verify the overview surfaces show weakened confidence, while a calm `no recent issues visible` state appears only for recent completed restore history.
### Tests for User Story 2
- [X] T009 [P] [US2] Add weak-history KPI regression coverage for failed, partial, follow-up, and calm completed restore outcomes in `apps/platform/tests/Feature/Filament/DashboardKpisWidgetTest.php`
- [X] T010 [P] [US2] Add weak-history attention and `no recent issues visible` coverage in `apps/platform/tests/Feature/Filament/NeedsAttentionWidgetTest.php`
- [X] T011 [P] [US2] Add dashboard-linked restore-result confirmation coverage for problematic restore runs in `apps/platform/tests/Feature/Filament/RestoreResultAttentionSurfaceTest.php`
### Implementation for User Story 2
- [X] T012 [P] [US2] Update `apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php` to derive `weakened` and `no_recent_issues_visible` recovery-evidence states from `RestoreSafetyResolver` output
- [X] T013 [P] [US2] Update `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php` to surface failed, partial, and `completed_with_follow_up` restore attention using canonical summaries and next actions
- [X] T014 [P] [US2] Update `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php` to add a `no_recent_issues_visible` healthy-check that preserves the non-proof boundary for calm recent restore history
- [X] T015 [P] [US2] Update `apps/platform/app/Filament/Resources/RestoreRunResource.php` to expose a default-visible result-attention summary fact on restore-run list rows
- [X] T016 [P] [US2] Update `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php` to keep restore-result attention copy aligned with dashboard-linked failure, partial, and follow-up reasons
**Checkpoint**: User Story 2 is independently functional and weak restore evidence is visible on overview and restore-run confirmation surfaces.
---
## Phase 5: User Story 3 - Preserve Honest Drilldowns and RBAC Boundaries (Priority: P3)
**Goal**: Keep dashboard recovery signals, restore-history drilldowns, and RBAC outcomes aligned so missing access never makes the overview read more confidently than the evidence allows.
**Independent Test**: Open dashboard recovery signals as an owner, a readonly tenant member, and a non-member; verify list and detail drilldowns preserve the same reason, readonly members keep inspect access with disabled mutations, and non-members still receive deny-as-not-found behavior.
### Tests for User Story 3
- [X] T017 [P] [US3] Create no-history and list-fallback continuity coverage in `apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php`
- [X] T018 [P] [US3] Create readonly, capability-denied, and non-member recovery-posture visibility coverage in `apps/platform/tests/Feature/Rbac/DashboardRecoveryPostureVisibilityTest.php`
- [X] T019 [P] [US3] Extend restore-run enforcement coverage for readonly inspect access, capability-denied drillthrough 403 responses, disabled mutations, and deny-as-not-found semantics in `apps/platform/tests/Feature/Filament/RestoreRunUiEnforcementTest.php`
### Implementation for User Story 3
- [X] T020 [P] [US3] Update `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php` to accept `recovery_posture_reason` and render continuity subheadings for dashboard fallbacks
- [X] T021 [P] [US3] Update `apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php` to fall back from missing or brittle direct restore-run links to canonical restore-run list URLs with continuity context
- [X] T022 [P] [US3] Update `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php` to mirror the same fallback and disabled-link behavior for recovery-confidence actions
- [X] T023 [P] [US3] Update `apps/platform/app/Filament/Resources/RestoreRunResource.php` and `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php` to preserve truthful restore-history drillthroughs and 403 capability denials for in-scope members without changing existing mutation permissions
**Checkpoint**: User Story 3 is independently functional and dashboard-to-restore-history continuity stays honest across RBAC outcomes.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Final quality checks that span multiple stories.
- [X] T024 Verify `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php` remains unchanged by this slice so no tenant-linked recovery posture summary is introduced outside the tenant dashboard
- [X] T025 Review operator-facing recovery copy in `apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php`, `apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php`, `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php`, and `apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php` to remove any `recovery proven`, `recovery guaranteed`, or equivalent overclaim language
- [X] T026 [P] Add query-shape regression coverage for the 10-candidate cap and no N+1 rendering across the tenant dashboard and restore-run list surfaces in `apps/platform/tests/Feature/Filament/DashboardRecoveryPosturePerformanceTest.php`
- [X] T027 [P] Run formatting and the focused verification workflow from `specs/184-dashboard-recovery-honesty/quickstart.md` against `apps/platform/tests/Unit/Support/RestoreSafety/RestoreResultAttentionTest.php`, `apps/platform/tests/Feature/Filament/DashboardKpisWidgetTest.php`, `apps/platform/tests/Feature/Filament/NeedsAttentionWidgetTest.php`, `apps/platform/tests/Feature/Filament/RestoreResultAttentionSurfaceTest.php`, `apps/platform/tests/Feature/Filament/RestoreRunUiEnforcementTest.php`, `apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php`, `apps/platform/tests/Feature/Filament/DashboardRecoveryPosturePerformanceTest.php`, and `apps/platform/tests/Feature/Rbac/DashboardRecoveryPostureVisibilityTest.php`
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies; can start immediately.
- **Foundational (Phase 2)**: Depends on Setup completion; blocks all user stories.
- **User Story 1 (Phase 3)**: Depends on Foundational completion; recommended MVP cut.
- **User Story 2 (Phase 4)**: Depends on User Story 1 because it extends the same dashboard recovery-evidence seams in `DashboardKpis.php` and `NeedsAttention.php`.
- **User Story 3 (Phase 5)**: Depends on User Story 2 because it aligns continuity and RBAC behavior for both no-history and weak-history overview signals.
- **Polish (Phase 6)**: Depends on all desired user stories being complete.
### User Story Dependencies
- **US1**: No dependencies beyond Foundational.
- **US2**: Builds on the recovery-evidence KPI and attention seams introduced in US1.
- **US3**: Builds on the drillthrough targets and recovery-evidence states introduced in US1 and US2.
### Within Each User Story
- Write the story tests first and confirm they fail before implementation.
- Update dashboard derivation or resource behavior before adjusting cross-surface copy.
- Keep each story shippable on its own before moving to the next priority.
### Parallel Opportunities
- `T001` and `T002` can run in parallel.
- Within US1, `T005` and `T006` can run in parallel, then `T007` and `T008` can run in parallel.
- Within US2, `T009`, `T010`, and `T011` can run in parallel, then `T012`, `T013`, `T014`, `T015`, and `T016` can be split across contributors.
- Within US3, `T017`, `T018`, and `T019` can run in parallel, then `T020`, `T021`, `T022`, and `T023` can be split across contributors.
---
## Parallel Example: User Story 1
```bash
# Parallel test pass for US1
T005 Add healthy-backups-with-no-history KPI regression coverage in apps/platform/tests/Feature/Filament/DashboardKpisWidgetTest.php
T006 Add no-history healthy-boundary regression coverage in apps/platform/tests/Feature/Filament/NeedsAttentionWidgetTest.php
# Parallel implementation pass for US1
T007 Update apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php
T008 Update apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php
```
## Parallel Example: User Story 2
```bash
# Parallel test pass for US2
T009 Add weak-history KPI regression coverage in apps/platform/tests/Feature/Filament/DashboardKpisWidgetTest.php
T010 Add weak-history attention coverage in apps/platform/tests/Feature/Filament/NeedsAttentionWidgetTest.php
T011 Add restore-result confirmation coverage in apps/platform/tests/Feature/Filament/RestoreResultAttentionSurfaceTest.php
# Parallel implementation pass for US2
T012 Update apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php
T013 Update apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php
T014 Update apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php
T015 Update apps/platform/app/Filament/Resources/RestoreRunResource.php
T016 Update apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php
```
## Parallel Example: User Story 3
```bash
# Parallel test pass for US3
T017 Create apps/platform/tests/Feature/Filament/RestoreRunListContinuityTest.php
T018 Create apps/platform/tests/Feature/Rbac/DashboardRecoveryPostureVisibilityTest.php
T019 Extend apps/platform/tests/Feature/Filament/RestoreRunUiEnforcementTest.php
# Parallel implementation pass for US3
T020 Update apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ListRestoreRuns.php
T021 Update apps/platform/app/Filament/Widgets/Dashboard/DashboardKpis.php
T022 Update apps/platform/app/Filament/Widgets/Dashboard/NeedsAttention.php
T023 Update apps/platform/app/Filament/Resources/RestoreRunResource.php and apps/platform/app/Filament/Resources/RestoreRunResource/Pages/ViewRestoreRun.php
```
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 1: Setup.
2. Complete Phase 2: Foundational derivation.
3. Complete Phase 3: User Story 1.
4. Validate the no-history dashboard truth using the focused tests in `quickstart.md`.
5. Stop and review the wording before widening the slice.
### Incremental Delivery
1. Ship US1 to stop the highest-risk overclaim on the tenant dashboard.
2. Add US2 to elevate weak restore history into the same overview surfaces.
3. Add US3 to keep list or detail drilldowns and RBAC outcomes aligned with the dashboard summary.
4. Finish with the focused formatting and verification pass from Phase 6.