## Summary - harden finding lifecycle changes behind the canonical `FindingWorkflowService` gateway - route automated resolve and reopen flows through the same audited workflow path - tighten tenant and workspace scope checks on finding actions and audit visibility - add focused spec artifacts, workflow regression coverage, automation coverage, and audit visibility tests - update legacy finding model tests to use the workflow service after direct lifecycle mutators were removed ## Testing - `vendor/bin/sail bin pint --dirty --format agent` - focused findings and audit slices passed during implementation - `vendor/bin/sail artisan test --compact tests/Feature/Models/FindingResolvedTest.php` - full repository suite passed: `2757 passed`, `8 skipped`, `14448 assertions` ## Notes - Livewire v4.0+ compliance preserved - no new Filament assets or panel providers introduced; provider registration remains in `bootstrap/providers.php` - findings stay on existing Filament action surfaces, with destructive actions still confirmation-gated - no global search behavior was changed for findings resources Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #181
197 lines
13 KiB
Markdown
197 lines
13 KiB
Markdown
# Tasks: Findings Workflow Enforcement and Audit Backstop
|
|
|
|
**Input**: Design documents from `/specs/151-findings-workflow-backstop/`
|
|
**Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/, quickstart.md
|
|
|
|
**Tests**: Tests are REQUIRED for this feature because it changes runtime behavior, authorization-sensitive mutation paths, and audit guarantees.
|
|
**Operations**: This feature does not introduce new long-running or queued work. Existing runbooks remain out of scope unless they mutate findings lifecycle truth, in which case they must use `AuditLog` coverage instead of new `OperationRun` behavior.
|
|
**RBAC**: Findings mutations remain tenant/admin plane behavior. Non-members or users outside workspace or tenant scope must resolve as `404`; in-scope users lacking capability must resolve as `403`. No raw capability strings or role-string checks may be introduced.
|
|
**UI Naming**: Existing operator-facing wording remains `Triage`, `Start progress`, `Assign`, `Resolve`, `Close`, `Risk accept`, and `Reopen` across UI and audit surfaces.
|
|
**Filament UI Action Surfaces**: Existing Findings list and view surfaces remain the primary UI contract. Tasks below preserve grouped workflow actions, confirmation requirements, audit logging, and inspection affordances.
|
|
**Badges**: No new badge domain is introduced. Existing finding status badges remain centralized and must not be remapped locally.
|
|
|
|
## Phase 1: Setup (Shared Infrastructure)
|
|
|
|
**Purpose**: Prepare shared fixtures and helper coverage used by all stories.
|
|
|
|
- [X] T001 Update lifecycle-ready finding factory states in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/database/factories/FindingFactory.php
|
|
- [X] T002 [P] Add shared findings workflow test helpers in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Pest.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/Concerns/InteractsWithFindingsWorkflow.php
|
|
|
|
---
|
|
|
|
## Phase 2: Foundational (Blocking Prerequisites)
|
|
|
|
**Purpose**: Establish the shared workflow and audit foundation before any user-story slice is implemented.
|
|
|
|
**⚠️ CRITICAL**: No user story work should begin until this phase is complete.
|
|
|
|
- [X] T003 Normalize findings workflow audit action registration in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/Audit/AuditActionId.php
|
|
- [X] T004 Establish the service-owned findings workflow gateway for status, owner-assignment, and reason-bearing lifecycle mutations in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Findings/FindingWorkflowService.php
|
|
- [X] T005 [P] Add workflow bypass regression guard coverage in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingWorkflowGuardTest.php
|
|
- [X] T006 [P] Tighten findings audit sanitization and summary handling in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/Audit/AuditContextSanitizer.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Intune/AuditLogger.php
|
|
|
|
**Checkpoint**: Shared workflow and audit primitives are ready. User stories can now be implemented independently.
|
|
|
|
---
|
|
|
|
## Phase 3: User Story 1 - Prevent Invalid Workflow Bypasses (Priority: P1) 🎯 MVP
|
|
|
|
**Goal**: Ensure every covered findings lifecycle mutation goes through one enforced transition path and fails closed on invalid or bypassed writes.
|
|
|
|
**Independent Test**: Attempt valid and invalid transitions through service, list action, bulk action, and direct mutation-style paths; only valid transitions should persist.
|
|
|
|
### Tests for User Story 1
|
|
|
|
- [X] T007 [P] [US1] Add transition validation tests for status changes, owner reassignment, and required-reason mutations in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingWorkflowServiceTest.php
|
|
- [X] T008 [P] [US1] Add Livewire findings action enforcement tests that preserve the existing action surface contract in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingWorkflowUiEnforcementTest.php
|
|
|
|
### Implementation for User Story 1
|
|
|
|
- [X] T009 [US1] Remove or neutralize direct lifecycle mutators in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/Finding.php
|
|
- [X] T010 [US1] Rewire single-record workflow actions to the canonical gateway in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Resources/FindingResource.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Resources/FindingResource/Pages/ViewFinding.php
|
|
- [X] T011 [US1] Rewire bulk workflow actions to the canonical gateway in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Resources/FindingResource.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Resources/FindingResource/Pages/ListFindings.php
|
|
- [X] T012 [US1] Tighten tenant-scope and capability enforcement for covered mutations in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Policies/FindingPolicy.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Findings/FindingWorkflowService.php
|
|
|
|
**Checkpoint**: User Story 1 is complete when invalid transitions and direct bypass attempts no longer mutate findings and existing Findings UI actions still function for authorized users.
|
|
|
|
---
|
|
|
|
## Phase 4: User Story 2 - Trust the Audit History for Findings Lifecycle Changes (Priority: P1)
|
|
|
|
**Goal**: Guarantee that every covered findings lifecycle mutation produces one durable, readable, tenant-safe audit event.
|
|
|
|
**Independent Test**: Execute representative lifecycle changes and confirm exactly one audit row is created per mutation with the correct actor, scope, before-state, after-state, and reason metadata.
|
|
|
|
### Tests for User Story 2
|
|
|
|
- [X] T013 [P] [US2] Add findings audit backstop tests in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingAuditBackstopTest.php
|
|
- [X] T014 [P] [US2] Add finding audit visibility, scope, and deleted-or-inaccessible record readability tests in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Audit/FindingAuditVisibilityTest.php
|
|
|
|
### Implementation for User Story 2
|
|
|
|
- [X] T015 [US2] Ensure each covered gateway mutation, including owner reassignment and reason-bearing updates, writes one canonical audit event in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Findings/FindingWorkflowService.php
|
|
- [X] T016 [US2] Register findings workflow audit summaries and labels in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/Audit/AuditActionId.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/Navigation/RelatedNavigationResolver.php
|
|
- [X] T017 [US2] Enforce findings audit metadata minimization in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/Audit/AuditContextSanitizer.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/AuditLog.php
|
|
- [X] T018 [US2] Add duplicate-audit prevention and backstop behavior in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Audit/AuditRecorder.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Intune/AuditLogger.php
|
|
|
|
**Checkpoint**: User Story 2 is complete when covered lifecycle mutations always emit one readable audit event and audit review remains tenant-safe.
|
|
|
|
---
|
|
|
|
## Phase 5: User Story 3 - Keep Recurrence and Reopen Semantics Consistent Across All Mutation Paths (Priority: P2)
|
|
|
|
**Goal**: Bring system-driven reopen and auto-resolve flows under the same lifecycle truth and audit rules as interactive workflow actions.
|
|
|
|
**Independent Test**: Run recurrence and auto-resolve scenarios through baseline, permission posture, and Entra-admin flows and confirm they use the same workflow rules and audit outputs as UI actions.
|
|
|
|
### Tests for User Story 3
|
|
|
|
- [X] T019 [P] [US3] Add automation workflow regression tests in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingAutomationWorkflowTest.php
|
|
- [X] T020 [P] [US3] Add concurrency edge-case tests for human and automation mutations in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Findings/FindingWorkflowConcurrencyTest.php
|
|
|
|
### Implementation for User Story 3
|
|
|
|
- [X] T021 [US3] Route baseline auto-close through the canonical gateway in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Baselines/BaselineAutoCloseService.php
|
|
- [X] T022 [US3] Route permission posture lifecycle updates through the canonical gateway in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/PermissionPosture/PermissionPostureFindingGenerator.php
|
|
- [X] T023 [US3] Route Entra admin roles lifecycle updates through the canonical gateway in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/EntraAdminRoles/EntraAdminRolesFindingGenerator.php
|
|
- [X] T024 [US3] Unify recurrence reopen handling in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Jobs/CompareBaselineToTenantJob.php and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Services/Findings/FindingWorkflowService.php
|
|
|
|
**Checkpoint**: User Story 3 is complete when automation paths no longer mutate findings lifecycle truth through private side channels.
|
|
|
|
---
|
|
|
|
## Phase 6: Polish & Cross-Cutting Concerns
|
|
|
|
**Purpose**: Finalize documentation alignment and end-to-end verification across all stories.
|
|
|
|
- [X] T025 [P] Update verification notes and final command set, including the Filament action-surface guard, in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/151-findings-workflow-backstop/quickstart.md and /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/151-findings-workflow-backstop/contracts/findings-workflow.openapi.yaml
|
|
- [X] T026 Record final rollout notes and confirm that no unapproved implementation exemptions were introduced in /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/151-findings-workflow-backstop/plan.md after running focused Pint and Pest validation
|
|
|
|
---
|
|
|
|
## 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; provides the MVP enforcement slice.
|
|
- **User Story 2 (Phase 4)**: Depends on Foundational completion and should follow US1 because it hardens the same gateway with audit guarantees.
|
|
- **User Story 3 (Phase 5)**: Depends on Foundational completion and benefits from US1 gateway consolidation before routing automation paths.
|
|
- **Polish (Phase 6)**: Depends on all desired user stories being complete.
|
|
|
|
### User Story Dependencies
|
|
|
|
- **US1**: Can start immediately after Foundational; no dependency on other stories.
|
|
- **US2**: Can begin after Foundational, but is lowest-risk after US1 establishes the canonical gateway.
|
|
- **US3**: Can begin after Foundational, but depends conceptually on the gateway introduced in US1 and the audit guarantees reinforced in US2.
|
|
|
|
### Within Each User Story
|
|
|
|
- Tests should be written first and verified to fail before implementation.
|
|
- Gateway or policy changes should land before UI or automation rewiring.
|
|
- Story-specific verification should pass before moving to the next story.
|
|
|
|
### Parallel Opportunities
|
|
|
|
- T001 and T002 can run in parallel.
|
|
- T005 and T006 can run in parallel once T003 and T004 are underway.
|
|
- Within each story, the test tasks marked `[P]` can run in parallel.
|
|
- US3 service rewiring tasks T021, T022, and T023 can run in parallel once the canonical gateway behavior is stable.
|
|
|
|
---
|
|
|
|
## Parallel Example: User Story 1
|
|
|
|
```bash
|
|
# Write the two US1 test files in parallel
|
|
Task: T007 [US1] tests/Feature/Findings/FindingWorkflowServiceTest.php
|
|
Task: T008 [US1] tests/Feature/Findings/FindingWorkflowUiEnforcementTest.php
|
|
|
|
# After the tests are in place, rewire the two UI surfaces in parallel
|
|
Task: T010 [US1] app/Filament/Resources/FindingResource.php + app/Filament/Resources/FindingResource/Pages/ViewFinding.php
|
|
Task: T011 [US1] app/Filament/Resources/FindingResource.php + app/Filament/Resources/FindingResource/Pages/ListFindings.php
|
|
```
|
|
|
|
## Parallel Example: User Story 2
|
|
|
|
```bash
|
|
# Add audit backstop and visibility tests in parallel
|
|
Task: T013 [US2] tests/Feature/Findings/FindingAuditBackstopTest.php
|
|
Task: T014 [US2] tests/Feature/Audit/FindingAuditVisibilityTest.php
|
|
|
|
# Then split audit taxonomy and sanitizer work
|
|
Task: T016 [US2] app/Support/Audit/AuditActionId.php + app/Support/Navigation/RelatedNavigationResolver.php
|
|
Task: T017 [US2] app/Support/Audit/AuditContextSanitizer.php + app/Models/AuditLog.php
|
|
```
|
|
|
|
## Parallel Example: User Story 3
|
|
|
|
```bash
|
|
# Route automation services independently once the gateway contract is stable
|
|
Task: T021 [US3] app/Services/Baselines/BaselineAutoCloseService.php
|
|
Task: T022 [US3] app/Services/PermissionPosture/PermissionPostureFindingGenerator.php
|
|
Task: T023 [US3] app/Services/EntraAdminRoles/EntraAdminRolesFindingGenerator.php
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Strategy
|
|
|
|
### MVP First
|
|
|
|
Implement **User Story 1** first to establish a single enforced workflow mutation path and remove the most dangerous bypasses. This delivers immediate risk reduction even before audit and automation cleanup are complete.
|
|
|
|
### Incremental Delivery
|
|
|
|
1. Complete Setup and Foundational phases.
|
|
2. Deliver US1 as the first mergeable slice.
|
|
3. Add US2 to guarantee durable historical evidence for the same gateway.
|
|
4. Extend the gateway to automation paths in US3.
|
|
5. Finish with cross-cutting validation and documentation updates.
|
|
|
|
### Suggested MVP Scope
|
|
|
|
- **MVP**: Phase 1 + Phase 2 + Phase 3 (User Story 1)
|
|
- **Production-ready hardening slice**: MVP + Phase 4 (User Story 2)
|
|
- **Full feature scope**: MVP + US2 + US3 + Polish |