D133 — Viewer framing for named pages (--view-embed)¶
Decision¶
A viewer can be framed by named pages: route --view-embed "<origins>" replaces X-Frame-Options: DENY with Content-Security-Policy: frame-ancestors <origins> on the viewer's pages; the default (no option) is unchanged, the token still guards every request, and the value is checked (letters, digits and .:/*-_[] and spaces only) because it goes into a header. The stack-test page (devsite/stack.py, :8771) embeds each running board's viewer this way; bench/viewport.py gives every board its own port (8800-8899) and one shared token (bench/results/.view-token), bench/run.py --view and bench/escalate.py use it
Alternatives¶
A reverse proxy in the devsite (needs a WebSocket relay and an Origin rewrite); dropping the header for everyone; binding the viewers to loopback and tunnelling (the token would stay private, but the page could not reach them)
Reason¶
Routing with the viewer is byte-identical to without (one board, 4-variant portfolio, checked); only the first portfolio variant streams. Anyone who can open the stack page can read the token and open the viewers: the same trust as the page itself. Also added to the stack page: a burndown chart (boards not yet clean over the campaign, from the modification times of the result files; bench/ledger.py burndown())