105 lines
5.2 KiB
Markdown
105 lines
5.2 KiB
Markdown
# WebUI preview behind sign-in (2026-10-11)
|
|
|
|
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`.
|
|
One row. Amended the same evening for Jason's Q91 answer "A" (lead
|
|
decision 93): a read-only preview at its own hostname, behind Pocket ID
|
|
forward auth limited to Jason's group, the old build left up. Target:
|
|
Jason signs in on 2026-10-12, by 2026-10-13T05:00Z at the latest. The
|
|
service script is cut from this row for that date; it is a follow-up.
|
|
|
|
## WebUI preview: a signed-in, read-only Console behind the edge proxy
|
|
|
|
### Problem
|
|
|
|
Jason asked for an ETA for the refactor WebUI at mosaic.woltje.com. Today
|
|
the Console can't be reached from anywhere but the host it runs on, by
|
|
design:
|
|
|
|
- `startServer` refuses to bind to a non-loopback address
|
|
(`packages/webui/src/serve.mjs:82`) and answers 403 to any request whose
|
|
Host isn't loopback on its own port (`serve.mjs:92`). A reverse proxy
|
|
that forwards the public Host is refused.
|
|
- The Origin check (`serve.mjs:96`) compares against `http://<Host>`, so a
|
|
browser on `https://<public name>` is refused as cross-origin.
|
|
- There is no sign-in. Anything that connects to the port reads what a
|
|
reader capability reads (`packages/webui/README.md`, the paragraph on
|
|
the bus views), and the README forbids a public proxy.
|
|
- Two routes write: POST `/api/seen` and `/api/reply` go to the board.
|
|
- Nothing runs the Console as a service. It is a foreground `serve`.
|
|
|
|
Mos approved these cuts for the preview (2026-10-11): sign-in at the edge
|
|
through Pocket ID forward auth, not login code in the Console; a preview
|
|
hostname, so the old build at mosaic.woltje.com stays; read-only; not
|
|
held for S7 (row 42) or Gate E (row 5). ops-01 owns the Pocket ID client
|
|
(limited to Jason's group), the DNS name, TLS, the proxy and the route
|
|
from the edge to this host. The route opens once rev-sol-01 passes
|
|
ops-01's proposal (Q91 A).
|
|
|
|
### Owner and reviewer
|
|
|
|
Owner: Dewey, who owns the WebUI, starting 2026-10-11 evening. Reviewers:
|
|
Darkwing and Filbert, ahead of their own rows.
|
|
|
|
### Files owned
|
|
|
|
- `packages/webui/src/serve.mjs`, `packages/webui/src/cli.mjs`,
|
|
`packages/webui/README.md` and `packages/webui/tests/`
|
|
- `agents/dewey/work/queue-<row>/`
|
|
|
|
### What ships
|
|
|
|
A preview mode, off by default. Without its flags the Console behaves
|
|
exactly as today, and the existing tests show it.
|
|
|
|
- `serve --public-host NAME --auth-header HEADER --allow-user ID`, all
|
|
three or none. NAME is a hostname, no port or scheme. The bind stays
|
|
loopback; nothing here listens beyond it.
|
|
- In preview mode a request's Host must be NAME, or loopback on the
|
|
Console's port as today. An Origin, when sent, must be `https://NAME`
|
|
for a NAME request, and the loopback form for a loopback request.
|
|
- A NAME request must carry HEADER with a value equal to ID. Missing or
|
|
different answers 401 with no bus read made. Loopback requests are
|
|
unchanged, so the operator's own browser on the host still works.
|
|
- In preview mode every POST answers 403 `read-only`, whatever the Host.
|
|
`/api/seen` and `/api/reply` don't reach the board.
|
|
- Tests for each refusal: wrong Host, wrong Origin, missing header, wrong
|
|
user, a POST to each write route, and a partial flag set refused at
|
|
start. A test that the loopback path is unchanged in preview mode.
|
|
- The minimum for the first sign-in is the inbox, tasks, agents and
|
|
trails (`/api/bus/*`) read-only. The other GET routes stay as they are.
|
|
The board panel reads the board already running on 7331; if it is down
|
|
the panel shows its existing error and the bus views still work.
|
|
- The README replaces "Do not expose either unauthenticated server
|
|
through a public proxy" with what the preview mode requires of the
|
|
proxy: it strips HEADER from every client request and sets it only
|
|
after Pocket ID signs the user in, it preserves Host, it terminates TLS,
|
|
and it is the only thing that reaches the port from off the host. It
|
|
says plainly that any local process can still connect and send HEADER,
|
|
the same exposure the README already describes for the port.
|
|
- The packet runs the Console in preview mode with `curl` against
|
|
loopback, showing each refusal and one allowed read, with no network
|
|
beyond the host.
|
|
|
|
### Out of scope
|
|
|
|
- OIDC or login code in the Console; Pocket ID config; DNS, TLS, the
|
|
proxy and the route from the edge (ops-01).
|
|
- Resolving decisions or replying from the browser. REQ-DEC-3 keeps
|
|
resolution in the CLI; changing that is a ruling and its own row.
|
|
- Live-seat conversations (CHAT-07) and any board change.
|
|
- A container image, CI deploy, or changes to the bus unit.
|
|
- A service script and unit template (`scripts/webui-service.sh` on the
|
|
`bus-service.sh` pattern). That is a follow-up row.
|
|
- Starting it on dragon-lin. After the row lands, Sage starts the preview
|
|
as a transient user unit (`systemd-run --user`, loopback port 7332;
|
|
7330 holds the operator's own Console). The edge reaches it once
|
|
rev-sol-01 passes ops-01's route.
|
|
- The group check. Pocket ID and the proxy limit sign-in to Jason's
|
|
group; the Console checks the header against the one user id.
|
|
|
|
### Gate
|
|
|
|
Darkwing and Filbert approve on the row's issue naming the candidate
|
|
manifest. The webui, control-board and cli node suites and every
|
|
`scripts/test-*.sh` green on Sage's gate rerun.
|