# Feature Specification: Findings Notifications & Escalation v1

**Feature Branch**: `224-findings-notifications-escalation`  
**Created**: 2026-04-22  
**Status**: Draft  
**Input**: User description: "Findings Notifications & Escalation v1"

## Spec Candidate Check *(mandatory — SPEC-GATE-001)*

- **Problem**: Findings now have clear owner-versus-assignee semantics plus personal and shared work surfaces, but assignment, automatic reopen, and aging transitions still remain silent unless operators keep polling findings pages.
- **Today's failure**: A finding can be assigned, auto-reopened, become due soon, or become overdue without the responsible operator noticing in time. Due dates become passive metadata instead of a real control loop.
- **User-visible improvement**: Responsible operators receive calm, tenant-safe notifications with one clear deep link when work is assigned, reopens automatically, approaches its due date, or becomes overdue. Workspace teams can optionally add existing external alert copies without building a second findings-specific notification system.
- **Smallest enterprise-capable version**: Add four finding event types, one bounded recipient-resolution contract over existing owner and assignee truth, direct personal notifications for actionable finding events, and optional workspace-level external copies through the existing Alerts rules and destinations.
- **Explicit non-goals**: No multi-stage escalation chains, no notification-preference center, no comments or chat, no external ticket synchronization, no new owner-only queue, and no generic workflow engine.
- **Permanent complexity imported**: Four finding event types, one bounded recipient-resolution contract, one direct-notification copy contract, and focused regression coverage for entitlement-safe delivery and dedupe.
- **Why now**: Spec 219 clarified responsibility, Spec 221 created the personal assignee queue, and Spec 222 created shared intake. The next missing slice is to close the loop so those surfaces no longer rely on manual polling.
- **Why not local**: A badge or queue-only polish fix would still leave assignment, reopen, and aging changes silent across the workspace. The gap is cross-cutting workflow feedback, not one page.
- **Approval class**: Core Enterprise
- **Red flags triggered**: One bounded new recipient-resolution rule and one new event family. Scope stays acceptable because it reuses existing finding truth, existing alert delivery infrastructure, and existing notification primitives.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 1 | **Gesamt: 10/12**
- **Decision**: approve

## Spec Scope Fields *(mandatory)*

- **Scope**: workspace
- **Primary Routes**:
  - Admin UI → Workspace → Monitoring → Alerts → Alert rules
  - Admin UI → Workspace → Monitoring → Alerts → Alert deliveries
  - `/admin/t/{tenant}/findings/{finding}` as the primary follow-up destination from finding notifications
- **Data Ownership**:
  - Tenant-owned findings remain the only source of truth for assignment, reopen state, due state, severity, and tenant scope.
  - Workspace-owned alert rules and alert destinations remain the only source of truth for external copies and shared escalation delivery.
  - Existing user notification records remain delivery artifacts only and must not become a second findings workflow state store.
- **RBAC**:
  - Workspace membership is required for alert rule and alert delivery surfaces.
  - `ALERTS_VIEW` gates viewing alert-rule configuration and alert delivery history.
  - `ALERTS_MANAGE` gates creating, editing, enabling, disabling, or deleting external alert-copy rules.
  - Direct finding notifications are only delivered to currently entitled operators who may already inspect the target tenant and finding scope.
  - Non-members or wrong-plane requests remain deny-as-not-found. Members missing capability receive `403` on protected configuration surfaces.

## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*

| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Alert rules resource gains finding notification event types and routing copy | yes | Native Filament resource forms + existing alert configuration primitives | Same workspace monitoring configuration family as existing alert rules | form, event labels, routing helper copy | no | Existing surface extended; no new alert page |
| Alert deliveries viewer gains finding-event labels and delivery visibility | yes | Native Filament table + existing alert delivery viewer | Same workspace alert observability family | table, filter labels, delivery summaries | no | Existing viewer extended; still read-only |
| Direct finding notifications and deep links | yes | Existing in-app notification primitives + shared link helpers | Same personal workflow entry-point family as other operator notifications | notification payload, deep link, recipient explanation | no | Reuses current notification surface; no new notification center |

## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*

| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Alert rules resource gains finding notification event types and routing copy | Secondary Context Surface | A workspace operator decides which finding events should also create external or shared-team copies | Event type, tenant scope, severity threshold, cooldown, quiet-hours, and destinations | Delivery history, raw event keys, and failure diagnostics | Secondary because it configures workflow feedback rather than hosting the work itself | Keeps findings notification policy inside existing Alerts administration | Avoids inventing a second findings-specific settings area |
| Alert deliveries viewer gains finding-event labels and delivery visibility | Tertiary Evidence / Diagnostics Surface | A workspace operator verifies whether rule-based copies were sent, deferred, suppressed, or failed | Event label, tenant, severity, status, and timestamp | Safe diagnostics and historical delivery details | Tertiary because it explains delivery history after the notification decision already happened | Preserves one audit-style surface for external delivery truth | Avoids debugging notification behavior by searching logs or guessing destination behavior |
| Direct finding notifications and deep links | Secondary Context Surface | An operator receives a finding event and decides whether to open the finding now | Why the operator was notified, the affected tenant, the finding summary, severity, and one deep link | Full finding detail, evidence, audit trail, and workflow actions after opening the finding | Secondary because the notification points into the real work surface instead of replacing it | Aligns assignment and aging signals with the already-established findings workflow surfaces | Removes repeated polling of My Findings, intake, and tenant-local findings pages |

## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*

| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Alert rules resource gains finding notification event types and routing copy | Config / Settings | Workflow routing configuration | Save or update a rule for finding events | Alert rule | required on the existing list | Existing `More` group on the alert-rules list | Existing destructive actions remain grouped and confirmed on the resource | Workspace Monitoring → Alerts → Alert rules | Existing alert-rule edit surface | Workspace scope, event type, severity, tenant targeting, destinations | Alert rules / Alert rule | Which finding events are routed externally and under which scope rules | none |
| Alert deliveries viewer gains finding-event labels and delivery visibility | Utility / System | Read-only log / report surface | Inspect whether a finding-event delivery was sent or suppressed | Alert delivery | allowed on the existing viewer | Existing read-only filter and inspect controls only | none | Workspace Monitoring → Alerts → Alert deliveries | Existing delivery inspect surface | Workspace scope, tenant label, delivery status, event type | Alert deliveries / Alert delivery | Whether a finding-event copy was sent, deferred, suppressed, or failed | none |
| Direct finding notifications and deep links | Utility / System | Notification / drill-in entry point | Open the finding that needs follow-up | Finding | forbidden | No competing mutation; one deep link only | none | Existing in-app notification surface | `/admin/t/{tenant}/findings/{finding}` | Tenant name, severity, recipient reason, event label | Findings / Finding | Why this operator was notified and what finding requires attention | Existing notification surface reused; no new standalone page |

## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*

| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Alert rules resource gains finding notification event types and routing copy | Workspace operator with alert-management responsibility | Decide which finding events should create external copies or shared escalation signals | Configuration surface | Which finding workflow events should notify beyond the directly responsible operator? | Event type, minimum severity, tenant scope, destinations, cooldown, quiet hours | Delivery failures, suppressed history, low-level event keys | alert-event type, severity threshold, tenant scope | Workspace configuration only | Create rule, Edit rule, Enable or disable rule | Delete rule |
| Alert deliveries viewer gains finding-event labels and delivery visibility | Workspace operator reviewing alert behavior | Verify whether external finding-event copies were delivered as configured | Read-only history surface | Did the configured finding notification copy actually go out? | Event label, tenant, severity, timestamp, delivery status | Safe failure reasons and delivery metadata | delivery status, event type, severity | none | View delivery | none |
| Direct finding notifications and deep links | Tenant operator or tenant manager | Decide whether to open a specific finding now because work was assigned, reopened, is due soon, or is overdue | Notification entry point | Why am I being notified, and what do I need to look at? | Tenant, finding summary, severity, event label, recipient reason, deep link | Full evidence, audit trail, lifecycle history, and related context after opening the finding | assignment change, reopen truth, due-state aging | none on the notification itself | Open finding | none |

## Proportionality Review *(mandatory when structural complexity is introduced)*

