## 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
26 KiB
Feature Specification: Finding Risk Acceptance Lifecycle
Feature Branch: 154-finding-risk-acceptance
Created: 2026-03-19
Status: Draft
Input: User description: "Create a formal exception and risk acceptance workflow for findings with approval, expiry, renewal, audit trail, and evidence linkage."
Spec Scope Fields (mandatory)
- Scope: tenant + canonical-view
- Primary Routes:
/admin/t/{tenant}/findings/{finding}as the tenant-context finding inspection surface where operators can review and initiate risk-acceptance requests/admin/t/{tenant}/exceptionsas the tenant-scoped exception register for active, pending, expiring, expired, rejected, and revoked finding exceptions/admin/exceptionsas the canonical workspace review and governance queue for authorized approvers and auditors- Existing evidence and audit destinations remain drill-down targets from exception detail when the operator is entitled to inspect them
- Data Ownership:
- Tenant-owned: finding exception records, approval decisions, renewal decisions, expiry state, revocation state, and linked evidence references for one tenant's findings
- Workspace-owned but tenant-filtered: canonical review queue state, approval workload filters, and workspace-level summaries for expiring or overdue exceptions without changing tenant ownership of the exception itself
- Existing findings, evidence snapshots, review packs, and audit events remain separate systems of record and are referenced rather than duplicated
- RBAC:
- Workspace membership remains required for every exception workflow surface
- Tenant entitlement remains required to inspect or mutate tenant-scoped exception records
finding_exception.viewpermits reviewing exception details within authorized scopefinding_exception.managepermits creating requests, renewing requests, attaching justification and evidence references, and revoking exceptions where policy allowsfinding_exception.approvepermits approving or rejecting requests and renewals within authorized scope- Non-members or users outside the relevant workspace or tenant scope remain deny-as-not-found, while in-scope members lacking the required capability remain forbidden
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active: When an operator navigates from a tenant finding into the shared exceptions queue, the canonical workspace view opens with that tenant prefiltered. The operator may clear or change the filter only within their authorized tenant set.
- Explicit entitlement checks preventing cross-tenant leakage: Exception queries, counts, approver queues, filter options, related finding labels, and linked evidence references must be assembled only after workspace and tenant entitlement checks. Unauthorized users must not learn whether another tenant has pending, active, expiring, or expired exceptions.
User Scenarios & Testing (mandatory)
User Story 1 - Propose and approve a time-bounded risk acceptance (Priority: P1)
As a tenant manager, I want to request a formal risk acceptance for a finding and route it for approval, so that a risk decision becomes explicit, reviewable, and time-bounded instead of being hidden behind a status flag.
Why this priority: This is the core governance gap. Without a first-class request and approval flow, the product still cannot answer who accepted a risk, why, and until when.
Independent Test: Can be fully tested by creating a finding, submitting a risk-acceptance request with justification and review date, approving it as an authorized approver, and verifying that the finding becomes governed by a valid active exception.
Acceptance Scenarios:
- Given a finding is open and no active exception exists, When an authorized operator submits a risk-acceptance request with justification, owner, and review deadline, Then the system creates a pending exception request linked to that finding.
- Given a pending exception request exists, When an authorized approver approves it, Then the exception becomes active with a recorded approver, decision time, and expiry date.
- Given a pending exception request exists, When an authorized approver rejects it, Then the request records the rejection outcome and reason without changing the finding into an accepted-risk state.
- Given a user lacks the relevant capability or tenant entitlement, When they attempt to create or approve an exception request, Then the server denies the action with the correct 404 or 403 behavior.
User Story 2 - See whether accepted risk is still valid (Priority: P1)
As an auditor or workspace approver, I want a clear register of pending, active, expiring, expired, rejected, and revoked exceptions, so that I can tell which accepted risks are still valid and which require action.
Why this priority: A risk-acceptance workflow is only governable if operators can review its current state without reconstructing history from comments and status changes.
Independent Test: Can be fully tested by creating exception records in several lifecycle states and verifying that tenant and canonical views expose the correct state, dates, owners, and next-action cues without leaking unauthorized tenant data.
Acceptance Scenarios:
- Given a tenant has pending, active, and expired exceptions, When an authorized operator opens the tenant exception register, Then each exception clearly shows its lifecycle state, finding, owner, approver context, and review timing.
- Given an approver is responsible for multiple tenants, When they open the canonical exceptions queue, Then they can filter by tenant, state, and due timing without seeing unauthorized tenants.
- Given an active exception is nearing expiry, When an authorized operator inspects the register, Then the exception is visibly distinguished from long-valid exceptions.
- Given no exception matches the current filters, When the operator opens the register, Then the empty state explains that no governed exceptions match and offers exactly one clear next action.
User Story 3 - Renew or revoke an accepted risk with audit evidence (Priority: P2)
As a governance operator, I want to renew or revoke an existing accepted risk with a durable decision trail and linked evidence, so that exceptions stay current rather than becoming permanent silent waivers.
Why this priority: Time-bounded approval loses value if the product cannot handle renewal and revocation as first-class governance decisions.
Independent Test: Can be fully tested by renewing an active exception with new justification and evidence references, revoking another one, and verifying that lifecycle history, current validity, and audit trail remain intelligible.
Acceptance Scenarios:
- Given an active exception is approaching expiry, When an authorized operator submits a renewal request with updated justification and supporting evidence references, Then the system records a new renewal decision path without rewriting the earlier decision.
- Given a renewal request exists, When an authorized approver approves it, Then the active-validity window extends and the prior decision history remains visible.
- Given an active exception is no longer acceptable, When an authorized operator revokes it with a reason, Then the exception becomes revoked and no longer counts as valid risk acceptance.
- Given a linked evidence snapshot or supporting artifact later disappears from active views, When an operator reviews the exception history, Then the exception remains understandable from stored reference metadata.
User Story 4 - Detect governance drift in accepted-risk findings (Priority: P2)
As a compliance-focused operator, I want the system to surface findings marked as accepted risk without a currently valid exception, so that governance drift is visible instead of silently undermining auditability.
Why this priority: The business risk is not just missing workflow. It is false confidence when a finding looks accepted even though its approval expired, was revoked, or never existed.
Independent Test: Can be fully tested by creating findings in accepted-risk status with valid, expired, revoked, and missing exception records and verifying that only truly valid exceptions count as accepted governance state.
Acceptance Scenarios:
- Given a finding is marked as accepted risk and has a valid active exception, When the operator inspects it, Then the finding shows that the acceptance is governed and time-bounded.
- Given a finding is marked as accepted risk but the linked exception is expired, revoked, or absent, When the operator inspects it or opens the exception queue, Then the system surfaces it as a governance warning rather than a valid accepted risk.
- Given a downstream review or evidence workflow summarizes accepted risks, When it evaluates findings, Then only findings backed by a currently valid exception count as active risk acceptance.
Edge Cases
- A finding is resolved or closed while an exception request is still pending; the request must not silently convert into an active accepted risk without an explicit decision.
- A finding remains in
risk_acceptedstatus after the governing exception expires or is revoked; the system must show that the risk state is no longer valid. - An operator attempts to renew an exception that is already expired; the renewal path must remain explicit and must not overwrite the expired decision history.
- The same person requests and approves an exception; the system must block self-approval in v1 because requester and approver must be different users and no override path exists in this slice.
- A finding reopens through detection recurrence while a previous exception exists; the system must make it clear whether the earlier exception still governs the re-opened risk or whether a fresh decision is required.
- Evidence linked to an exception may be partial, stale, or later removed from active surfaces; the exception history must preserve enough reference context for review.
- A workspace approver can review multiple tenants, but must not see queue counts, labels, or filter values for unauthorized tenants.
Requirements (mandatory)
Constitution alignment (required): This feature introduces a new governance data model and new user-driven write behavior, but no new Microsoft Graph calls. Exception request, approval, renewal, rejection, expiry, and revocation are security-relevant DB-backed governance mutations and must be explicitly audited. The feature must define tenant isolation, approval safety, validity semantics, linked-evidence semantics, and tests for valid, expired, revoked, missing, and unauthorized paths. If scheduled reminder or expiry evaluation is introduced, it must describe how that work is observable and how it avoids cross-tenant leakage.
Constitution alignment (OPS-UX): The primary workflow is synchronous governance mutation and does not require a dedicated long-running OperationRun for request, approval, rejection, renewal, or revocation. These decisions must therefore be observable through audit history, surface state changes, and user notifications instead of an operation progress surface. If the product later adds scheduled reminder or expiry evaluation, that work may integrate with existing monitoring or alerting patterns, but the first release of this feature does not rely on a new operator-facing progress workflow.
Constitution alignment (RBAC-UX): This feature operates in the tenant/admin plane for tenant-scoped finding and exception surfaces and in the workspace-admin canonical view for the approval queue. Cross-plane access remains deny-as-not-found. Non-members or users outside workspace or tenant scope receive 404. In-scope users lacking finding_exception.view, finding_exception.manage, or finding_exception.approve receive 403 according to the attempted action. Authorization must be enforced server-side for request creation, approval, rejection, renewal, revocation, and any canonical queue action. The canonical capability registry remains the only capability source. Destructive-like actions such as revoke and reject require confirmation.
Constitution alignment (OPS-EX-AUTH-001): Not applicable. No authentication handshake behavior is changed.
Constitution alignment (BADGE-001): Exception lifecycle state, risk-governance validity, and due-timing indicators are status-like values and must use centralized badge semantics rather than per-page color choices. Tests must cover all introduced states such as pending, active, expiring, expired, rejected, and revoked.
Constitution alignment (UI-NAMING-001): The target object is the finding exception. Operator-facing verbs are Request exception, Approve exception, Reject exception, Renew exception, and Revoke exception. The term risk acceptance describes the governance outcome, while exception names the governed record. The same vocabulary must be preserved across finding detail, exception register, approval queue, audit prose, and notifications. Implementation-first terms such as waiver row, approval token, or state machine must not become primary labels.
Constitution alignment (Filament Action Surfaces): This feature modifies tenant finding detail and introduces exception list and detail inspection surfaces plus approval actions. The Action Surface Contract is satisfied by explicit header actions on tenant and canonical list surfaces, canonical inspect affordances, and authorization-gated audited mutations. Bulk mutation actions are explicitly exempted for the tenant register and canonical queue in v1 because exception decisions are high-risk governance records and this slice intentionally avoids bulk approve, bulk reject, bulk renew, bulk revoke, or bulk export semantics until a later spec defines safe confirmation, audit, and review behavior.
Constitution alignment (UX-001 — Layout & Information Architecture): Exception list screens must provide search, sort, and filters for state, tenant, owner, approver, and expiry timing. Exception detail must be an inspection surface using Infolist-style composition rather than a disabled edit form. Creation and renewal may use a structured modal or dedicated form surface, but must keep justification, owner, timing, and evidence references grouped inside sections. Empty states must include a specific title, explanation, and exactly one CTA.
Functional Requirements
- FR-001: The system MUST provide a first-class finding exception record that governs formal risk acceptance for a specific finding.
- FR-002: A finding exception MUST capture at minimum the target finding, requester, accountable owner, requested justification, requested decision time, and the bounded validity window for accepted risk.
- FR-003: The system MUST support an exception lifecycle that distinguishes at least pending, active, expiring, expired, rejected, revoked, and superseded or renewed states.
- FR-004: An operator MUST be able to request risk acceptance for a finding without directly bypassing the approval lifecycle.
- FR-005: The system MUST support explicit approval and explicit rejection of pending exception requests, with durable decision reason and actor history.
- FR-006: The system MUST support renewal of an existing exception as a new governance decision that preserves earlier request and approval history.
- FR-007: The system MUST support explicit revocation of an active exception, with recorded actor, time, and revocation reason.
- FR-008: The system MUST treat a finding as having valid accepted risk only while a currently valid active exception exists for that finding.
- FR-009: A finding in
risk_acceptedstatus without a currently valid exception MUST be surfaced as a governance warning rather than a fully governed accepted risk. - FR-010: One finding MAY have multiple historical exception records over time, but the system MUST allow at most one currently governing active exception and MUST block parallel pending request or renewal workflows for the same finding until the in-flight workflow reaches a terminal state.
- FR-011: Exception requests and renewals MUST support structured supporting context, including freeform justification and one or more linked evidence references when available.
- FR-012: Evidence references linked to an exception MUST remain intelligible even if the live evidence artifact later expires, is superseded, or becomes inaccessible from normal active views.
- FR-013: The system MUST provide a tenant-scoped exception register that allows authorized operators to review current and historical exception records for that tenant.
- FR-014: The system MUST provide a canonical workspace approval and governance queue that allows authorized viewers to review pending, expiring, expired, rejected, and revoked exceptions across entitled tenants.
- FR-015: Tenant and canonical views MUST provide filters for lifecycle state, due timing, requester, owner, approver, and finding severity or type where relevant.
- FR-016: The system MUST make upcoming expiry and already-expired exceptions clearly visible so that time-bounded risk acceptance does not silently lapse.
- FR-017: The first release MUST define reminder semantics as passive in-product visibility only: exceptions nearing expiry are highlighted in tenant finding detail, tenant exception register, canonical queue, and exception detail for the requester, accountable owner, tenant managers, and entitled workspace approvers; users with only
finding_exception.viewmay inspect due-state badges when they are otherwise entitled, but do not receive management CTAs; no scheduled notifications, emails, or background reminder jobs are introduced in v1. - FR-018: All exception lifecycle mutations must be recorded in audit history with workspace scope, tenant scope, actor, target finding context, action, outcome, and readable supporting context.
- FR-019: Exception audit records MUST be summary-first and MUST NOT store secrets, raw evidence payloads, or arbitrary oversized snapshots.
- FR-020: The system MUST enforce 404 deny-as-not-found behavior for non-members and out-of-scope users, and 403 behavior for in-scope users lacking the required capability.
- FR-021: The feature MUST block normal self-approval in v1. The requester and approver must be different users, and no self-approval override path exists in this slice; any future override path requires a dedicated follow-up spec with explicit governance, audit, and authorization rules.
- FR-022: The feature MUST preserve intelligible history when a finding later resolves, closes, reopens, or changes severity after an exception decision, including clear display of the exception decision timeline and whether the current finding state is still governed, expired, revoked, or requires a fresh decision.
Exception Concurrency And Reminder Rules
- A finding may accumulate multiple historical exception records across time, but only one active governing exception may exist at once.
- If a finding already has a pending initial request or pending renewal workflow, the system blocks creation of an additional pending request for that same finding.
- Renewal extends governance through the current exception record and its decision history rather than creating parallel competing active records.
- Reminder behavior in v1 is limited to visual due-state cues and queue visibility inside the existing tenant and canonical surfaces; requester, accountable owner, tenant managers, and entitled workspace approvers receive these cues in the surfaces they can access, while view-only users can inspect the due state without management actions; no scheduled reminders or external notifications are part of this slice.
- FR-023: Downstream review, evidence, and reporting workflows that summarize accepted risk MUST distinguish valid governed exceptions from expired, revoked, rejected, or missing ones.
- FR-024: The feature MUST introduce at least one positive and one negative authorization test for tenant-context request flows and canonical approval-queue flows.
- FR-025: The feature MUST introduce regression tests for pending, approved, rejected, renewed, revoked, expired, and missing-exception states, plus wrong-tenant and invalid-transition paths.
UI Action Matrix (mandatory when Filament is changed)
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Finding Detail Risk Panel | Tenant-context finding inspection under /admin/t/{tenant}/findings/{finding} |
Request exception (finding_exception.manage) when no valid exception exists |
Linked exception summary card or explicit View exception affordance |
View exception, Request exception or Renew exception depending on state |
None | Request first exception when no governance record exists |
Renew exception, Revoke exception when authorized |
N/A | Yes | Action labels must describe the governance object, not just the finding status |
| Tenant Exception Register | Tenant-context list under /admin/t/{tenant}/exceptions |
Request exception when current tenant context contains an eligible finding; Clear filters |
Clickable row to exception detail | View exception, Renew exception or Revoke exception depending on state |
Explicit exemption in v1: no grouped bulk actions because exception decisions are high-risk governance mutations that require per-record review and confirmation | Request first exception |
None | N/A | Yes | Inspection-first surface; bulk actions intentionally deferred to a future safety spec |
| Canonical Exceptions Queue | Workspace canonical view at /admin/exceptions |
Clear filters, View tenant register for the currently selected tenant filter |
Clickable row to exception detail | Approve exception, Reject exception for pending items |
Explicit exemption in v1: no grouped bulk actions because approval and rejection remain per-record governance decisions with tenant-specific context | Clear filters |
None | N/A | Yes | Queue must remain tenant-safe and only show entitled tenants |
| Exception Detail | Tenant or canonical detail inspection surface | None | N/A | None | None | N/A | Approve exception, Reject exception, Renew exception, Revoke exception depending on state and capability |
N/A | Yes | Detail is an inspection surface, not a disabled edit form |
Key Entities (include if feature involves data)
- Finding Exception: A governed risk-acceptance record for one finding, including request context, decision state, validity timing, and current governance outcome.
- Exception Decision: A durable approval, rejection, renewal, or revocation record that explains who made the decision, when, and why.
- Exception Evidence Reference: A structured pointer to supporting evidence used to justify or review an exception, preserved as intelligible reference metadata.
- Risk Governance Validity: The normalized truth of whether a finding's accepted-risk posture is currently valid, expiring soon, expired, revoked, rejected, or unsupported.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: An authorized operator can request and route a formal finding exception in under 3 minutes without leaving the product.
- SC-002: In automated tests, 100% of findings counted as valid accepted risk are backed by a currently valid active exception.
- SC-003: In acceptance review, an authorized auditor can answer who requested, who approved, why it was accepted, and until when it remains valid within 2 minutes using the product alone.
- SC-004: Expired, revoked, rejected, and missing-governance accepted-risk states are all distinguishable in automated regression coverage with no false classification as valid active acceptance.
- SC-005: Negative authorization tests prove that non-members or wrong-tenant users receive deny-as-not-found behavior and in-scope users without the required capability cannot request, approve, renew, or revoke exceptions.
- SC-006: Renewal and revocation flows preserve prior decision history in automated tests rather than overwriting the previous governance record.
Measurement Notes
- SC-001 is measured manually during the quickstart on a seeded local Sail environment with one workspace, one tenant, one eligible open finding, and distinct requester and approver users. The timer starts on tenant finding detail and stops when a complete request is visible in the canonical queue on the first successful run.
- SC-003 is measured manually during the quickstart on the same seeded baseline. The timer starts on exception detail and stops when the reviewer can point to requester, approver, justification, and validity-window evidence in the product UI on the first successful run.
Assumptions
- Spec 111 remains the product source of truth for finding lifecycle and status semantics, including the existing
risk_acceptedstatus. - Spec 134 remains the source of truth for canonical audit readability and event history behavior.
- Evidence linkage may reference evidence snapshots, review artifacts, or other governance evidence when available, but the exception lifecycle must not be blocked merely because evidence is partial.
- Normal approval flow blocks self-approval in v1; no override path exists in this slice.
- The first rollout focuses on finding-specific exceptions, not a generic cross-domain waiver engine.
Non-Goals
- Replacing the existing findings workflow with a different status model
- Creating a generic exception platform for every future domain in the first slice
- Suppressing or deleting findings automatically when risk is accepted
- Making legal or certification claims about compliance acceptance
- Replacing evidence snapshots, review packs, or the broader audit foundation with exception-owned storage
Dependencies
- Findings workflow semantics and lifecycle rules from
specs/111-findings-workflow-sla/spec.md - Audit history foundation and event readability rules from
specs/134-audit-log-foundation/spec.md - Evidence-domain linkage patterns from
specs/153-evidence-domain-foundation/spec.mdwhen evidence snapshots are available