Expand description
OS notification Presenter — docs/specs/SPEC_OS_NOTIFICATIONS_SYSTEM_2026_09_24.md §3.2, §6.
The srv Router decides whether to notify and publishes notification /
notification:retract on its event bus. This module is the launcher’s
subscriber: it keeps a WebSocket to srv (the launcher’s first), renders
each notification with the platform backend, and reports the user’s
click/dismiss back as notify.ack.
Why the launcher (spec §3.2): it outlives host restarts, stays up with no window in background mode, owns the tray, and — on macOS — is the bundle’s main executable. Click callbacks need a live process; this is the longest-lived one.
§Lifecycle
start once srv is up; update_endpoint whenever srv is respawned (new
port + auth key); shutdown before the launcher exits, which clears every
toast this app put in the notification center — a click on a toast from a
dead instance could do nothing useful (Phase 1 has no cold-start
activation, spec §6.1).
Modules§
- linux 🔒
- Linux notification backend —
SPEC_OS_NOTIFICATIONS_SYSTEM_2026_09_24.md§6.3.
Structs§
- AckResponse
- srv’s
notify.ackanswer (NotifyAckResult). - Endpoint 🔒
- Handle 🔒
- Notification
- Mirrors srv’s
OsNotification(crates/srv/src/backend/notify/policy.rs). Unknown fields are ignored so srv can grow the payload first. - Null
Presenter 🔒 - No platform backend (macOS today — needs a signed bundle and a Mac to verify, spec §6.2): log and drop.
Enums§
- Click
Plan - What a click makes the launcher do (rich-content spec §3.3 C, D, F).
- Frame
- What an incoming srv frame means to the presenter.
- Session
End 🔒 - User
Action - What the user did — on a toast (reported by a backend) or in the tray’s
notification menu (
tray_request).
Statics§
Traits§
- Presenter
- A platform notification surface.
Functions§
- actions 🔒
- carry_
out_ 🔒click - Raise first, in this process: the toast click made the launcher the foreground-eligible process, and that right is what a raise needs — waiting for the pane selection to go srv → renderer → host first can lose it (rich-content spec §3.3 C, F4). Every branch logs.
- click_
plan - Pure: srv decided the target; this only maps its answer to an action.
- flash_
hwnd 🔒 - make_
presenter 🔒 - parse_
frame - Parse one srv WS text frame. Events arrive as
{"eventtype":"rpc","data":{"command":"eventrecv","data":<MuxEvent>}}; RPC responses as{"eventtype":"rpc","data":{"resid":..,"data":..}}. - raise_
hwnd 🔒 - request_
start_ at_ login - Write
app:startatloginthrough srv, like any settings change, so the Settings page and the OS login entry follow it (start_at_login). Queues until the session is up. - rpc 🔒
- run 🔒
- session 🔒
- shutdown
- Launcher is exiting: remove our toasts from the notification center.
- start
- Start the presenter. Idempotent: a second call only updates the endpoint.
- tray_
request - The tray’s notification menu (spec §4.2): open an attention item exactly as its toast click would, or pause/resume. Non-blocking; callable from the tray thread.
- window_
for - The host window showing backend window
window_id:(label, hwnd, iconic). - ws_url
host:port(srv’s ESTART form) or a full URL → the/wsURL.
Type Aliases§
- Action
Channel 🔒 - The user-action channel exists from first use, not from
start: the tray (and its Pause/Resume/Open menu) comes up before srv does, and a pick made in that window must queue until the presenter connects rather than vanish (ReAgent P2 on #3654).starttakes the receiver. - Launcher
State - The launcher’s reducer state — where a clicked toast’s window is looked up (backend window id → label → HWND).