- **New source of truth?**: no
- **New persisted entity/table/artifact?**: no
- **New abstraction?**: yes — one bounded recipient-resolution contract over existing finding owner and assignee truth plus existing alert destinations
- **New enum/state/reason family?**: yes — four finding notification event types and one bounded recipient-reason vocabulary
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: Findings already move through assignment, reopen, and due-state transitions, but the responsible operator still has to rediscover those changes by polling queues and tenant pages.
- **Existing structure is insufficient because**: Existing findings queues only show current backlog once an operator opens them. Existing Alerts rules handle shared external delivery, but they do not by themselves define who the directly responsible operator should be for assignment, reopen, and aging signals.
- **Narrowest correct implementation**: Reuse the current finding owner and assignee contract, add four event types, resolve one direct recipient per event when possible, and let existing Alerts rules optionally produce external copies.
- **Ownership cost**: Ongoing maintenance for one bounded recipient-resolution rule set, event labels, and regression coverage for entitlement-safe delivery and dedupe.
- **Alternative intentionally rejected**: A full notification-preference center or a generic workflow-notification engine was rejected because it imports durable product complexity before the smaller control-loop problem is proven.
- **Release truth**: Current-release truth. This spec turns existing findings workflow changes into actionable operator feedback now rather than preparing for a distant automation layer.

### Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.

Canonical replacement is preferred over preservation.

## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*

- **Test purpose / classification**: Feature
- **Validation lane(s)**: fast-feedback, confidence
- **Why this classification and these lanes are sufficient**: The feature changes visible workflow consequences for findings and workspace alert configuration, but it does not add a new browser-only interaction model or a heavy-governance computation lane. Focused feature coverage proves event production, direct recipient routing, external rule integration, deep-link safety, and no-leak authorization behavior.
- **New or expanded test families**: Add focused finding-notification event tests, direct-recipient routing tests, due-cycle dedupe tests, alert-rule event-type option tests, and deep-link authorization tests.
- **Fixture / helper cost impact**: Moderate. Tests need findings with explicit owner and assignee combinations, due dates across notification thresholds, workspace alert rules and destinations, and hidden versus visible tenant memberships.
- **Heavy-family visibility / justification**: none
- **Special surface test profile**: global-context-shell
- **Standard-native relief or required special coverage**: Ordinary feature coverage is sufficient, plus explicit proof that notification deep links honor current tenant entitlement and that hidden tenants do not leak through notification text, event routing, or delivery history.
- **Reviewer handoff**: Reviewers must confirm that each event type has a deterministic trigger, that direct recipient precedence matches the spec, that owner-only changes do not emit assignment notifications, and that external rule-based copies remain optional rather than becoming the only notification path.
- **Budget / baseline / trend impact**: none
- **Escalation needed**: none
- **Active feature PR close-out entry**: Guardrail
- **Planned validation commands**:
  - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/FindingsNotificationEventTest.php tests/Feature/Findings/FindingsNotificationRoutingTest.php`
  - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Alerts/FindingsAlertRuleIntegrationTest.php tests/Feature/Notifications/FindingNotificationLinkTest.php`

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Receive direct notification when work changes hands or reopens (Priority: P1)

As a responsible operator, I want assignment and automatic reopen events to notify me directly, so findings do not silently appear in my workload.

**Why this priority**: This is the smallest workflow-closing slice. If assignment and automatic reopen remain silent, ownership semantics and personal queues still rely on manual polling.

**Independent Test**: Can be fully tested by assigning findings to a user, triggering an automatic reopen, and verifying that the correct recipient receives one tenant-safe notification with a deep link.

**Acceptance Scenarios**:

1. **Given** an open finding is assigned to a new assignee, **When** the assignment is saved, **Then** the new assignee receives one direct notification explaining that the finding was assigned to them.
2. **Given** a previously resolved finding is automatically reopened by system detection and still has an assignee, **When** the reopen is recorded, **Then** the assignee receives one direct reopen notification with a deep link to the finding.
3. **Given** only the accountable owner changes while the assignee remains unchanged, **When** the owner update is saved, **Then** no assignment notification is emitted.

---

