lichen.page.review from the reviewed point 0b92cb61 to stack eb5a1653, as one PR per subsystem (review set)

full 17: Dashboard: the React pages served, Tera removed, custom dashboards #80

targeting full/16-api-cli
Open opened by and assigned to notplants-bot.bsky.social
targeting full/16-api-cli

The front server's side of the React dashboard. The dashboard's pages now answer the React app's index.html with their data as JSON views, and the sign-in pages are React drawn on the server in a separate render child. A host operator can swap in their own dashboard package, chosen once at startup. The front server's Tera engine and its page rendering are gone.


AST-verified changes

  • The settings helpers left utils.rs for lichen-site: read_settings_section, edit_settings_in_tree and their siblings went to settings/edit.rs, and load_settings_for_site_with_overrides to settings.rs (PER-SITE-PROCESS P2c-2b commit 1c, 85a5e79e; the other half is in #37). Checked by the builder (run id not recorded): "10 moved, 3 visibility". The adversary's rerun got the same counts. utils.rs now re-exports them.
  • The site settings page's context builder (build_site_settings_context, now SettingsContext) left utils.rs for lichen-site's settings/page.rs, and the page templates were renamed into the site crate (P2c-2b commit 5, 6c06675b; the other half is in #37). Checked by the builder (run id not recorded): "move 5 ok: 10 moved, 4 carried, 1 renamed, 4 vis". The adversary's rerun got the same counts. Allowed: four pub(crate) → pub widenings, as mapped.
  • The path rewrites of SECURITY-FOLDER-AND-PRINCIPALS units 1 and 2 in this PR's files (crate::site_area → crate::admin_area, crate::access → crate::security::access, and the other security:: paths), which those checks cover (unit 1 notify-eebdd32e, unit 2 adversary notify-020eb199, both equal, errors 0), with the rustfmt rewraps after them (d6c25912, bdaa795b), proven by cargo fmt.
  • FULL-SITE-PROCESS 6a (deef05fc → 0b71076c, map machine-docs/reports/fsp-6a/move-map.json): sign_in_render_spec and SIGN_IN_RENDER_ADDRESS_SPACE left sign_in_render.rs for lichen-site's sandbox/spawns.rs (#39), with seven other spawn items; the module imports them. Run notify-82fbca10: "equal=True: items 5581/5581: moved 9, stayed 5572; visibility_changes 8, every one listed; comments compared 4995"; adversary rerun equal=True, 5581/5581, plants caught (notify-ec60785b).

Roughly 193 of this PR's 1,904 changed lines are code these moves carried verbatim, nearly all of them the lines that left utils.rs. Everything else (the JSON views, the render child, the dashboard source) is new code to read; 6a's two items were written after 09-23, so they appear in no line here.


DASHBOARD-REACT replaced the Tera dashboard one page at a time:

  • The pages /, /settings/ and /settings/{domain} answer the app's index.html (dashboard_app.rs, embedded). Each page's data comes from a JSON view in dashboard.rs (dashboard_json, account_json, site_settings_json), so the page and the API show one thing. The app's files are served from a fixed list: a request names a file of the list, or nothing is looked up.
  • The sign-in pages are drawn on the server (sign_in_render.rs, unit 4) in a render child: this executable started again as lichen render-child, under lichen sandbox where the sandbox is on. A sign-in page renders data a visitor sets, so its JavaScript runs where no secret is. One warm child serves renders one at a time and stops when idle. A render that outlives its limit, or an answer outside the protocol, has the child killed with everything it started.
  • Without JavaScript the dashboard is the same child's server-drawn sites list (U4b), with plain forms to create and delete a site. Deleting needs the domain typed again.
  • A host operator can replace the dashboard (dashboard_source.rs): [dashboard] source in lichen.toml is a path: folder, an HTTPS archive or a git source, each with a pin, read through the site frontend loader's confined tree and fetchers. Only startup reads the configuration or the package; requests see validated, immutable bytes. A bad selection serves the built-in app with a bounded notice. A site cannot select it.
  • Tera is gone from the front server: templates.rs (the dashboard engine) is deleted, and utils.rs loses render_template and the settings-page context.
  • The site's settings view shows the git remote and sync the site process's admin thread records, asked over /hub/remote (FULL-SITE-PROCESS 6d), and a remote that is failing (remote_failure, SITE-FRONT-BOUNDARY units 6 and 7); a share guest is shown none of it. The sites list's usage and the hub's status come from the running processes (/hub/status).

Files (crates/lichen-server/src/)

  • dashboard.rs (+445/−207) — the JSON views, the edit-host links, the no-JavaScript page and its forms, the event stream. Read this first.
  • sign_in_render.rs — new: the render child and its protocol; its sandbox spec is in lichen-site's sandbox/spawns.rs (#39).
  • dashboard_app.rs — new: the embedded app and its fixed file list.
  • dashboard_source.rs — new: the host-selected dashboard, resolved at startup.
  • utils.rs (+10/−356) — Tera rendering removed; the settings helpers re-exported from lichen-site.
  • templates.rs — deleted.

Lives elsewhere

  • The dashboard's JSON API (api.rs) and the CLI: #32. The routes and their groups (server.rs): #30.
  • The site frontend loader the dashboard source reuses (frontend/remote.rs, frontend/git.rs): #34. The settings page's values (settings/page.rs): #37.
  • The render child's loop, lichen_site::ssr::serve_render_child: #26.
  • Not in any PR (base commit): the React app (frontends/dashboard/, frontends/ui/), its built bundles (app.js, ssr/dashboard-ssr.js), the deleted Tera templates (crates/lichen-server/templates/*), static/lichen.toml.example and the tests.

Category: Dashboard: the React pages served, Tera removed, custom dashboards Size: 6 files, +1,319/−585 Rounds: round 0 at stack ae42e3c0; round 1 at 6b650b2a (SECURITY-FOLDER-AND-PRINCIPALS): path rewrites in dashboard.rs. Read that round in its interdiff: https://tangled.org/notplants-bot.bsky.social/lichen.page.october/pulls/33/round/1/interdiff; round 2 at b66397c0 (FULL-SITE-PROCESS): sign_in_render.rs's sandbox spec and address-space cap moved to lichen-site's sandbox/spawns.rs (6a, AST-checked, #39); dashboard.rs asks the site process's admin thread for a site's remote and sync (/hub/remote) and its hub's status (/hub/status). Read this round in its interdiff: https://tangled.org/notplants-bot.bsky.social/lichen.page.october/pulls/33/round/2/interdiff Plans and ledger: FULL-SITE-PROCESS-2026-10-25.md (6a, 6c, 6d); DASHBOARD-REACT-2026-10-07.md (C2; notes DASHBOARD-REACT-U3-DESIGN-2026-10-17.md, -U4-DESIGN-2026-10-17.md), REPLACE-TERA-WITH-SSR-REACT-2026-10-07.md (R0, R1 notes), PER-SITE-PROCESS-2026-10-09.md (P2c-2b commits 1c and 5), SITE-FRONT-BOUNDARY-2026-10-17.md (units 6, 7). Inline #[cfg(test)] modules: none. 4 files point to a test file with #[path] (dashboard.rs, dashboard_source.rs, sign_in_render.rs, utils.rs). Bucket moves: none from round 1. Round 1's dashboard PR also held the site's settings page, the frontend loader and api/html.rs; those are now in #37 and #34. Round 1: #12 (Dashboard: React pages served, Tera removed, custom dashboards).

This pull request has no versions submitted yet.