Decision 94 records Q94 yes and Mos's sage-0054/0055 directions: no broker row (the Console already reads as the human), Jason starts the Console, nine rows deferred, S7's line amended, Gate E partial pass on the dogfood day, no rollback hostname. New brief for the Console service row and the send-to-a-role row. Row 74's start line and S7's request line amended. Co-Authored-By: Claude Opus 5.5 <[email protected]>
118 lines
6.0 KiB
Markdown
118 lines
6.0 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 forward
|
|
auth limited to Jason's group, the old build left up. The identity
|
|
provider is Authentik at auth.diversecanvas.com, not Pocket ID as first
|
|
relayed; the Console names no provider. 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 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 Authentik application
|
|
(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. The check is generic: one header name and one user id,
|
|
both from the flags, nothing provider-specific in code or tests.
|
|
Node lowercases incoming header names, so HEADER matches without
|
|
regard to case (`X-authentik-uid` on the flag finds
|
|
`x-authentik-uid`), and a test shows it. The value compare is exact.
|
|
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 the identity provider signs the user in, it forwards only
|
|
requests whose Host is NAME and preserves that Host (a forwarded
|
|
loopback Host would skip the header check), 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; Authentik 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. The Console reads the bus through the human
|
|
transport, so whoever starts it holds the human's capability. An agent
|
|
starting it, even detached through systemd, works around the human
|
|
proof (lead decisions 62 and 94). After the row lands, Jason starts it
|
|
from his own shell as a transient user unit (`systemd-run --user`,
|
|
loopback port 7332; 7330 holds the operator's own Console), with the
|
|
command Sage gives him. The edge reaches it once rev-sol-01 passes
|
|
ops-01's route.
|
|
- The group check. Authentik 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.
|