# GetNotification

## Overview

GetNotification retrieves a single Notification row by its id. The row carries the polymorphic `sourceType + sourceId` reference, the channel, the rendered subject and body, the `payloadVars` snapshot used at render time, the `deliveryStatus` (linear axis: QUEUED, SENT, DELIVERED, FAILED, BOUNCED) and the `engagementStatuses` set (any subset of {SEEN, READ, ARCHIVED}). The query is used by inbox detail UIs and self-service delivery inspection.

## Business Rules

- Accepts a single lookup parameter: `{ id }`
- Returns null when no Notification row matches the supplied id
- Results are scoped to the caller: the row is returned only when the caller is its recipient (`recipientUserId == caller.actorId`); otherwise the query returns **null** — exactly like a missing row — so callers cannot enumerate foreign notification ids (no existence oracle)
- Returns the row in any `deliveryStatus` (including QUEUED, FAILED, BOUNCED) — the inbox-style filtering on `deliveryStatus IN {SENT, DELIVERED}` is applied by `ListInboxNotifications`, not here
- Returned row carries id, recipientUserId, channelId, sourceType, sourceId, subject, body, payloadVars, deliveryStatus, engagementStatuses, createdAt, plus engagement timestamps (`seenAt`, `readAt`, `archivedAt`) when set

## Process Flow

```mermaid
flowchart TD
    A[Receive id] --> B[Load Notification by id]
    B --> C{Row found?}
    C -->|No| D[Return null]
    C -->|Yes| E{Caller is the recipient?}
    E -->|No| D
    E -->|Yes| G[Return Notification row]
```

## External Dependencies

- None

## Error Scenarios

- **NO_MATCH**: No matching row exists for the supplied input; null or empty result is returned

> Returning `NO_MATCH` is a normal empty/null result rather than a thrown error — the query returns the null/empty value and does not raise `NoMatchError`.

(An unauthorized caller receives the same null as a missing row — no FORBIDDEN error is raised, to avoid an existence oracle.)

## Test Cases

- returns the Notification when found by id and caller is the recipient
- returns the row regardless of `deliveryStatus` (QUEUED, SENT, DELIVERED, FAILED, BOUNCED)
- returns the row with the current `engagementStatuses` set
- returns null when id does not exist
- returns null when the caller is not the recipient (no existence oracle)