### User Story 2 - Get due-soon reminders and overdue escalation without spam (Priority: P1)

As an operator responsible for a finding, I want the system to remind me before a due date and escalate overdue items predictably, so aging work does not disappear until the next manual review.

**Why this priority**: Due dates without reminder and escalation behavior are not operational controls. This story turns due metadata into an actionable workflow signal.

**Independent Test**: Can be fully tested by placing findings into the due-soon window and overdue state across different owner and assignee combinations, then verifying the correct recipient, one-time due-cycle behavior, and no duplicate notifications when the same person holds both roles.

**Acceptance Scenarios**:

1. **Given** an open finding enters the due-soon reminder window and has a current assignee, **When** evaluation runs, **Then** the assignee receives one due-soon reminder for that due cycle.
2. **Given** an open finding becomes overdue and has an owner distinct from the assignee, **When** evaluation runs, **Then** the owner receives the overdue escalation and the system does not send a second duplicate direct notification if owner and assignee are the same person.
3. **Given** a finding has already emitted a due-soon or overdue notification for the current due cycle, **When** later evaluations run without a due-date reset or reopen, **Then** no duplicate direct notification is emitted for that same cycle.

---

### User Story 3 - Configure external copies through existing Alerts management (Priority: P2)

As a workspace operator, I want the existing Alerts rules to support finding assignment, reopen, due-soon, and overdue event types, so shared team destinations can receive the same workflow signals without a second notification product.

**Why this priority**: The direct user notification closes the personal loop, but enterprise teams still need optional shared or external copies through the current alerting foundation.

**Independent Test**: Can be fully tested by adding the new event types to an alert rule, triggering one matching event, and verifying that an external delivery is created while the direct personal notification behavior remains available.

**Acceptance Scenarios**:

1. **Given** a workspace operator edits an alert rule, **When** they open the event-type selector, **Then** the four new findings notification event types are available.
2. **Given** a matching alert rule exists for an overdue findings event, **When** an open finding becomes overdue, **Then** the existing alert delivery pipeline creates one external copy per matching enabled destination.
3. **Given** no matching alert rule exists for an assignment event, **When** a finding is assigned to an entitled operator, **Then** the direct operator notification still occurs while no external delivery is created.

### Edge Cases

- The same entitled user may be both owner and assignee; the system must send one direct notification, not two copies with different labels.
- A finding may lose its assignee or owner entitlement after the workflow event was created but before delivery; direct delivery must re-check current entitlement and suppress the personal notification instead of leaking scope.
- A finding may become terminal after entering the due-soon window but before evaluation sends reminders; due-soon and overdue notifications must suppress for terminal findings.
- Rapid reassignment or repeated automatic reopen within the same notification fingerprint window must not fan out duplicate direct notifications.
- Existing tenant-level `sla_due` summary alerts remain valid and separate; this feature must not redefine or remove that aggregate overdue signal.

## Requirements *(mandatory)*

**Constitution alignment (required):** This feature adds no Microsoft Graph calls and no new `OperationRun` type. It reuses the existing alert-evaluation and alert-delivery operations plus existing in-app notification primitives. Scheduled evaluation remains system-run, so no new initiator-only terminal DB notification rule is introduced. Tenant isolation, delivery history, and test coverage remain mandatory because the feature emits new finding event types into existing background alert flows.

**Constitution alignment (TEST-GOV-001):** The proof burden is focused feature coverage for finding event production, recipient resolution, direct notification deep-link safety, alert-rule UI options, external delivery integration, and hidden-tenant suppression. No browser or heavy-governance lane is required.

**Constitution alignment (RBAC-UX):** The feature spans workspace-context alert configuration and tenant-scoped finding follow-up. Non-members, wrong-workspace users, and hidden-tenant requests remain `404`. Workspace members without `ALERTS_VIEW` or `ALERTS_MANAGE` remain `403` on protected alert pages. Notification payloads and deep links must not reveal finding or tenant details to operators who are no longer entitled to inspect the finding at open time.

