# Implementation Plan: Finding Risk Acceptance Lifecycle **Branch**: `154-finding-risk-acceptance` | **Date**: 2026-03-19 | **Spec**: [/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/spec.md](/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/spec.md) **Input**: Feature specification from `/specs/154-finding-risk-acceptance/spec.md` ## Summary Introduce a first-class tenant-owned Finding Exception domain that governs formal risk acceptance for findings instead of relying on a bare `risk_accepted` status and freeform reason field. The implementation adds dedicated exception and exception-decision records, tenant-scoped request and detail surfaces, a canonical workspace approval queue, centralized validity semantics, audit coverage for every lifecycle mutation, and explicit downstream contracts so evidence and reporting flows can distinguish valid governed exceptions from expired, revoked, rejected, or missing ones. The implementation keeps Findings as the system of record for the underlying issue, uses the existing `FindingWorkflowService` as the only path that can transition a finding into or out of `risk_accepted`, stores governance history in append-only decision records, and uses DB-backed tenant/workspace queries rather than a new `OperationRun` workflow for normal approval actions. ## Technical Context **Language/Version**: PHP 8.4.15 **Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Pest v4, existing Finding, AuditLog, EvidenceSnapshot, CapabilityResolver, WorkspaceCapabilityResolver, and UiEnforcement patterns **Storage**: PostgreSQL with new tenant-owned exception tables and JSONB-backed supporting metadata **Testing**: Pest feature tests, Pest unit tests, and Livewire/Filament component tests **Target Platform**: Laravel Sail web application on PostgreSQL **Project Type**: Web application monolith **Performance Goals**: Exception request, approval, rejection, renewal, and revocation remain synchronous DB-backed actions under 2 seconds; tenant and canonical exception lists remain DB-only at render time; expiring queue filters remain index-backed **Constraints**: No Microsoft Graph calls; no new public API; one current valid active exception per finding at a time; no parallel pending request or renewal workflows for the same finding; self-approval is blocked in v1 with no override path; approval history must remain append-only; reminder semantics stay passive and in-product only for v1; normal workflow stays outside `OperationRun`; status-like UI uses centralized badge semantics **Scale/Scope**: First rollout covers finding-specific exceptions only, tenant detail plus workspace approval queue, linked evidence references, validity-state evaluation, and downstream reuse by evidence/reporting consumers ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - **Pre-Phase-0 Gate: PASS** - Inventory-first: PASS. The feature governs findings and linked evidence already present in the product; it does not recollect or redefine source inventory. - Read/write separation: PASS. Exception request, approval, rejection, renewal, and revocation are explicit governance writes with confirmation, audit coverage, and focused tests. - Graph contract path: PASS. No Graph calls are introduced. - Deterministic capabilities: PASS. New capabilities are added to the canonical registry and role maps and tested through existing capability resolver patterns. - RBAC-UX / workspace / tenant isolation: PASS. Tenant exception records stay tenant-owned; the canonical workspace queue is query-only and entitlement-filtered; non-members remain 404 and in-scope capability denials remain 403. - Global search: PASS. The first rollout does not require global-search exposure for exception records. - Run observability: PASS with explicit exemption. Normal exception decisions are DB-only and expected to complete under 2 seconds, so they intentionally skip `OperationRun` and rely on audit history and surface state changes. No remote or long-running work is introduced. - Ops-UX 3-surface feedback: PASS by non-applicability. No new `OperationRun`-driven operator workflow is introduced in v1. - Ops-UX lifecycle / summary counts / system runs: PASS by non-applicability for the core decision paths. - Data minimization: PASS. Exception records store bounded justification, structured evidence references, and sanitized audit context; no raw payloads or secrets are persisted. - BADGE-001: PASS. New exception-state and validity-state badges are introduced via centralized badge domain entries and covered by tests. - UI-NAMING-001: PASS. Operator-facing vocabulary remains `Request exception`, `Approve exception`, `Reject exception`, `Renew exception`, and `Revoke exception` with `risk acceptance` used for the governed outcome. - Filament UI Action Surface Contract: PASS with explicit exemption. Tenant finding detail, tenant exception register, canonical approval queue, and exception detail all use explicit inspection affordances and confirmed destructive-like mutations; the two list surfaces intentionally defer bulk actions in v1 because exception decisions require per-record review, confirmation, and audit context. - Filament UI UX-001: PASS. Detail surfaces are inspection-first Infolists; list surfaces expose search, sort, filters, and passive expiring-state reminder cues; exception request and renewal use structured sections in modals or dedicated forms. **Post-Phase-1 Re-check: PASS** - The design keeps Findings as the underlying domain record, adds a tenant-owned governance layer without cross-tenant duplication, routes all status mutations through the existing workflow service, avoids unnecessary `OperationRun` usage, and preserves audit-first history for every decision path. ## Project Structure ### Documentation (this feature) ```text specs/154-finding-risk-acceptance/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ └── tasks.md ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Pages/ │ │ └── Monitoring/ │ └── Resources/ ├── Models/ ├── Policies/ ├── Services/ │ ├── Audit/ │ ├── Auth/ │ ├── Evidence/ │ └── Findings/ └── Support/ ├── Audit/ ├── Auth/ ├── Badges/ └── Rbac/ database/ └── migrations/ tests/ ├── Feature/ │ ├── Findings/ │ ├── Monitoring/ │ └── Guards/ └── Unit/ ├── Findings/ └── Support/ ``` **Structure Decision**: Keep the existing Laravel monolith structure. Add new exception models and decision-history tables under `app/Models`, lifecycle orchestration under `app/Services/Findings`, authorization under `app/Policies`, and tenant/canonical Filament surfaces under `app/Filament`. Persist schema in `database/migrations` and cover behavior with focused Pest feature/unit tests in existing Findings, Monitoring, and guard suites. ## Complexity Tracking No constitution violations require justification. The only deviation is the documented v1 exemption from list-surface bulk actions for governance safety. ## Phase 0 — Research Output - [research.md](/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/research.md) ## Phase 1 — Design Output - [data-model.md](/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/data-model.md) - [quickstart.md](/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/quickstart.md) - [contracts/finding-risk-acceptance.openapi.yaml](/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/154-finding-risk-acceptance/contracts/finding-risk-acceptance.openapi.yaml) ## Phase 2 — Implementation Planning The implementation task plan covers these execution slices: 1. Schema creation for `finding_exceptions` and `finding_exception_decisions` with tenant/workspace ownership constraints, validity indexes, and evidence-reference metadata. 2. Capability registry and role-map updates for `finding_exception.view`, `finding_exception.manage`, and `finding_exception.approve` plus authorization policies for tenant and canonical views. 3. Service-layer orchestration that routes all accepted-risk status mutations through a new exception lifecycle service plus the existing `FindingWorkflowService`. 4. Filament tenant finding-detail, tenant exception register, canonical approval queue, and exception detail surfaces aligned with Action Surface and UX-001 rules. 5. Audit-log integration, badge-domain additions, and canonical related-navigation support. 6. Passive reminder visibility semantics for expiring exceptions on tenant and canonical surfaces without introducing scheduled jobs or external notifications. 7. Downstream validity-resolution hooks for evidence and reporting consumers that must distinguish valid governed exceptions from expired, revoked, rejected, or missing ones. 8. Focused Pest coverage for positive and negative authorization, blocked self-approval, invalid transitions, overlapping-request rejection, renewal/revocation history, finding lifecycle changes after exception decisions, wrong-tenant behavior, and canonical queue filtering.