TenantAtlas/specs/242-operational-controls/tasks.md
ahmido d96abc65fb
Some checks failed
Main Confidence / confidence (push) Failing after 1m23s
Remove Findings lifecycle backfill operational surface (controls slice) (#280)
Removes the Findings lifecycle backfill from the Operational Controls UI and OperationalControlCatalog.

This patch is a safe, controls-only change; runbooks, jobs and other runtime artifacts are NOT removed yet. Follow-up work will delete the runbook service/scope, jobs, commands, and update tests.

Files changed:
- apps/platform/app/Filament/System/Pages/Ops/Controls.php
- apps/platform/app/Support/OperationalControls/OperationalControlCatalog.php
- apps/platform/tests/Feature/System/OpsControls/OperationalControlManagementTest.php
- apps/platform/tests/Unit/Support/OperationalControls/OperationalControlCatalogTest.php
- apps/platform/tests/Unit/Support/OperationalControls/OperationalControlScopeResolutionTest.php

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #280
2026-04-26 15:43:47 +00:00

187 lines
17 KiB
Markdown

---
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.