```yaml
id: UJ-004
title: Snoozed inbox item returns after expiry
actors: [dashboard-operator]
surface: inbox
goal: Operator hides one item until its configured expiry, then sees it again.
trigger: Activate `Snooze` at `/inbox`.
fixtures: [ALL_ITEMS, __OVERDECK_SNOOZE_MS]
success_state:
  visible: Item is absent until expiry then visible.
  durable: localStorage `overdeck-inbox-snoozes` maps item ID to expiry.
  persistence: Reload before expiry keeps item absent.
source_specs: [apps/web/src/components/inbox/InboxTriageRow.tsx, apps/web/src/components/inbox/InboxContent.tsx, apps/web/src/components/inbox/inbox-snooze.ts, apps/web/tests/inbox.spec.ts]
readiness: ready
canonical: true
blockers: []
```

## Path

| Hop | Evidence |
|---|---|
| UI trigger | `apps/web/src/components/inbox/InboxTriageRow.tsx:168` |
| Request construction | N/A — browser-local preference has no HTTP request. |
| Endpoint auth and parse | N/A — browser-local preference has no endpoint. |
| Authoritative write | `apps/web/src/components/inbox/inbox-snooze.ts:40` |
| Response | N/A — browser-local write has no HTTP response. |
| Terminal render | `apps/web/src/components/inbox/InboxContent.tsx:20` |

## Happy path

### H1
- Setup: `ghci:alexcodeplace/multideal:4821:1` is visible and snooze duration is `500`.
- Action: Activate `Snooze` at `/inbox`.
- Request: N/A — browser-local preference has no HTTP request.
- Response: N/A — transport produced no HTTP response.
- Visible: `ghci:alexcodeplace/multideal:4821:1` is absent.
- Durable: localStorage `overdeck-inbox-snoozes` maps `ghci:alexcodeplace/multideal:4821:1` to expiry.
- Fresh read: Full reload before expiry omits `ghci:alexcodeplace/multideal:4821:1`.
- Forbidden: Collector item is not deleted.
- Evidence:
  - Setup: `apps/web/tests/inbox.spec.ts:72`
  - Action: `apps/web/tests/inbox.spec.ts:79`
  - Request: `apps/web/src/components/inbox/InboxTriageRow.tsx:168`
  - Response: `apps/web/src/components/inbox/inbox-snooze.ts:40`
  - Visible: `apps/web/tests/inbox.spec.ts:80`
  - Durable: `apps/web/src/components/inbox/inbox-snooze.ts:41`
  - Fresh read: `apps/web/src/components/inbox/inbox-snooze.ts:23`
  - Forbidden: `apps/web/src/components/inbox/InboxContent.tsx:64`

## Alternate and failure paths

### A1
- Setup: Snoozed item expiry is reached.
- Action: Advance browser clock beyond expiry.
- Request: N/A — browser-local preference has no HTTP request.
- Response: N/A — transport produced no HTTP response.
- Visible: `ghci:alexcodeplace/multideal:4821:1` is visible.
- Durable: Expired map entry is removed.
- Fresh read: Full reload omits expired snooze entry.
- Forbidden: Item remains hidden after expiry.
- Evidence:
  - Setup: `apps/web/tests/inbox.spec.ts:82`
  - Action: `apps/web/tests/inbox.spec.ts:85`
  - Request: `apps/web/src/components/inbox/InboxContent.tsx:45`
  - Response: `apps/web/src/components/inbox/inbox-snooze.ts:55`
  - Visible: `apps/web/tests/inbox.spec.ts:86`
  - Durable: `apps/web/src/components/inbox/InboxContent.tsx:49`
  - Fresh read: `apps/web/src/components/inbox/inbox-snooze.ts:55`
  - Forbidden: `apps/web/src/components/inbox/inbox-snooze.ts:58`

## Permissions and boundaries

N/A — browser-local preference has no user identity boundary.

## Source specs

- `apps/web/src/components/inbox/InboxTriageRow.tsx`
- `apps/web/src/components/inbox/InboxContent.tsx`
- `apps/web/src/components/inbox/inbox-snooze.ts`
- `apps/web/tests/inbox.spec.ts`