**Constitution alignment (UI-FIL-001):** Existing Filament `AlertRuleResource` and alert delivery viewer remain the only configuration and delivery-history surfaces. Existing notification primitives and shared link helpers must be reused for direct finding notifications. No findings-specific notification center, badge system, or page-local alert markup may be introduced.

**Constitution alignment (UI-NAMING-001):** The target object is always the `finding`. Primary operator verbs are `assigned`, `reopened`, `due soon`, `overdue`, and `Open finding`. The same finding vocabulary must hold across alert-rule labels, notification titles, delivery history, and deep-link copy. Implementation-first terms such as fingerprint, recipient resolver, or evaluation window remain secondary.

**Constitution alignment (DECIDE-001):** Direct notifications are entry points, not replacement work surfaces. They must make the first decision obvious in one glance and then defer to the existing finding detail as the durable decision context.

**Constitution alignment (UI-CONST-001 / UI-SURF-001 / ACTSURF-001 / HDR-001):** No new list or detail page is introduced. Existing alert configuration surfaces stay config-first. Direct notifications expose one inspect model only: the finding. They must not compete with page-local mutation affordances or invent a second queue model.

**Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001):** This feature derives notification truth directly from existing finding lifecycle, ownership, due-date, and tenant-entitlement data. It must not add a second persisted workflow state, a local notification-only status, or a duplicate owner or assignee meaning.

### Functional Requirements

- **FR-001**: The system MUST support four new finding notification event types for the existing alert dispatch pipeline: `findings.assigned`, `findings.reopened`, `findings.due_soon`, and `findings.overdue`.
- **FR-002**: `findings.assigned` MUST be produced when an open finding is assigned to a new assignee. Owner-only changes, assignee clears, and no-op saves MUST NOT emit this event.
- **FR-003**: `findings.reopened` MUST be produced only for system-driven reopen of an existing finding caused by recurring detection. Manual reopen remains out of scope for v1 notifications.
- **FR-004**: `findings.due_soon` MUST be produced once per due cycle when an open finding first enters the due-soon reminder window. The default v1 reminder window is 24 hours before `due_at`.
- **FR-005**: `findings.overdue` MUST be produced once per due cycle when an open finding first becomes overdue.
- **FR-006**: A finding due cycle resets only when the finding’s `due_at` is recalculated by the existing lifecycle contract, such as after a system reopen that resets due dates. `reopened_at` may explain why the cycle changed, but only a new `due_at` value may produce a new due-soon or overdue event for the same finding.
- **FR-007**: The system MUST resolve one direct personal recipient for each event when possible using this precedence:
  - `findings.assigned` → new assignee
  - `findings.reopened` → current assignee, else current owner
  - `findings.due_soon` → current assignee, else current owner
  - `findings.overdue` → current owner, else current assignee
- **FR-008**: Direct personal delivery MUST only occur when the resolved recipient is still currently entitled to inspect the target tenant and finding at send time. If no currently entitled direct recipient exists, the system MUST suppress direct personal delivery rather than broaden disclosure.
- **FR-009**: When the resolved owner and assignee are the same currently entitled user, the system MUST send only one direct personal notification for that event.
- **FR-010**: Each finding event MUST carry a deterministic fingerprint suitable for dedupe and cooldown. Assignment fingerprints must distinguish the target assignee change, automatic reopen fingerprints must distinguish the reopen occurrence, and due-soon or overdue fingerprints must roll when the due cycle resets.
- **FR-011**: Direct personal notifications MUST be available without requiring a matching workspace alert rule. Workspace alert rules remain optional copies for external or shared-team delivery.
- **FR-012**: Existing Alerts rules MUST support the four new finding notification event types in the event-type selector. No new alert pages, no new destination type family, and no findings-specific preference center may be introduced in v1.
- **FR-013**: Existing Alerts v1 behavior for minimum severity, tenant scoping, cooldown, dedupe, quiet hours, and destination fan-out MUST apply unchanged to external rule-based copies of the new finding events.
- **FR-014**: Direct personal notification payloads MUST include the finding summary, tenant context, severity, event label, why the current operator received it, and one deep link to open the finding.
- **FR-015**: Notification titles, body copy, delivery history labels, and alert-rule event labels MUST stay domain-first and must not expose raw internal event keys as the primary operator language.
- **FR-016**: Direct and external notifications MUST deep-link to the existing tenant finding detail route for the target finding. Opening that link MUST continue to honor current `404` versus `403` entitlement semantics at the time of use.
- **FR-017**: Existing tenant-level `sla_due` summary alert behavior from Spec 111 MUST remain in place. The new due-soon and overdue events are finding-level actionable signals and MUST NOT replace or silently redefine the aggregate `sla_due` event.
- **FR-018**: Alert delivery history MUST show external finding-event deliveries in the existing workspace alert deliveries viewer with the new event labels. The feature MUST NOT introduce a second workspace-wide history page for direct in-app personal notifications.
- **FR-019**: The feature MUST NOT introduce a new findings lifecycle state, a second assignment model, a notification-only queue, or a repeated daily overdue escalation loop by default.

