# Implementation Plan: Spec 354 - Finding Exceptions / Accepted Risk Resolution Guidance v1 - Branch: `354-finding-exceptions-accepted-risk-resolution-guidance-v1` - Date: 2026-06-05 - Spec: `specs/354-finding-exceptions-accepted-risk-resolution-guidance-v1/spec.md` - Input: Spec 354 + repo inspection of Finding Exceptions queue/detail surfaces, accepted-risk governance resolver, Governance Inbox accepted-risk routing, and downstream review-output continuity. ## Summary Add one derived accepted-risk guidance layer to the existing Finding Exceptions queue and detail owner surfaces so operators can see one dominant accepted-risk case, one dominant next-step affordance, and conservative owner-surface wording without reconstructing meaning from badges, dates, and grouped actions. The implementation stays narrow: - reuse existing `FindingException`, `FindingExceptionDecision`, `Finding`, `FindingRiskGovernanceResolver`, `ResolutionCase`, and current lifecycle actions - keep queue/detail as the owning accepted-risk surfaces - preserve current action confirmation, authorization, audit, and notification behavior - reuse downstream customer-safe wording only where already repo-backed - avoid new persistence, new provider seams, and new workflow frameworks ## Technical Context - Language/Version: PHP 8.4.15, Laravel 12.52.x - UI stack: Filament 5.2.x, Livewire 4.x - Database: PostgreSQL, no schema change planned - Testing: Pest unit + feature/Livewire + one strategic browser smoke - Validation lanes: fast-feedback + confidence + browser - Local runtime posture: Sail-first - Deployment/runtime impact: no expected env, migration, queue-family, scheduler, storage, or panel/provider change - Global search: unchanged; `FindingExceptionResource` remains not globally searchable ## Current Repo Truth That Constrains The Slice - `FindingExceptionsQueue` already owns: - workspace-wide accepted-risk access - explicit `environment_id` filter behavior - selected-record inspect state - approve / reject actions with confirmation - related finding and queue/deep-link actions - `ViewFindingException` already owns: - accepted-risk detail presentation - renew / revoke actions with confirmation - decision-register return-link continuity - `FindingExceptionResource` already disables global search. - `FindingRiskGovernanceResolver` already derives: - accepted-risk workflow family - governance warning text - primary narrative - next-action copy - validity / attention signals - the current repo-real fresh-decision-required warning path - `GovernanceInboxSectionBuilder` already exposes accepted-risk lane text, due context, and the primary action label `Review accepted risk`. - Customer-safe accepted-risk summaries already exist in review-output paths through `EnvironmentReviewComposer`, Customer Review Workspace, and review-pack summaries, but this slice should treat them as wording reference rather than a runtime mutation target. - The queue audit (`ui-012`) already marks risk decision language, expiry visibility, and customer-safe wording as top issues. - There is no need for a second accepted-risk model, a new accepted-risk page family, or a new review-output engine. ## Domain / Model Implications - No schema or migration change is planned. - No new persisted accepted-risk readiness entity, review-impact entity, or action-history model is allowed in this slice. - The narrowest acceptable implementation shape is one derived accepted-risk guidance adapter or selector over: - current `FindingException` - current `FindingExceptionDecision` - current linked `Finding` - current `FindingRiskGovernanceResolver` - current queue/detail action availability - Existing ownership boundaries remain unchanged: - exception lifecycle truth stays `FindingException` / `FindingExceptionDecision` owned - source finding truth stays `Finding` owned - customer-safe review truth stays review/output owned and unchanged by this slice - any new guidance state stays request-local and derived ## UI / Filament / Livewire Implications - Filament v5 continues to run on Livewire v4.x; no version or API drift is permitted. - No panel/provider registration change is allowed; `apps/platform/bootstrap/providers.php` remains untouched. - `FindingExceptionResource` stays not globally searchable. - Existing destructive or high-impact accepted-risk actions must keep their current confirmation, authorization, notification, and audit posture. - No new asset registration is planned, so there is no expected `filament:assets` deployment change for this spec. ## RBAC / Policy Implications - Workspace membership and entitled environment access remain the only scope authorities. - Current capabilities continue to decide queue visibility, detail visibility, and lifecycle-action executability. - Guidance selection itself must remain safe for unauthorized users by operating only on already-authorized page state. - Queue and detail must keep deny-as-not-found semantics for out-of-scope workspace/environment access. ## Audit / Logging / Evidence Implications - Existing approve / reject / renew / revoke handling and current audit emission remain authoritative. - No new audit stream, notification family, or evidence artifact is planned. - The implementation must keep accepted-risk render paths read-only and side-effect free. - Existing related-context disclosure, decision history, and evidence references remain secondary and only appear when already repo-backed on the current owner surfaces. ## Data / Migration Implications - No database migration, backfill, or persisted projection is planned. - All derived guidance output must be request-local and DB-backed from already stored truth. - Compatibility shims are not justified because no data shape replacement is proposed in this prep slice. ## Rollout Considerations - No feature flag is expected because the slice is a bounded presentation improvement over existing repo truth. - Staging validation should still prove four operator states explicitly: - expiring accepted risk - expired, revoked, or fresh-decision-required support - incomplete governance support (owner/rationale/review due missing on an existing exception record) - calm valid state - Production risk is limited to guidance hierarchy, wrong-link regressions, and owner-surface wording drift, so focused tests and one bounded browser smoke remain the main rollout controls. ## UI / Surface Guardrail Plan - **Guardrail scope**: - `FindingExceptionsQueue` - selected-record queue summary and action hierarchy - `ViewFindingException` - downstream accepted-risk wording continuity only where already repo-backed - **Affected surfaces**: - `apps/platform/app/Filament/Pages/Monitoring/FindingExceptionsQueue.php` - `apps/platform/resources/views/filament/pages/monitoring/finding-exceptions-queue.blade.php` - `apps/platform/app/Filament/Resources/FindingExceptionResource.php` - `apps/platform/app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php` - `apps/platform/resources/views/filament/pages/monitoring/partials/finding-exception-queue-sidebar.blade.php` - `apps/platform/app/Services/Findings/FindingRiskGovernanceResolver.php` - `apps/platform/app/Support/GovernanceInbox/GovernanceInboxSectionBuilder.php` - **Native vs custom**: - preserve native Filament queue/detail ownership - avoid new custom page families - allow one bounded derived guidance adapter or selector if necessary - **Shared-family relevance**: - status messaging - next-action guidance - accepted-risk wording - evidence / decision-history disclosure - Governance Inbox to owner-surface continuity - **Required tests / smoke**: - focused unit tests for accepted-risk guidance selection - feature/Livewire tests for queue/detail rendering and scope-safe action/link hierarchy - one bounded browser smoke for the strategic queue/detail surfaces - **UI/Productization coverage**: - update `ui-012-finding-exceptions-queue.md` - create or update `ui-036-exception-detail.md` - update `route-inventory.md` coverage for `UI-036` - update `unresolved-pages.md` to remove or reclassify `UI-036` once durable coverage exists - update `design-coverage-matrix.md` only if classification or surface counts change ## Shared Pattern And System Fit - **Preferred reuse path**: - current `FindingRiskGovernanceResolver` truth - current `ResolutionCase` / `ResolutionAction` contract - current `GovernanceActionCatalog` - current queue/detail links and navigation helpers - current review-output accepted-risk wording as conservative wording reference only - **Likely implementation shape**: - one bounded `FindingExceptionResolutionAdapter` or page-local selector under the current `ResolutionGuidance` path - queue/detail-specific mapping stays local to the accepted-risk owner surfaces - existing paired lifecycle actions remain source-owned even when one dominant next-step affordance is promoted in the guidance summary - **Avoid**: - new accepted-risk workflow engine - new persisted readiness or action state - new global review-impact framework - new provider/platform abstraction ## OperationRun UX Impact Spec 354 does not create a new `OperationRun` type and does not require new `OperationRun` links on the accepted-risk owner surfaces. Implementation responsibility is limited to preserving the current no-new-OperationRun-link posture unless an already-present owner-surface related-context path exists. ## Likely Runtime Files | Area | Repo-real files | |---|---| | Queue runtime | `apps/platform/app/Filament/Pages/Monitoring/FindingExceptionsQueue.php`, `apps/platform/resources/views/filament/pages/monitoring/finding-exceptions-queue.blade.php` | | Queue focused-review partial | `apps/platform/resources/views/filament/pages/monitoring/partials/finding-exception-queue-sidebar.blade.php` | | Detail runtime | `apps/platform/app/Filament/Resources/FindingExceptionResource.php`, `apps/platform/app/Filament/Resources/FindingExceptionResource/Pages/ViewFindingException.php` | | Accepted-risk truth | `apps/platform/app/Services/Findings/FindingRiskGovernanceResolver.php`, `apps/platform/app/Services/Findings/FindingExceptionService.php` | | Shared guidance contract | `apps/platform/app/Support/ResolutionGuidance/ResolutionCase.php`, `apps/platform/app/Support/ResolutionGuidance/ResolutionAction.php` | | Adjacent routing / continuity | `apps/platform/app/Support/GovernanceInbox/GovernanceInboxSectionBuilder.php`, current related-navigation helpers | | Downstream wording reference only | `apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewComposer.php`, `apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, current review-pack summary builders | | UI audit docs | `docs/ui-ux-enterprise-audit/page-reports/ui-012-finding-exceptions-queue.md`, `docs/ui-ux-enterprise-audit/page-reports/ui-036-exception-detail.md`, `docs/ui-ux-enterprise-audit/route-inventory.md`, `docs/ui-ux-enterprise-audit/unresolved-pages.md` | ## Likely Test Files | Layer | Planned file | |---|---| | Unit | `apps/platform/tests/Unit/ResolutionGuidance/Spec354AcceptedRiskResolutionAdapterTest.php` | | Feature/Livewire | `apps/platform/tests/Feature/Monitoring/Spec354FindingExceptionsQueueGuidanceTest.php` | | Feature/Livewire | `apps/platform/tests/Feature/Findings/Spec354FindingExceptionDetailGuidanceTest.php` | | Browser | `apps/platform/tests/Browser/Spec354AcceptedRiskGuidanceSmokeTest.php` | ## Implementation Approach ### Phase 0 - Repo Truth Gate 1. Re-read `spec.md`, `plan.md`, `tasks.md`, `repo-truth-map.md`, `contracts/accepted-risk-guidance-signal-map.md`, and `checklists/requirements.md`. 2. Re-verify the current runtime truth in the queue/detail/resolver/governance files listed below. 3. Keep draft mismatches explicit: - no new accepted-risk model - no global-search change - no standalone customer-facing accepted-risk surface 4. Confirm no migration, package, env var, queue-family, storage, panel/provider, or global-search change is required. ### Phase 1 - Tests First 1. Add unit coverage for deterministic guidance selection: - valid accepted risk - expiring accepted risk - expired support - revoked or rejected support - fresh decision required - pending or renewal-requested support - missing governance support on an existing exception record - incomplete owner/rationale/review support - conservative owner-surface wording reuse without downstream artifact mutation 2. Add feature/Livewire coverage for the queue: - one dominant case - one dominant next-step affordance - existing related context only when repo-backed - no fake remediation buttons - scope-safe links and explicit `environment_id` behavior - out-of-scope access stays 404 and member-but-missing-capability behavior stays aligned with current queue semantics 3. Add feature/Livewire coverage for detail: - one dominant case - current infolist hierarchy remains detail-owned - current high-impact actions remain state- and capability-bound - owner/rationale/review support is visible before deeper diagnostics - out-of-scope detail access stays 404 and action denial remains capability-bound 4. Add one browser smoke: - queue expiring state - queue or detail expired/revoked state - detail incomplete-governance state - calm valid state ### Phase 2 - Derived Guidance Contract 1. Choose the narrowest implementation shape: - prefer one bounded accepted-risk adapter or selector - avoid expanding review-output or provider adapters into a generic risk-workflow engine 2. Build one derived accepted-risk payload with: - key - title - status - severity - reason - impact - primary action or dominant next-step mapping - secondary actions - technical details 3. Keep priority ordering explicit and narrow. 4. Preserve the current fresh-decision-required signal from `requiresFreshDecisionForFinding()` and do not expand it into a broader stale-governance framework. ### Phase 3 - Queue Integration 1. Add a top guidance presentation to `FindingExceptionsQueue` without removing current queue/table/selected-record truth. 2. Reuse existing repo-backed actions and links: - inspect accepted risk - approve exception - reject exception - open finding - existing related context only when already available on the current surface 3. Keep destructive/high-impact actions unchanged: - confirmation - authorization - audit - notifications 4. Do not widen authorization because guidance is more visible. ### Phase 4 - Detail Integration 1. Add an explicit guidance summary to the detail surface through `FindingExceptionResource::infolist()` and `ViewFindingException`. 2. Reuse current owner/rationale/expiry/review data before inventing any new accepted-risk state. 3. Keep renew and revoke source-owned. 4. Keep decision history, evidence references, and related context secondary. ### Phase 5 - Downstream Continuity 1. Reuse current Governance Inbox accepted-risk deep-link and update it only if label or target continuity is inconsistent after queue/detail guidance becomes decision-first. 2. Reuse existing conservative accepted-risk wording as owner-surface reference only; do not mutate downstream review-output artifacts in this slice. 3. Avoid turning downstream review-output surfaces into second accepted-risk owner surfaces. ### Phase 6 - Copy, Audit, And Artifacts 1. Update only the copy required in `apps/platform/lang/en/localization.php`. 2. Update matching copy in `apps/platform/lang/de/localization.php`. 3. Update `docs/ui-ux-enterprise-audit/page-reports/ui-012-finding-exceptions-queue.md`. 4. Create or update `docs/ui-ux-enterprise-audit/page-reports/ui-036-exception-detail.md`. 5. Update `docs/ui-ux-enterprise-audit/route-inventory.md` and `docs/ui-ux-enterprise-audit/unresolved-pages.md` for `UI-036`. 6. Save screenshots under the Spec 354 artifact path, or record the host-visible artifact blocker honestly. ### Phase 7 - Validation 1. Run focused unit, feature, and browser coverage for this slice. 2. Re-run current queue/detail related acceptance and guard tests in the narrowest honest family. 3. Confirm final render paths remain DB-local and do not call `GraphClientInterface` or provider HTTP during page render. 4. Run `pint` and `git diff --check`. 5. Report broader-suite or unrelated browser-harness issues honestly if they remain outside this slice.