# Session notification broker Host implementation checkpoint, 2026-09-24. No notification UI, keyboard focus, touch interaction, or board proof is claimed here. This service supplies actual runtime data to the coherent shell's shade rather than a mock list. `k230-notifications serve` owns a private Unix socket, normally `/run/shell-notifications/events.sock`. The daemon accepts one bounded newline JSON request per connection. `k230-notifications history`, `emit`, `dismiss ID`, `dismiss-all`, and `action ID` are CLI clients of the same protocol. A native shell client can use the socket directly without launching a process per poll. The `history` response has `schema: 1`, `count`, `events`, and nullable `preview`. Each history event has `id`, `source`, `icon`, `summary`, `body`, `priority`, `timestamp` (Unix seconds), `error`, `dismissible`, and `action_available`. Preview has `id`, `source`, `summary`, `icon`, `priority`, `ongoing`, and `focus: false`. The client must keep unsolicited previews outside the keyboard and focused input; that client behavior remains to be tested. Requests use `operation: history|emit|dismiss|dismiss-all|action`. Dismiss/action also carry integer `id`. Emit accepts `summary`, `body`, `tag`, `priority`, `private`, `ongoing`, and optional Sway container `target`. Sender-supplied source labels are ignored. Linux peer credentials establish root/system or a Nix-pinned executable identity from the `--trusted` JSON map; other session senders are unknown, ordinary, private, with no app icon or action authority. Unsolicited private previews reveal neither source identity nor summary/body. Opening history reveals the retained content. Previews expire after five seconds without deleting history; ongoing critical events retain a preview and cannot be dismissed. Only their trusted source's matching tag can update them to resolved. Ordinary history expires after an hour. At most 64 events remain; a full history of ongoing critical events rejects further input. Source/tag deduplication updates one record. Missing action targets remain in history with an error; action always revalidates the actual Sway tree before focus and never executes an event-supplied command. The broker accepts at most eight simultaneous clients, 4096 request bytes, and two seconds per connection. An unfinished client does not stall other clients. The socket and runtime directory are private to the session user. An exclusive broker lock supports stale-socket recovery after a killed daemon. History is session memory, not a claim of reboot persistence or freedesktop notification API coverage. `python3 tests/test_notification_center.py` passed nine host tests: priority, privacy, retention/deduplication/expiry, unknown-source downgrade, preview timeout, disappeared target/retry, retained/resolved critical events, bounded critical flood, and a real Unix-socket daemon with a stalled client and killed daemon restart. UI-specific typing-focus/scroll/swipe cases deliberately remain unimplemented and are rejected if requested; they require the actual client. `nix build .#handheld-notifications --no-link --print-out-paths --max-jobs 1 --cores 8` passed, producing `/nix/store/n9p1qlrflc463v3siyrhj49n5hdbh1fd-k230-notifications`. The package uses the board package graph and excludes XWayland; an initial overbroad dependency selection was stopped and corrected before this build. Remaining: service integration, pinned source registration, shade rendering and interaction, real compositor focus test, and board evidence.