## 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 |
|---|---|---|---|---|---|---|---|---|---|---|
| Alert Rules Resource | Workspace Monitoring → Alerts → Alert rules | Existing create action only | Clickable row to existing edit surface | Existing Edit and `More` actions only | none | Existing create CTA only | n/a | Save / Cancel | Yes for existing rule mutations | Surface is extended only with four event types and routing helper copy. Action Surface Contract remains satisfied by the existing resource pattern. |
| Alert Deliveries viewer | Workspace Monitoring → Alerts → Alert deliveries | none | Existing inspect behavior only | Existing read-only inspect action only | none | none | n/a | n/a | No new mutation audit because the surface stays read-only | Existing viewer only gains finding-event labels and safe recipient-facing delivery summaries. |

### Key Entities *(include if feature involves data)*

- **Finding notification event**: A derived workflow event produced from an existing finding transition or aging threshold and routed through the existing alerting pipeline.
- **Direct finding notification**: A personal in-app notification sent to the single currently responsible operator resolved from existing finding owner and assignee truth.
- **Alert rule (extended)**: The existing workspace alert rule model, extended with the four new finding notification event types.
- **Recipient-resolution contract**: The bounded precedence rule that selects the directly responsible operator for assignment, automatic reopen, due-soon, and overdue events without creating a second ownership model.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: In acceptance review, an operator can understand why they received an assignment, reopen, due-soon, or overdue notification and open the correct finding in one interaction.
- **SC-002**: 100% of covered automated tests route each of the four event types to the correct direct recipient or correctly suppress direct delivery when no currently entitled recipient exists.
- **SC-003**: 100% of covered due-cycle tests emit at most one direct due-soon reminder and one direct overdue escalation per finding due cycle unless the due cycle resets.
- **SC-004**: 100% of covered alert-rule tests show that the four new event types are available in the existing Alerts UI and create external deliveries only when matching rules exist.

## Assumptions

- The existing notification-routing foundation can deliver direct in-app notifications to currently entitled operators without introducing a second notification product.
- The due-soon horizon is fixed at 24 hours before `due_at` in v1.
- Existing finding detail remains the canonical follow-up surface reached from the notification deep link.
- Membership and assignment hygiene after a person loses tenant access remains a separate hardening slice and is not solved fully here.

## Non-Goals

- Introduce multi-stage escalation chains or automatic reassign logic.
- Build a findings-specific notification-preference center or destination management UX.
- Replace the existing aggregate `sla_due` alert semantics with item-level reminders.
- Add comments, chat, or external ticket handoff.
- Create a second findings queue or a notification-only workflow state.

## Dependencies

- Spec 099, Alerts v1, remains the source of truth for workspace alert rules, destinations, cooldown, quiet hours, and delivery history.
- Spec 100, Alert target test actions, remains the source of truth for alert destination testability and delivery-viewer conventions.
- Spec 111, Findings Workflow + SLA, remains the source of truth for finding lifecycle, due dates, reopen behavior, and aggregate `sla_due` alerts.
- Spec 219, Finding Ownership Semantics Clarification, remains the source of truth for owner-versus-assignee meaning.
- Spec 221, Findings Operator Inbox V1, and Spec 222, Findings Intake & Team Queue V1, remain the established work surfaces that benefit from these notifications even though this spec does not create new queue pages.