# Feature Specification: Findings Workflow Enforcement and Audit Backstop **Feature Branch**: `151-findings-workflow-backstop` **Created**: 2026-03-18 **Status**: Draft **Input**: User description: "nimm strategisch das beste und sinnvollste aus spec-candidate" ## Spec Scope Fields *(mandatory)* - **Scope**: tenant + canonical-view - **Primary Routes**: - Tenant-context Findings list and detail pages under `/admin/t/{tenant}/...` - Existing Findings workflow action endpoints triggered from tenant-context Filament list, bulk, and view surfaces - Canonical audit review surface at `/admin/audit-log` where resulting workflow history is reviewed - **Data Ownership**: - Tenant-owned: `Finding` lifecycle truth, assignment metadata, transition reasons, and recurrence-driven status changes - Workspace-owned: audit events that record meaningful workflow mutations and preserve historical reviewability - Existing review-pack, reporting, and monitoring outputs remain downstream consumers of the same finding truth and are not redefined by this feature - **RBAC**: - Tenant membership remains the isolation boundary for finding visibility and workflow mutation - Findings view and mutation capabilities remain tenant-context capability-gated through the canonical capability registry - Audit review remains workspace-scoped and capability-gated through existing audit visibility rules - Non-members remain deny-as-not-found; in-scope members without the required capability remain forbidden For canonical-view specs, the spec MUST define: - **Default filter behavior when tenant-context is active**: The canonical audit review surface remains at `/admin/audit-log`. When an operator arrives from tenant context, audit review may prefilter to the active tenant, but it must remain on the shared audit route and must not imply broader tenant visibility than the viewer is entitled to see. - **Explicit entitlement checks preventing cross-tenant leakage**: Audit rows, filter options, drill-down labels, and finding-related links must be assembled only after workspace and tenant entitlement checks succeed for the referenced tenant-bound finding. Unauthorized viewers must not learn about finding existence, prior status, assignee, or tenant identity through audit metadata. ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Prevent invalid workflow bypasses (Priority: P1) As a tenant operator, I need every meaningful finding workflow mutation to pass through one enforced transition contract, so that invalid status changes or direct persistence shortcuts cannot create workflow truth that the product did not explicitly allow. **Why this priority**: This closes the main architectural gap. Spec 111 defined the workflow, but the repo still relies too much on disciplined service usage instead of making bypasses impossible or immediately detectable. **Independent Test**: Can be fully tested by attempting valid and invalid status changes through single-record actions, bulk actions, and direct persistence-style paths, then confirming that only allowed transitions succeed. **Acceptance Scenarios**: 1. **Given** a finding is in an open workflow state, **When** an allowed workflow action is executed, **Then** the finding transitions successfully through the canonical workflow path. 2. **Given** a finding is in a state that does not permit the requested next state, **When** a workflow mutation is attempted, **Then** the mutation is refused before persistence. 3. **Given** a covered workflow mutation path attempts to bypass the canonical transition path, **When** the mutation executes, **Then** the system fails closed instead of silently accepting the change. --- ### User Story 2 - Trust the audit history for findings lifecycle changes (Priority: P1) As a compliance-focused operator, I need every meaningful findings workflow change to leave one complete, understandable audit trail, so that I can answer who changed what, from which state, for which tenant, and why. **Why this priority**: A workflow that can change state without durable historical evidence is not enterprise-grade. Auditability is the required backstop when UI discipline or service discipline fails. **Independent Test**: Can be fully tested by executing representative workflow changes and verifying that each one produces exactly one readable audit history entry with the correct scope, actor, transition, and reason metadata. **Acceptance Scenarios**: 1. **Given** a user triages, resolves, closes, risk-accepts, reopens, or reassigns a finding, **When** the mutation succeeds, **Then** one audit entry records the meaningful before-and-after lifecycle change. 2. **Given** a system-driven workflow change such as automatic reopen or automatic resolve occurs, **When** the mutation succeeds, **Then** the audit trail records that the change was system-driven rather than a human action. 3. **Given** the finding is later deleted, renamed, or no longer directly accessible, **When** the operator reviews the audit history, **Then** the workflow event remains intelligible from stored summary data. --- ### User Story 3 - Keep recurrence and reopen semantics consistent across all mutation paths (Priority: P2) As a product owner, I need recurrence, reopen, and other system-driven lifecycle behaviors to use the same enforced workflow truth as interactive UI actions, so that no second lifecycle model emerges for automated findings changes. **Why this priority**: The workflow becomes fragile again if human actions are hardened but recurrence, reopen, or auto-resolve logic still write state through side paths. **Independent Test**: Can be fully tested by exercising recurrence detection, reopen behavior, and auto-resolve behavior through representative automated flows and confirming they follow the same transition validity and audit rules. **Acceptance Scenarios**: 1. **Given** a previously resolved finding is detected again, **When** recurrence handling runs, **Then** the reopen uses the same canonical transition truth as a user-driven reopen. 2. **Given** a drift finding is no longer detected and qualifies for automatic resolution, **When** system-driven closure logic runs, **Then** the resulting state change follows the same transition guard and audit contract. 3. **Given** a concurrent user action and automated lifecycle update target the same finding, **When** both flows are evaluated, **Then** the final persisted result remains valid under one workflow contract and the audit trail remains coherent. ### Edge Cases - A bulk action targets findings that span multiple current statuses, some of which permit the transition and some of which do not. - A direct update changes assignment or lifecycle-reason metadata without using the canonical workflow mutation path. - A recurrence or auto-resolve flow attempts to change status after a human user already moved the finding to a different terminal state. - A no-op save re-submits the current status and reason fields without any meaningful lifecycle change. - A workflow mutation succeeds, but the normal audit-writing path is unavailable or skipped; the feature must still prevent silent history loss. - An audit viewer is entitled to the workspace but no longer entitled to the tenant that owned the historical finding. ## Requirements *(mandatory)* **Constitution alignment (required):** This feature introduces no new Microsoft Graph calls and no new product workflow states. It hardens existing write behavior around findings lifecycle truth and meaningful audit history. Because it governs security-relevant DB-only mutations, it must define one canonical transition path, fail-closed behavior for bypass attempts, tenant isolation, and durable `AuditLog` coverage instead of relying on UI discipline alone. Existing queue-backed runbooks such as findings lifecycle backfill remain outside the primary scope except where they must obey the same lifecycle truth rules for any state changes they perform. **Constitution alignment (OPS-UX):** This feature does not create a new `OperationRun` type and does not change the Ops-UX 3-surface contract. Existing operational runbooks that already use `OperationRun` keep their current behavior. This spec is about workflow truth and auditability for findings mutations, not about new start surfaces, progress surfaces, or terminal run notifications. **Constitution alignment (RBAC-UX):** This feature operates in the tenant/admin plane for findings workflow actions and in the canonical admin monitoring plane for audit review. Cross-plane access remains deny-as-not-found. Non-members or users not entitled to the workspace or tenant scope remain `404`. In-scope members lacking the required capability remain `403`. Server-side authorization remains mandatory for every findings mutation path, including bulk actions and any automated or service-owned workflow entry point that runs on behalf of a human actor. The capability registry remains canonical, global search behavior is unchanged, and destructive-like actions such as resolve, close, risk accept, and reopen remain confirmation-gated where already required. **Constitution alignment (OPS-EX-AUTH-001):** Not applicable. This feature does not alter authentication handshake behavior or Monitoring page outbound work. **Constitution alignment (BADGE-001):** The set of finding status values does not change. Existing centralized finding-status badge semantics remain the only allowed presentation source, and tests must continue to prove that audit and findings surfaces do not introduce ad hoc status label mappings. **Constitution alignment (UI-NAMING-001):** The target object is the finding lifecycle change. Operator-facing verbs remain `Triage`, `Start progress`, `Assign`, `Resolve`, `Close`, `Risk accept`, and `Reopen`. Audit prose must preserve the same domain vocabulary across workflow buttons, confirmations, and audit summaries, and must avoid implementation-first language such as internal transition engine terms or persistence jargon. **Constitution alignment (Filament Action Surfaces):** This feature modifies existing Findings Filament surfaces by enforcing one transition contract behind list, bulk, and view actions and by requiring audit-safe outcomes for those mutations. The Action Surface Contract is satisfied because destructive-like actions remain explicit, confirmed, capability-gated, and auditable. **Constitution alignment (UX-001 — Layout & Information Architecture):** This feature does not add new create or edit screens. Existing Findings list and detail screens keep their current layout. UX impact is limited to preserving consistent workflow actions, keeping the existing explicit empty state, and ensuring view and list surfaces reflect canonical status truth rather than hidden side-path mutations. ### Functional Requirements - **FR-151-001**: The system MUST define one canonical findings workflow mutation path for all in-scope lifecycle changes. - **FR-151-002**: The canonical findings workflow mutation path MUST enforce the allowed lifecycle transitions already defined by Spec 111 rather than redefining the findings lifecycle. - **FR-151-003**: In-scope lifecycle changes MUST include at least status transitions, manual reopen, automated reopen, automated resolve, assignee or owner changes, and terminal-reason updates that materially change workflow history. - **FR-151-004**: Any in-scope mutation attempt that does not satisfy the canonical transition contract MUST be refused before persistence. - **FR-151-005**: Covered findings list actions, bulk actions, and detail-page actions MUST use the same canonical workflow mutation path rather than separate local transition logic. - **FR-151-006**: Automated findings lifecycle paths that reopen, resolve, or otherwise materially advance workflow truth MUST use the same canonical workflow mutation path as interactive actions. No narrow or audited exemption is declared for this feature slice. - **FR-151-007**: The system MUST prevent silent direct status mutation in covered flows. A covered bypass attempt MUST either be blocked or be forced through the canonical workflow mutation path before persistence. - **FR-151-008**: Every successful in-scope findings workflow mutation MUST produce exactly one meaningful audit event describing actor class, workspace scope, tenant scope, target finding, before state, after state, and reason metadata when applicable. - **FR-151-009**: The audit backstop MUST ensure that a meaningful workflow mutation cannot complete successfully without durable audit history, even if a preferred audit-writing path is skipped. - **FR-151-010**: The audit backstop MUST avoid duplicate audit history for the same successful findings workflow mutation. - **FR-151-011**: Audit metadata for findings workflow changes MUST remain summary-first and MUST NOT store raw evidence payloads, secrets, or oversized snapshots. - **FR-151-012**: System-driven lifecycle mutations MUST be auditable as system-originated changes and MUST remain distinguishable from human-initiated workflow actions. - **FR-151-013**: Reopen, recurrence, and auto-resolve behavior defined by Spec 111 MUST remain valid after this hardening and MUST not create a second lifecycle truth model. - **FR-151-014**: When concurrent workflow mutations target the same finding, the persisted result MUST still satisfy the canonical lifecycle rules and the resulting audit history MUST remain internally coherent. - **FR-151-015**: Findings workflow audit history MUST remain understandable even when the finding is later deleted, merged, consolidated, or no longer directly viewable to the current operator. - **FR-151-016**: Audit review surfaces MUST continue to enforce workspace and tenant entitlement before showing finding-related historical detail, labels, or links. - **FR-151-017**: The feature MUST add negative-path regression coverage for invalid transitions, bypass attempts, missing-audit scenarios, and recurrence edge cases. - **FR-151-018**: The feature MUST add positive-path regression coverage for representative human-driven and system-driven workflow mutations. - **FR-151-019**: This feature MUST NOT introduce new finding statuses, new findings capabilities, or a new exception or risk-acceptance entity lifecycle. - **FR-151-020**: This feature MUST document the narrow boundary between workflow enforcement and audit backstop so future lifecycle-heavy domains can reuse the pattern without copying findings-specific semantics. ## 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 | |---|---|---|---|---|---|---|---|---|---|---| | Findings Resource | Tenant-context Findings list and detail pages | Existing lifecycle utilities only; no new top-level destructive action required for this spec | Existing view affordance and linked record navigation remain | `View`, `Workflow` | `Workflow` group | `Clear filters` | `Workflow` | N/A | Yes | `Workflow` remains the operator surface for `Triage`, `Start progress`, `Assign`, `Resolve`, `Close`, `Risk accept`, and `Reopen`. All destructive-like transitions remain confirmation-gated and capability-gated. | ### Key Entities *(include if feature involves data)* - **Finding lifecycle mutation**: A meaningful change to a finding's workflow truth, such as status progression, reopen, automatic resolution, or ownership change that operators rely on for governance. - **Workflow transition rule**: The allowed before-and-after lifecycle relationship that makes a findings mutation valid. - **Findings workflow audit event**: The durable historical record that explains who or what changed a finding lifecycle state, in which tenant scope, and why. - **System-originated lifecycle change**: A recurrence, auto-resolve, or other product-driven update that changes workflow truth without a direct user click. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-151-001**: 100% of covered findings workflow mutations in automated tests produce exactly one audit event with actor class, tenant scope, before state, and after state. - **SC-151-002**: 0 covered invalid findings lifecycle transitions succeed in automated regression tests. - **SC-151-003**: Representative human-driven and system-driven findings lifecycle mutations both pass through one enforced transition contract in acceptance testing. - **SC-151-004**: In regression tests where the target finding later becomes inaccessible, authorized audit viewers can still understand the historical workflow event without opening the live record. - **SC-151-005**: CI includes at least one negative guard that fails when a covered findings workflow path bypasses the canonical transition contract or loses audit coverage. ## Non-Goals - Introducing a new findings workflow state model - Creating a first-class risk exception entity or approval workflow - Redesigning the Findings UI information architecture beyond what enforcement requires - Replacing the broader audit foundation with findings-specific history storage - Turning all low-signal finding field updates into auditable lifecycle events ## Assumptions - Spec 111 remains the product source of truth for allowed findings statuses and core lifecycle semantics. - Spec 134 remains the source of truth for canonical audit review, event readability, and audit visibility rules. - Existing findings capabilities and confirmation rules remain adequate for this hardening slice. - The current product already has representative human-driven and automated findings mutation paths worth hardening under one pattern. - No automation-path exemption from the canonical workflow gateway is allowed in this slice; any future exemption would require a follow-up spec change. ## Dependencies - Spec 111 - Findings Workflow V2 + SLA - Spec 134 - Audit Log Foundation - Existing tenant isolation and capability enforcement for Findings actions - Existing findings recurrence, detection, and auto-resolve behavior that must be brought under the same lifecycle truth model