Files
enricobuehlerandClaude Opus 5 7f606e3d14 feat(ui): the console explains the two-sided setup and writes rules for you
M2: the plugin gets a console page — Overview (what is held, live), Devices (what the couch
is sharing), Rules (the passthrough allowlist), Diagnostics (what to fix).

The Devices tab is where a rule gets created, on purpose: picking a row writes a NAME-based
rule, which survives the couch rebooting or the device changing port. Typing an address is
still possible in Rules, but it is the brittle path, so it is not what the happy path offers.

Diagnostics and the `doctor` CLI command are now ONE implementation. A support thread and the
panel must never disagree about what is wrong, and every failing check owes a remedy — a
check that says something is broken without saying what to do is a bug, and a test enforces it.

Status is pushed, not polled: the binder publishes to a PubSub after the journal is durable
(so a subscriber never sees a change a crash could un-do) and the SSE feed maps that into
frames. Client health is recorded as a side effect of real verbs, so an open status panel
generates no VirtualHere traffic of its own.

The new API smoke test — a real web handler over stubbed services, no host and no VirtualHere
— immediately earned its keep: POST /api/bind answered 500 instead of 404 because a
`Schema.Union` of annotated errors silently loses the per-member status. Fixed by removing the
union, which also corrected a modelling error: an ambiguous match or a refused USE is a normal
outcome the binder reports as `ok: false` with a sentence, not a transport failure. Only "that
rule does not exist" is a real client mistake, so that is the only typed error left.

A config that fails to parse now falls back to defaults for the API only, so the one screen
that could explain the breakage is not the screen that goes blank. The binder still refuses to
start on a bad config — that part must stay loud.

Attribution ("sold separately", not affiliated, no iOS/tvOS server) renders on every page
rather than in a footer nobody scrolls to.

35 tests green; contract, plugin and UI typecheck; biome clean; SPA builds into the bundle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 21:00:59 +02:00
..