--- description: "Task list for 098-settings-slices-v1-backup-drift-ops" --- # Tasks: 098 — Settings Slices v1 (Backup + Drift + Operations) **Input**: Design documents from `/specs/098-settings-slices-v1-backup-drift-ops/` (spec.md, plan.md) **Tests**: REQUIRED (Pest) — runtime behavior changes. **Scope**: workspace-level settings; DB-only rendering; no Graph calls. ## Phase 1: Setup (Shared Infrastructure) - [X] T001 Confirm feature branch + clean working tree in specs/098-settings-slices-v1-backup-drift-ops/spec.md - [X] T002 Verify Settings Foundation dependency is present by locating SettingsRegistry in app/Support/Settings/SettingsRegistry.php - [X] T003 [P] Capture baseline behaviors + constants and record them in specs/098-settings-slices-v1-backup-drift-ops/plan.md by reviewing app/Jobs/ApplyBackupScheduleRetentionJob.php, app/Services/Drift/DriftFindingGenerator.php, app/Jobs/PruneOldOperationRunsJob.php, routes/console.php --- ## Phase 2: Foundational (Blocking Prerequisites) **Purpose**: Shared settings primitives + Workspace Settings page patterns used by all slices. - [X] T004 Update Settings registry validation to match spec (max 365) in app/Support/Settings/SettingsRegistry.php - [X] T005 [P] Add per-setting reset UX pattern scaffolding (no global reset) in app/Filament/Pages/Settings/WorkspaceSettings.php - [X] T006 Add “unset input + helper text shows default/effective” support in app/Filament/Pages/Settings/WorkspaceSettings.php - [X] T007 [P] Update existing workspace settings RBAC tests for new per-setting reset actions in tests/Feature/SettingsFoundation/WorkspaceSettingsViewOnlyTest.php - [X] T008 [P] Update existing manage test to assert per-setting reset (not header reset) in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php **Checkpoint**: Workspace Settings page supports per-setting resets and unset presentation without changing behavior. --- ## Phase 3: User Story 1 — Backup retention defaults (Priority: P1) 🎯 MVP **Goal**: Workspace overrides for backup retention default + min floor; job clamps effective keep-last to floor. **Independent Test**: Run ApplyBackupScheduleRetentionJob behavior with/without workspace overrides and verify clamping. ### Tests (US1) - [X] T009 [P] [US1] Add/extend retention job tests to cover default + floor clamp in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php - [X] T010 [P] [US1] Add validation tests for backup settings bounds (1..365) via SettingsWriter in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php ### Implementation (US1) - [X] T011 [US1] Register backup floor setting and tighten keep-last rules (1..365) in app/Support/Settings/SettingsRegistry.php - [X] T012 [US1] Extend Workspace Settings UI: Backup section adds `backup.retention_keep_last_default` + `backup.retention_min_floor` fields with per-setting reset actions in app/Filament/Pages/Settings/WorkspaceSettings.php - [X] T013 [US1] Update Workspace Settings save logic: empty field triggers reset (delete override) instead of persisting null in app/Filament/Pages/Settings/WorkspaceSettings.php - [X] T014 [US1] Apply floor clamping for both schedule override and resolved default in app/Jobs/ApplyBackupScheduleRetentionJob.php --- ## Phase 4: User Story 2 — Drift severity mapping (Priority: P2) **Goal**: Workspace-level `finding_type → severity` mapping with default `medium` and strict validation; normalize severities to lowercase. **Independent Test**: Generate drift findings and assert severity uses mapping when present; saving invalid mapping is rejected. ### Tests (US2) - [X] T015 [P] [US2] Add drift generator test asserting default severity remains medium when no mapping set in tests/Feature/Drift/DriftPolicySnapshotDriftDetectionTest.php - [X] T016 [P] [US2] Add drift generator test asserting mapped severity is applied when mapping exists in tests/Feature/Drift/DriftPolicySnapshotDriftDetectionTest.php - [X] T017 [P] [US2] Add settings save validation tests for drift severity mapping JSON shape + allowed values in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php ### Implementation (US2) - [X] T018 [US2] Add `Finding::SEVERITY_CRITICAL` constant and ensure severity domain remains stable in app/Models/Finding.php - [X] T019 [US2] Extend finding severity badge mapping to include `critical` (BADGE-001 compliant) in app/Support/Badges/Domains/FindingSeverityBadge.php - [X] T020 [US2] Register `drift.severity_mapping` setting with JSON validation + canonical normalization (lowercase values, string keys) in app/Support/Settings/SettingsRegistry.php - [X] T021 [US2] Update DriftFindingGenerator to resolve workspace severity mapping (via SettingsResolver in workspace context) and apply mapped severity (fallback medium) in app/Services/Drift/DriftFindingGenerator.php - [X] T022 [US2] Extend Workspace Settings UI: Drift section adds JSON textarea for `drift.severity_mapping` with unset behavior + per-setting reset in app/Filament/Pages/Settings/WorkspaceSettings.php --- ## Phase 5: User Story 3 — Operations retention + stuck threshold (Priority: P3) **Goal**: Workspace-level `operations.operation_run_retention_days` drives pruning; `operations.stuck_run_threshold_minutes` is stored only. **Independent Test**: Create old/new OperationRuns across workspaces and verify prune respects per-workspace retention; stuck threshold persists and reloads. ### Tests (US3) - [X] T023 [P] [US3] Update pruning schedule test to match new job behavior (per-workspace retention) in tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php - [X] T024 [P] [US3] Add prune job test verifying per-workspace retention cutoff using workspace settings in tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php - [X] T025 [P] [US3] Add workspace settings save/reset tests for operations keys in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php ### Implementation (US3) - [X] T026 [US3] Register operations settings keys with correct bounds in app/Support/Settings/SettingsRegistry.php - [X] T027 [US3] Refactor PruneOldOperationRunsJob to compute retention per workspace (SettingsResolver + Workspace iteration) and prune by workspace_id in app/Jobs/PruneOldOperationRunsJob.php - [X] T028 [US3] Ensure scheduler continues to enqueue prune job without needing a parameter in routes/console.php - [X] T029 [US3] Extend Workspace Settings UI: Operations section adds `operation_run_retention_days` + `stuck_run_threshold_minutes` fields with unset behavior + per-setting reset in app/Filament/Pages/Settings/WorkspaceSettings.php --- ## Phase 6: Polish & Cross-Cutting Concerns - [X] T030 [P] Confirm multi-key save emits one audit entry per key changed by reviewing app/Services/Settings/SettingsWriter.php and Workspace Settings save flow in app/Filament/Pages/Settings/WorkspaceSettings.php - [X] T031 [P] Run Pint formatting on touched files via vendor/bin/sail bin pint --dirty (e.g., app/Filament/Pages/Settings/WorkspaceSettings.php, app/Support/Settings/SettingsRegistry.php, app/Jobs/ApplyBackupScheduleRetentionJob.php, app/Services/Drift/DriftFindingGenerator.php, app/Jobs/PruneOldOperationRunsJob.php) - [X] T032 Run focused settings UI tests via vendor/bin/sail artisan test --compact tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php - [X] T033 Run focused drift tests via vendor/bin/sail artisan test --compact tests/Feature/Drift/DriftPolicySnapshotDriftDetectionTest.php - [X] T034 Run focused pruning tests via vendor/bin/sail artisan test --compact tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php - [X] T035 [P] Add an automated regression test asserting per-setting reset actions require confirmation (destructive-like) in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php - [X] T036 [P] Add an automated regression test asserting multi-key save produces one audit entry per key changed (FR-008a) in tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php --- ## Dependencies & Execution Order - Setup (Phase 1) → Foundational (Phase 2) → US1 (Phase 3) → US2 (Phase 4) → US3 (Phase 5) → Polish (Phase 6) ## Parallel Execution Examples ```text US1 parallel example: T009 + T011 + T014 US2 parallel example: T015 + T018 + T021 US3 parallel example: T023 + T027 + T029 ``` ## Implementation Strategy - MVP = US1 only (backup defaults + floor clamp) with updated Workspace Settings UX and tests. - Then US2 (drift mapping) and US3 (operations retention/threshold) as independent increments.