## Summary - add a first-class finding exception domain with request, approval, rejection, renewal, and revocation lifecycle support - add tenant-scoped exception register, finding governance surfaces, and a canonical workspace approval queue in Filament - add audit, badge, evidence, and review-pack integrations plus focused Pest coverage for workflow, authorization, and governance validity ## Validation - vendor/bin/sail bin pint --dirty --format agent - CI=1 vendor/bin/sail artisan test --compact - manual integrated-browser smoke test for the request-exception happy path, tenant register visibility, and canonical queue visibility ## Notes - Filament implementation remains on v5 with Livewire v4-compatible surfaces - canonical queue lives in the admin panel; provider registration stays in bootstrap/providers.php - finding exceptions stay out of global search in this rollout Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #184
17 KiB
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.
- 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, anddatabase/migrations/2026_03_19_000003_create_finding_exception_evidence_references_table.php - T002 [P] Create Eloquent model scaffolding for the new domain in
app/Models/FindingException.php,app/Models/FindingExceptionDecision.php, andapp/Models/FindingExceptionEvidenceReference.php - 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, andapp/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.
- T004 Register exception capabilities and role mappings in
app/Support/Auth/Capabilities.php,app/Services/Auth/RoleCapabilityMap.php, andapp/Services/Auth/WorkspaceRoleCapabilityMap.php - T005 Implement policy and entitlement enforcement for tenant and canonical exception access in
app/Policies/FindingExceptionPolicy.php,app/Providers/Filament/AdminPanelProvider.php, andapp/Providers/Filament/TenantPanelProvider.php - T006 [P] Add shared audit action IDs, summaries, and related-navigation hooks in
app/Support/Audit/AuditActionId.php,app/Support/Navigation/RelatedNavigationResolver.php, andapp/Services/Intune/AuditLogger.php - T007 Implement the shared exception lifecycle service and validity resolver skeleton in
app/Services/Findings/FindingExceptionService.phpandapp/Services/Findings/FindingRiskGovernanceResolver.php - T008 Wire domain relationships and tenant-owned query behavior in
app/Models/Finding.php,app/Models/FindingException.php,app/Models/FindingExceptionDecision.php, andapp/Models/FindingExceptionEvidenceReference.php - T009 [P] Add foundational schema, policy, and model regression coverage in
tests/Unit/Findings/FindingExceptionModelTest.phpandtests/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
- T010 [P] [US1] Add request, approve, and reject feature coverage in
tests/Feature/Findings/FindingExceptionWorkflowTest.php - T011 [P] [US1] Add positive and negative authorization coverage for request and approval flows in
tests/Feature/Findings/FindingExceptionAuthorizationTest.php - 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
- 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.phpandapp/Models/FindingExceptionDecision.php - T014 [US1] Integrate approved and rejected exception outcomes with finding status mutation rules in
app/Services/Findings/FindingWorkflowService.phpandapp/Models/Finding.php - 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, andapp/Filament/Pages/Monitoring/FindingExceptionsQueue.php - T016 [US1] Persist request, approval, and rejection audit history with summary-first metadata in
app/Support/Audit/AuditActionId.php,app/Support/Audit/AuditContextSanitizer.php, andapp/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
- 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.phpandtests/Feature/Findings/FindingRiskGovernanceProjectionTest.php - 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.phpandtests/Feature/Findings/FindingExceptionAuthorizationTest.php - T019 [P] [US2] Add badge and validity-mapping unit coverage in
tests/Unit/Findings/FindingExceptionBadgeTest.php
Implementation for User Story 2
- 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, andapp/Filament/Resources/FindingResource/Pages/ViewFinding.php - 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 - T022 [US2] Add centralized exception-state and validity badges in
app/Support/Badges/BadgeDomain.php,app/Support/Badges/Domains/FindingExceptionStatusBadge.php, andapp/Support/Badges/Domains/FindingRiskGovernanceValidityBadge.php - T023 [US2] Add exception filter catalog entries and related navigation affordances in
app/Support/Filament/FilterOptionCatalog.phpandapp/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
- T024 [P] [US3] Add renewal and revocation feature coverage in
tests/Feature/Findings/FindingExceptionRenewalTest.phpandtests/Feature/Findings/FindingExceptionRevocationTest.php - T025 [P] [US3] Add append-only decision and evidence-reference unit coverage in
tests/Unit/Findings/FindingExceptionDecisionTest.phpandtests/Unit/Findings/FindingExceptionEvidenceReferenceTest.php
Implementation for User Story 3
- T026 [US3] Implement renewal and revocation lifecycle behavior in
app/Services/Findings/FindingExceptionService.php,app/Models/FindingException.php, andapp/Models/FindingExceptionDecision.php - T027 [US3] Persist and render structured evidence references in
app/Models/FindingExceptionEvidenceReference.php,app/Filament/Resources/FindingExceptionResource.php, andapp/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php - 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, andapp/Filament/Pages/Monitoring/FindingExceptionsQueue.php - 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, andapp/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
- T030 [P] [US4] Add governance-drift and finding-lifecycle-change coverage for finding detail and register warnings in
tests/Feature/Findings/FindingRiskGovernanceProjectionTest.php - T031 [P] [US4] Add evidence and review-pack downstream validity coverage in
tests/Feature/Evidence/ExceptionValidityEvidenceIntegrationTest.phpandtests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php
Implementation for User Story 4
- 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, andapp/Models/Finding.php - T033 [US4] Surface missing, expired, and revoked governance warnings in
app/Filament/Resources/FindingResource.php,app/Filament/Resources/FindingResource/Pages/ViewFinding.php, andapp/Filament/Resources/FindingExceptionResource.php - 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, andapp/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.
- 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.phpandtests/Feature/Guards/NoAdHocStatusBadgesTest.php - T036 [P] Tighten tenant-owned query and cross-tenant leakage guards for the new domain in
tests/Feature/Guards/TenantOwnedQueryGuardTest.phpandtests/Feature/Findings/FindingExceptionAuthorizationTest.php - 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, andtests/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
T002andT003can run in parallel afterT001.T006andT009can run in parallel onceT004andT005establish the authorization baseline.- In each story, the
[P]test tasks can run in parallel. T022andT023can run in parallel during US2 after list/detail surfaces exist.T035andT036can run in parallel in the polish phase.
Parallel Example: User Story 1
# 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
- Complete Phase 1 and Phase 2.
- Deliver User Story 1 as the MVP: request, approve, reject, audit, and correct authorization semantics.
- Validate that the core governance gap is closed before expanding read models and downstream consumers.
Incremental Delivery
- Add User Story 2 to make governance state visible and operable across tenant and canonical views.
- Add User Story 3 for renewal and revocation once the core approval lifecycle is stable.
- 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_acceptedfrom a bare status into a governed, approved, auditable exception workflow.