# Tasks: Finding Risk Acceptance Lifecycle **Input**: Design documents from `/specs/154-finding-risk-acceptance/` **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, auditability, and tenant-scoped governance workflows. **Operations**: This feature intentionally keeps request, approval, rejection, renewal, and revocation as security-relevant DB-only actions without `OperationRun`; tasks therefore enforce `AuditLog` coverage instead of an operations progress workflow. **RBAC**: This feature introduces authorization changes and MUST enforce canonical capability registry usage, 404 vs 403 semantics, cross-plane deny-as-not-found behavior, and positive/negative authorization tests. **Filament UI**: This feature adds and modifies Filament Resource and Page surfaces, so tasks include Action Surface Contract, BADGE-001, and UX-001 enforcement work. ## Phase 1: Setup (Shared Infrastructure) **Purpose**: Create the core schema and file scaffolding needed for all stories. - [X] T001 Create exception schema migrations in `database/migrations/2026_03_19_000001_create_finding_exceptions_table.php`, `database/migrations/2026_03_19_000002_create_finding_exception_decisions_table.php`, and `database/migrations/2026_03_19_000003_create_finding_exception_evidence_references_table.php` - [X] T002 [P] Create Eloquent model scaffolding for the new domain in `app/Models/FindingException.php`, `app/Models/FindingExceptionDecision.php`, and `app/Models/FindingExceptionEvidenceReference.php` - [X] T003 [P] Create Filament surface scaffolding in `app/Filament/Resources/FindingExceptionResource.php`, `app/Filament/Resources/FindingExceptionResource/Pages/ListFindingExceptions.php`, `app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php`, and `app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` --- ## Phase 2: Foundational (Blocking Prerequisites) **Purpose**: Establish the shared domain, authorization, audit, and navigation infrastructure before any user-story slice is implemented. **⚠️ CRITICAL**: No user story work should begin until this phase is complete. - [X] T004 Register exception capabilities and role mappings in `app/Support/Auth/Capabilities.php`, `app/Services/Auth/RoleCapabilityMap.php`, and `app/Services/Auth/WorkspaceRoleCapabilityMap.php` - [X] T005 Implement policy and entitlement enforcement for tenant and canonical exception access in `app/Policies/FindingExceptionPolicy.php`, `app/Providers/Filament/AdminPanelProvider.php`, and `app/Providers/Filament/TenantPanelProvider.php` - [X] T006 [P] Add shared audit action IDs, summaries, and related-navigation hooks in `app/Support/Audit/AuditActionId.php`, `app/Support/Navigation/RelatedNavigationResolver.php`, and `app/Services/Intune/AuditLogger.php` - [X] T007 Implement the shared exception lifecycle service and validity resolver skeleton in `app/Services/Findings/FindingExceptionService.php` and `app/Services/Findings/FindingRiskGovernanceResolver.php` - [X] T008 Wire domain relationships and tenant-owned query behavior in `app/Models/Finding.php`, `app/Models/FindingException.php`, `app/Models/FindingExceptionDecision.php`, and `app/Models/FindingExceptionEvidenceReference.php` - [X] T009 [P] Add foundational schema, policy, and model regression coverage in `tests/Unit/Findings/FindingExceptionModelTest.php` and `tests/Feature/Findings/FindingExceptionPolicyTest.php` **Checkpoint**: Foundation ready. User story work can now proceed. --- ## Phase 3: User Story 1 - Propose And Approve A Time-Bounded Risk Acceptance (Priority: P1) 🎯 MVP **Goal**: Allow tenant managers to request risk acceptance for a finding and route it through explicit approval or rejection. **Independent Test**: Create a finding, submit an exception request with justification and review timing, approve or reject it as an authorized approver, and verify correct finding governance state plus 404/403 authorization behavior. ### Tests for User Story 1 - [X] T010 [P] [US1] Add request, approve, and reject feature coverage in `tests/Feature/Findings/FindingExceptionWorkflowTest.php` - [X] T011 [P] [US1] Add positive and negative authorization coverage for request and approval flows in `tests/Feature/Findings/FindingExceptionAuthorizationTest.php` - [X] T012 [P] [US1] Add lifecycle transition, blocked self-approval, and overlapping-request rejection unit coverage in `tests/Unit/Findings/FindingExceptionServiceTest.php` ### Implementation for User Story 1 - [X] T013 [US1] Implement request, approve, and reject lifecycle transitions, blocked self-approval, overlapping-request guards, and append-only decision persistence in `app/Services/Findings/FindingExceptionService.php` and `app/Models/FindingExceptionDecision.php` - [X] T014 [US1] Integrate approved and rejected exception outcomes with finding status mutation rules in `app/Services/Findings/FindingWorkflowService.php` and `app/Models/Finding.php` - [X] T015 [US1] Add request, approve, and reject forms and actions to the finding detail and canonical queue in `app/Filament/Resources/FindingResource.php`, `app/Filament/Resources/FindingResource/Pages/ViewFinding.php`, and `app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` - [X] T016 [US1] Persist request, approval, and rejection audit history with summary-first metadata in `app/Support/Audit/AuditActionId.php`, `app/Support/Audit/AuditContextSanitizer.php`, and `app/Services/Intune/AuditLogger.php` **Checkpoint**: User Story 1 is independently functional and demonstrates the MVP governance workflow. --- ## Phase 4: User Story 2 - See Whether Accepted Risk Is Still Valid (Priority: P1) **Goal**: Provide tenant and canonical views that show pending, active, expiring, expired, rejected, and revoked exceptions without leaking unauthorized tenant data. **Independent Test**: Seed exception records in multiple lifecycle states and verify tenant and canonical views show correct state, timing, owners, and filters only for entitled tenants. ### Tests for User Story 2 - [X] T017 [P] [US2] Add tenant register and finding-detail coverage for lifecycle-state visibility, passive expiry reminders, actor-specific visibility, empty states, and filters in `tests/Feature/Findings/FindingExceptionRegisterTest.php` and `tests/Feature/Findings/FindingRiskGovernanceProjectionTest.php` - [X] T018 [P] [US2] Add canonical queue and exception-detail coverage for tenant-safe filtering, passive expiry reminders, and entitled actor visibility in `tests/Feature/Monitoring/FindingExceptionsQueueTest.php` and `tests/Feature/Findings/FindingExceptionAuthorizationTest.php` - [X] T019 [P] [US2] Add badge and validity-mapping unit coverage in `tests/Unit/Findings/FindingExceptionBadgeTest.php` ### Implementation for User Story 2 - [X] T020 [US2] Implement the tenant exception register, exception detail, and finding-detail reminder surfaces, including actor-specific passive reminder visibility, header actions, and the documented v1 bulk-action exemption, in `app/Filament/Resources/FindingExceptionResource.php`, `app/Filament/Resources/FindingExceptionResource/Pages/ListFindingExceptions.php`, `app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php`, `app/Filament/Resources/FindingResource.php`, and `app/Filament/Resources/FindingResource/Pages/ViewFinding.php` - [X] T021 [US2] Implement canonical queue filters, passive expiry reminders, header actions, empty states, documented v1 bulk-action exemption, and entitled tenant prefilter behavior in `app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` - [X] T022 [US2] Add centralized exception-state and validity badges in `app/Support/Badges/BadgeDomain.php`, `app/Support/Badges/Domains/FindingExceptionStatusBadge.php`, and `app/Support/Badges/Domains/FindingRiskGovernanceValidityBadge.php` - [X] T023 [US2] Add exception filter catalog entries and related navigation affordances in `app/Support/Filament/FilterOptionCatalog.php` and `app/Support/Navigation/RelatedNavigationResolver.php` **Checkpoint**: User Story 2 is independently functional and can be demonstrated with seeded exception records even without renewal or downstream consumer work. --- ## Phase 5: User Story 3 - Renew Or Revoke An Accepted Risk With Audit Evidence (Priority: P2) **Goal**: Support renewal and revocation with preserved decision history and structured evidence references. **Independent Test**: Renew an active exception with updated evidence references, revoke another one, and verify history remains append-only and intelligible. ### Tests for User Story 3 - [X] T024 [P] [US3] Add renewal and revocation feature coverage in `tests/Feature/Findings/FindingExceptionRenewalTest.php` and `tests/Feature/Findings/FindingExceptionRevocationTest.php` - [X] T025 [P] [US3] Add append-only decision and evidence-reference unit coverage in `tests/Unit/Findings/FindingExceptionDecisionTest.php` and `tests/Unit/Findings/FindingExceptionEvidenceReferenceTest.php` ### Implementation for User Story 3 - [X] T026 [US3] Implement renewal and revocation lifecycle behavior in `app/Services/Findings/FindingExceptionService.php`, `app/Models/FindingException.php`, and `app/Models/FindingExceptionDecision.php` - [X] T027 [US3] Persist and render structured evidence references in `app/Models/FindingExceptionEvidenceReference.php`, `app/Filament/Resources/FindingExceptionResource.php`, and `app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php` - [X] T028 [US3] Add renew and revoke actions to tenant and canonical surfaces in `app/Filament/Resources/FindingResource.php`, `app/Filament/Resources/FindingResource/Pages/ViewFinding.php`, and `app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` - [X] T029 [US3] Extend audit summaries and sanitization for renewal, revocation, and linked evidence metadata in `app/Support/Audit/AuditActionId.php`, `app/Support/Audit/AuditContextSanitizer.php`, and `app/Services/Intune/AuditLogger.php` **Checkpoint**: User Story 3 is independently functional and preserves exception history without overwriting earlier decisions. --- ## Phase 6: User Story 4 - Detect Governance Drift In Accepted-Risk Findings (Priority: P2) **Goal**: Surface findings that look risk-accepted but are not backed by a currently valid exception, and ensure downstream consumers count only valid governed exceptions. **Independent Test**: Seed findings with valid, expired, revoked, rejected, and missing exception states and verify only valid ones count as active accepted risk in finding detail and downstream evidence/reporting summaries. ### Tests for User Story 4 - [X] T030 [P] [US4] Add governance-drift and finding-lifecycle-change coverage for finding detail and register warnings in `tests/Feature/Findings/FindingRiskGovernanceProjectionTest.php` - [X] T031 [P] [US4] Add evidence and review-pack downstream validity coverage in `tests/Feature/Evidence/ExceptionValidityEvidenceIntegrationTest.php` and `tests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php` ### Implementation for User Story 4 - [X] T032 [US4] Implement validity projection, warning-state resolution, and history-preserving behavior for resolved, closed, reopened, and severity-changed findings in `app/Services/Findings/FindingRiskGovernanceResolver.php`, `app/Models/FindingException.php`, and `app/Models/Finding.php` - [X] T033 [US4] Surface missing, expired, and revoked governance warnings in `app/Filament/Resources/FindingResource.php`, `app/Filament/Resources/FindingResource/Pages/ViewFinding.php`, and `app/Filament/Resources/FindingExceptionResource.php` - [X] T034 [US4] Update downstream evidence and review-pack consumers to count only valid governed exceptions in `app/Services/Evidence/EvidenceSnapshotService.php`, `app/Jobs/GenerateReviewPackJob.php`, and `app/Services/ReviewPackService.php` **Checkpoint**: User Story 4 is independently functional and proves that accepted-risk reporting depends on valid exception governance rather than finding status alone. --- ## Phase 7: Polish & Cross-Cutting Concerns **Purpose**: Finalize cross-story safeguards, UI contract enforcement, and quickstart validation. - [X] T035 [P] Update Filament action-surface guard coverage for the new exception surfaces, including the documented v1 bulk-action exemptions, and refresh badge guard coverage in `tests/Feature/Guards/ActionSurfaceContractTest.php` and `tests/Feature/Guards/NoAdHocStatusBadgesTest.php` - [X] T036 [P] Tighten tenant-owned query and cross-tenant leakage guards for the new domain in `tests/Feature/Guards/TenantOwnedQueryGuardTest.php` and `tests/Feature/Findings/FindingExceptionAuthorizationTest.php` - [X] T037 Validate the quickstart scenarios, passive reminder visibility, actor-specific visibility matrix, and timed success-criteria walkthroughs against focused Pest packs in `specs/154-finding-risk-acceptance/quickstart.md`, `tests/Feature/Findings/FindingExceptionWorkflowTest.php`, `tests/Feature/Findings/FindingExceptionRegisterTest.php`, `tests/Feature/Findings/FindingRiskGovernanceProjectionTest.php`, `tests/Feature/Monitoring/FindingExceptionsQueueTest.php`, and `tests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php` --- ## Dependencies & Execution Order ### Phase Dependencies - **Setup (Phase 1)**: No dependencies; starts immediately. - **Foundational (Phase 2)**: Depends on Setup completion; blocks all user stories. - **User Story 1 (Phase 3)**: Depends on Foundational completion; recommended MVP slice. - **User Story 2 (Phase 4)**: Depends on Foundational completion; integrates best after User Story 1 because canonical queue actions reuse approval handlers. - **User Story 3 (Phase 5)**: Depends on Foundational completion and User Story 1 lifecycle foundations. - **User Story 4 (Phase 6)**: Depends on Foundational completion and benefits from User Stories 1 and 3 because validity projection relies on complete exception lifecycle states. - **Polish (Phase 7)**: Depends on all desired user stories being complete. ### User Story Dependencies - **US1**: No dependency on other user stories after Foundational; this is the MVP. - **US2**: Can be viewed with seeded data after Foundational, but approval queue actions are most complete after US1. - **US3**: Depends on US1 because renewal and revocation extend the primary exception lifecycle. - **US4**: Depends on US1 for valid governance semantics and on US3 for renewal/revocation edge states. ### Within Each User Story - Write tests before the corresponding implementation tasks and confirm they fail first. - Complete service and model behavior before Filament action wiring. - Complete audit and authorization enforcement before closing the story. ### Parallel Opportunities - `T002` and `T003` can run in parallel after `T001`. - `T006` and `T009` can run in parallel once `T004` and `T005` establish the authorization baseline. - In each story, the `[P]` test tasks can run in parallel. - `T022` and `T023` can run in parallel during US2 after list/detail surfaces exist. - `T035` and `T036` can run in parallel in the polish phase. --- ## Parallel Example: User Story 1 ```bash # Run the User Story 1 tests in parallel: Task: "Add request, approve, and reject feature coverage in tests/Feature/Findings/FindingExceptionWorkflowTest.php" Task: "Add positive and negative authorization coverage for request and approval flows in tests/Feature/Findings/FindingExceptionAuthorizationTest.php" Task: "Add lifecycle transition, blocked self-approval, and overlapping-request rejection unit coverage in tests/Unit/Findings/FindingExceptionServiceTest.php" # Then implement the shared lifecycle and UI wiring in sequence: Task: "Implement request, approve, and reject lifecycle transitions plus append-only decision persistence in app/Services/Findings/FindingExceptionService.php and app/Models/FindingExceptionDecision.php" Task: "Integrate approved and rejected exception outcomes with finding status mutation rules in app/Services/Findings/FindingWorkflowService.php and app/Models/Finding.php" Task: "Add request, approve, and reject forms and actions to the finding detail and canonical queue in app/Filament/Resources/FindingResource.php, app/Filament/Resources/FindingResource/Pages/ViewFinding.php, and app/Filament/Pages/Monitoring/FindingExceptionsQueue.php" ``` --- ## Implementation Strategy ### MVP First 1. Complete Phase 1 and Phase 2. 2. Deliver User Story 1 as the MVP: request, approve, reject, audit, and correct authorization semantics. 3. Validate that the core governance gap is closed before expanding read models and downstream consumers. ### Incremental Delivery 1. Add User Story 2 to make governance state visible and operable across tenant and canonical views. 2. Add User Story 3 for renewal and revocation once the core approval lifecycle is stable. 3. Add User Story 4 to tighten downstream validity semantics and governance-drift reporting. ### Suggested MVP Scope - **Recommended MVP**: Phases 1-3 only. - **Why**: This yields the minimum coherent business value by turning `risk_accepted` from a bare status into a governed, approved, auditable exception workflow.