--- description: "Task list for Operational Controls" --- # Tasks: Operational Controls **Input**: Design documents from `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/` **Prerequisites**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/plan.md` (required), `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/spec.md` (required), `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/research.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/data-model.md`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/contracts/operational-controls.contract.yaml`, `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/242-operational-controls/quickstart.md` **Tests**: REQUIRED (Pest) for all runtime behavior changes in this slice. Keep proof in Unit + Feature lanes only. **Operations**: Allowed starts must continue to reuse the shared OperationRun start UX. Blocked starts for `findings.lifecycle.backfill` and `restore.execute` must create no queued execution `OperationRun`, no queued execution `RestoreRun`, no queued job, and no provider-backed execution. Control activation governs new starts only and must not retroactively mutate already accepted runs. **RBAC**: Management is platform-plane only under `/system`; affected execution surfaces stay on `/system` or `/admin/t/{tenant}`. Non-members remain `404`, members without the underlying capability remain `403`, and entitled users blocked only by an active operational control get explicit paused-state feedback. **Organization**: Tasks are grouped by user story so each slice remains independently testable and bounded to the first-slice controls `findings.lifecycle.backfill` and `restore.execute`. ## Phase 1: Setup (Shared Infrastructure) **Purpose**: Prepare the local implementation lane and feature-local file layout without widening scope. - [x] T001 Start the local Sail environment with `cd apps/platform && ./vendor/bin/sail up -d` (script: `apps/platform/vendor/bin/sail`) - [x] T002 Create the bounded feature-local directories under `apps/platform/app/Support/OperationalControls/`, `apps/platform/tests/Unit/Support/OperationalControls/`, `apps/platform/tests/Feature/System/OpsControls/`, `apps/platform/tests/Feature/System/OpsRunbooks/`, `apps/platform/tests/Feature/Findings/`, `apps/platform/tests/Feature/Restore/`, and `apps/platform/tests/Feature/OperationalControls/` --- ## Phase 2: Foundational (Blocking Prerequisites) **Purpose**: Add the single new persistence model, the bounded operational-controls support namespace, and the shared capability/audit plumbing that all stories depend on. **Checkpoint**: The repo has one `operational_control_activations` truth, one evaluator/catalog/decision support path, one platform capability, and shared audit IDs before any surface integration begins. - [x] T003 Create the activation migration in `apps/platform/database/migrations/*_create_operational_control_activations_table.php`, including partial unique indexes for active global and workspace-scoped rows - [x] T004 Create the activation model in `apps/platform/app/Models/OperationalControlActivation.php` - [x] T005 [P] Create the activation factory in `apps/platform/database/factories/OperationalControlActivationFactory.php` - [x] T006 [P] Create the bounded catalog for `findings.lifecycle.backfill` and `restore.execute` in `apps/platform/app/Support/OperationalControls/OperationalControlCatalog.php` - [x] T007 [P] Create the derived decision object in `apps/platform/app/Support/OperationalControls/OperationalControlDecision.php` - [x] T008 Create the shared evaluator for global and workspace-targeted activations, including foundational global-first precedence and expiry handling, in `apps/platform/app/Support/OperationalControls/OperationalControlEvaluator.php` - [x] T009 [P] Add the platform management capability for the controls surface in `apps/platform/app/Support/Auth/PlatformCapabilities.php` and grant it in `apps/platform/database/seeders/PlatformUserSeeder.php` for the seeded local operator path - [x] T010 [P] Add stable audit action IDs for pause, update, resume, and execution-blocked events in `apps/platform/app/Support/Audit/AuditActionId.php` - [x] T011 Extend canonical audit plumbing for control scope, reason, expiry, requested-scope metadata, and blocked-execution evidence using `apps/platform/app/Services/Audit/AuditRecorder.php` for global control changes and blocked system all-tenant attempts and `apps/platform/app/Services/Audit/WorkspaceAuditLogger.php` for workspace/tenant-scoped changes and blocked execution - [x] T012 [P] Add catalog and evaluator unit coverage in `apps/platform/tests/Unit/Support/OperationalControls/OperationalControlCatalogTest.php` and `apps/platform/tests/Unit/Support/OperationalControls/OperationalControlEvaluatorTest.php` - [x] T013 [P] Add global-first precedence and expiry coverage in `apps/platform/tests/Unit/Support/OperationalControls/OperationalControlScopeResolutionTest.php` - [x] T014 Run the foundational unit suite with `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/OperationalControls/OperationalControlCatalogTest.php tests/Unit/Support/OperationalControls/OperationalControlEvaluatorTest.php tests/Unit/Support/OperationalControls/OperationalControlScopeResolutionTest.php` (tests: `apps/platform/tests/Unit/Support/OperationalControls/OperationalControlCatalogTest.php`) --- ## Phase 3: User Story 1 — Pause A Risky Action Centrally (Priority: P1) 🎯 MVP **Goal**: Give platform operators one system-plane control center that can pause `findings.lifecycle.backfill` and make the runbook and findings surfaces show one explicit blocked-state path instead of env-driven disappearance. **Independent Test**: Pause `findings.lifecycle.backfill` globally from `/system/ops/controls`, then verify `/system/ops/runbooks` and `/admin/t/{tenant}/findings` both show the action truthfully for entitled users, block execution server-side, and show the same paused-state reason. ### Tests for User Story 1 - [x] T015 [P] [US1] Add system-plane management coverage for staged scope-impact preview, controls-page 403 access denial, pause, update, resume, confirmation, global-audit ownership, on-demand audit history links, and audit logging in `apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php` - [x] T016 [P] [US1] Add findings lifecycle gate coverage for blocked `findings.lifecycle.backfill` starts at the shared `FindingsLifecycleBackfillRunbookService::start()` seam, including system-runbook callers, mandatory blocked-execution audit evidence, and truthful platform-plane ownership for blocked all-tenant attempts in `apps/platform/tests/Feature/System/OpsRunbooks/OperationalControlRunbookGateTest.php` - [x] T017 [P] [US1] Add findings header-action coverage for explicit blocked-state feedback, mandatory blocked-execution audit evidence, and no-start behavior in `apps/platform/tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php` ### Implementation for User Story 1 - [x] T018 [US1] Create the system ops controls page with native Filament sections, staged scope-impact preview plus confirmation-protected pause/resume actions, effective-state summaries, owner display, on-demand audit history links, and the mutation-path cleanup that deletes expired conflicting activations before writing a new pause in `apps/platform/app/Filament/System/Pages/Ops/Controls.php` - [x] T019 [US1] Integrate the evaluator into `apps/platform/app/Services/Runbooks/FindingsLifecycleBackfillRunbookService.php::start()` so the system runbooks page, CLI command, and deploy-hook command all honor the same blocked-start contract - [x] T020 [US1] Replace the env-gated findings maintenance path by routing the tenant findings action through the shared findings lifecycle service/evaluator path, blocked-execution audit recording, and shared paused-state feedback in `apps/platform/app/Filament/Resources/FindingResource/Pages/ListFindings.php` - [x] T021 [US1] Retire the in-scope findings env gate from `apps/platform/config/tenantpilot.php` - [x] T022 [US1] Run the US1 suite with `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/OpsControls/OperationalControlManagementTest.php tests/Feature/System/OpsRunbooks/OperationalControlRunbookGateTest.php tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php` (tests: `apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php`) --- ## Phase 4: User Story 2 — Block Execution Server-Side Without Masquerading As Auth (Priority: P1) **Goal**: Stop `restore.execute` before any queue, `OperationRun`, `RestoreRun`, or provider-backed execution starts while preserving normal `404` and `403` semantics. **Independent Test**: Activate `restore.execute`, attempt the restore execution flow as an entitled user, a non-member, and a member missing capability, and verify the outcomes are respectively paused-with-reason, `404`, and `403`, with no execution side effects on blocked paths. ### Tests for User Story 2 - [x] T023 [P] [US2] Add restore execution gate coverage for blocked execution starts, mandatory blocked-execution audit evidence, no queued-execution `RestoreRun`/`OperationRun` side effects, provider-start suppression, and proof that a later pause does not retroactively mutate already accepted restore runs in `apps/platform/tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php` - [x] T024 [P] [US2] Add explicit authorization-semantics and break-glass non-bypass coverage for non-member `404`, missing-capability `403` with the existing capability-denied UX, and paused-state feedback only for entitled users blocked by an operational control in `apps/platform/tests/Feature/OperationalControls/OperationalControlAuthorizationSemanticsTest.php` ### Implementation for User Story 2 - [x] T025 [US2] Integrate the evaluator into the restore execution start seam so blocked `restore.execute` decisions stop before any queued execution `RestoreRun`, queued execution `OperationRun`, queue dispatch, or provider call in `apps/platform/app/Filament/Resources/RestoreRunResource.php` - [x] T026 [US2] Reuse the shared provider-start gate for operational-control blocked outcomes instead of introducing restore-local runtime flags in `apps/platform/app/Services/Providers/ProviderOperationStartGate.php` - [x] T027 [US2] Run the US2 suite with `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php tests/Feature/OperationalControls/OperationalControlAuthorizationSemanticsTest.php` (tests: `apps/platform/tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php`) --- ## Phase 5: User Story 3 — Scope A Pause To One Workspace (Priority: P2) **Goal**: Allow platform operators to target one workspace without affecting unrelated workspaces, while keeping evaluator precedence and expiry behavior explicit and stable. **Independent Test**: Pause `restore.execute` or `findings.lifecycle.backfill` for Workspace A only, then verify the targeted workspace is blocked with the correct reason and a second workspace remains unaffected until the activation is removed or expires. ### Tests for User Story 3 - [x] T028 [P] [US3] Extend controls-page feature coverage for workspace-targeted pause, update, expiry, and resume flows in `apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php` - [x] T029 [P] [US3] Add workspace-isolation coverage for targeted findings and restore blocking in `apps/platform/tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php` and `apps/platform/tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php` ### Implementation for User Story 3 - [x] T030 [US3] Add workspace-targeted scope selection, validation, and effective-state presentation to the controls page in `apps/platform/app/Filament/System/Pages/Ops/Controls.php` - [x] T031 [US3] Extend `OperationalControlDecision` with workspace-targeted presentation details for matched scope, reason, expiry, and labels without redefining the foundational shared decision shape in `apps/platform/app/Support/OperationalControls/OperationalControlDecision.php` - [x] T032 [US3] Ensure runbooks, findings, and restore all pass workspace context consistently into control evaluation in `apps/platform/app/Filament/System/Pages/Ops/Runbooks.php`, `apps/platform/app/Filament/Resources/FindingResource/Pages/ListFindings.php`, and `apps/platform/app/Filament/Resources/RestoreRunResource.php` - [x] T033 [US3] Run the US3 suite with `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/OpsControls/OperationalControlManagementTest.php tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php` (tests: `apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php`) --- ## Phase 6: Polish & Cross-Cutting Concerns **Purpose**: Lock down the shared-path contract, update feature artifacts if implementation details move, and run the narrow validation suite. - [x] T034 [P] Add a CI guard against ad-hoc `config(...)` or page-local runtime-control bypasses for the in-scope controls in `apps/platform/tests/Feature/OperationalControls/NoAdHocOperationalControlBypassTest.php` - [x] T035 Update feature artifact close-out notes and final validation commands in `specs/242-operational-controls/plan.md` and `specs/242-operational-controls/quickstart.md` - [x] T036 Run formatting on touched platform files with `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` (target: `apps/platform/`) - [x] T037 Run the full narrow validation suite from `specs/242-operational-controls/quickstart.md`, including the timed manual smoke for SC-001, across `apps/platform/tests/Unit/Support/OperationalControls/`, `apps/platform/tests/Feature/System/OpsControls/`, `apps/platform/tests/Feature/System/OpsRunbooks/`, `apps/platform/tests/Feature/Findings/`, `apps/platform/tests/Feature/Restore/`, and `apps/platform/tests/Feature/OperationalControls/` --- ## Dependencies & Execution Order ### User Story Dependency Graph ```text Phase 1 (Setup) ↓ Phase 2 (Foundation: activation persistence + evaluator + capability/audit plumbing) ↓ US1 (system controls page + findings lifecycle gating) ─┐ ├─→ US3 (workspace-targeted scope + precedence/expiry) US2 (restore execution gate + auth semantics) ──────────┘ ``` ### Parallel Opportunities - Foundational tasks marked `[P]` can run in parallel once the migration/model direction is agreed. - US1 tests for controls, runbooks, and findings can be authored in parallel because they target separate files. - US2 restore and authorization-semantics tests can run in parallel while the restore seam work is isolated to `RestoreRunResource.php` and `ProviderOperationStartGate.php`. - US3 extends existing US1/US2 tests and can parallelize the findings and restore workspace-isolation assertions while one person updates the controls page scope UI. --- ## Parallel Example: User Story 1 ```bash Task: "Add system-plane management coverage in apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php" Task: "Add runbook gating coverage in apps/platform/tests/Feature/System/OpsRunbooks/OperationalControlRunbookGateTest.php" Task: "Add findings header-action coverage in apps/platform/tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php" Task: "Create the controls page in apps/platform/app/Filament/System/Pages/Ops/Controls.php" ``` --- ## Parallel Example: User Story 2 ```bash Task: "Add restore execution gate coverage in apps/platform/tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php" Task: "Add authorization-semantics coverage in apps/platform/tests/Feature/OperationalControls/OperationalControlAuthorizationSemanticsTest.php" Task: "Integrate the evaluator into apps/platform/app/Filament/Resources/RestoreRunResource.php" ``` --- ## Parallel Example: User Story 3 ```bash Task: "Extend controls-page workspace scope coverage in apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php" Task: "Add workspace-isolation assertions in apps/platform/tests/Feature/Findings/OperationalControlFindingsBackfillGateTest.php" Task: "Add workspace-isolation assertions in apps/platform/tests/Feature/Restore/OperationalControlRestoreExecutionGateTest.php" Task: "Add workspace-targeted scope selection in apps/platform/app/Filament/System/Pages/Ops/Controls.php" ``` --- ## Implementation Strategy ### MVP First (User Story 1) 1. Complete Phase 1 and Phase 2. 2. Deliver the controls page plus `findings.lifecycle.backfill` integrations in US1. 3. Validate with the US1 feature suite before extending the second control. ### Incremental Delivery 1. US1 delivers the new system-plane management surface and removes the ad-hoc findings env gate. 2. US2 wires the same evaluator into `restore.execute` and proves blocked execution is not treated as authorization failure. 3. US3 adds workspace-targeted scope, precedence, and expiry without widening the catalog or support namespace. 4. Phase 6 adds the bypass guard, feature-artifact close-out, formatting, and the narrow validation pass.