TenantAtlas/specs/354-finding-exceptions-accepted-risk-resolution-guidance-v1/plan.md
ahmido a9c54205bf feat: finding exceptions accepted risk resolution guidance v1 (spec 354) (#425)
Implemented the accepted risk resolution guidance, including the AcceptedRiskResolutionAdapter, guidance cards, and updated related Filament views. Added unit, feature, and browser tests.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #425
2026-06-05 02:20:46 +00:00

298 lines
16 KiB
Markdown

# 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.