# ListNotificationSubscriptions

## Overview

ListNotificationSubscriptions lists the calling user's own NotificationSubscription rows — every source they are subscribed to — for use in a "what am I following?" UI. The result can optionally be narrowed to a single record by supplying `{ sourceType, sourceId }`. Watcher resolution for dispatch happens **inside the dispatcher** (`dispatchNotification` reads NotificationSubscription directly by the event's `(sourceType, sourceId)`), so this query is purely a self-service read surface and never the audience source for delivery.

Results are always scoped to the caller: a user cannot inspect another user's subscriptions.

## Business Rules

- Accepts optional `{ sourceType, sourceId }` source narrowing and an optional `{ userId }` filter
- Self-scope: results are always restricted to the caller's own subscription rows (`userId == caller.actorId`)
- An explicit `userId` filter must equal the caller's `actorId`; otherwise `FORBIDDEN`
- The optional `sourceType` / `sourceId` filters narrow the caller's rows further
- Returns an empty list when no subscriptions match
- No implicit ordering is guaranteed beyond the requested `orderBy`
- Each row carries `userId`, `sourceType`, `sourceId`, and `subscribedAt`

## Process Flow

```mermaid
flowchart TD
    A[Receive input] --> B{userId supplied and != caller?}
    B -->|Yes| C[Error: FORBIDDEN]
    B -->|No| D[Query NotificationSubscription where userId = caller, applying optional source filters]
    D --> E[Return list]
```

## External Dependencies

- None

## Error Scenarios

- **FORBIDDEN**: Caller is not authorized to perform this operation in the target scope
- **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`.

## Test Cases

- returns the caller's subscriptions narrowed by `(sourceType, sourceId)`
- returns an empty list when the caller has no subscriptions for the source
- filters by the requested `sourceType`
- returns the caller's subscriptions when called with `userId == caller`
- returns an empty list when the caller has no subscriptions
- rejects calls with `userId != caller` with FORBIDDEN
- returns rows with `subscribedAt` populated
