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

product: 13 Site crate core: api, settings, shell, runtime #60

targeting oct/12-dashboard from oct/13-site-core
Closed opened by and assigned to notplants-bot.bsky.social
targeting oct/12-dashboard from oct/13-site-core

superseded by the full set from 09-23, #17–#37

description: Review set for lichen.page.review, 0b92cb61 (reviewed) → eb5a1653 (stack). PR 13 of 16. 26 files, +960/−947. One commit, f7035241dfec, which sets these files to their content at eb5a1653. Targets #12 (oct/12-dashboard). #14 stacks on this one. Tests and generated files are not in any PR; they are in main.

The rest of lichen-site: its HTTP layer, runtime, settings, shell and shared types. Most of the change follows from the PRs below this one; the parts with a subject of their own are:

  • The site's routes are in permission groups (api.rs): site_group(READS), WRITES and the group for sending the site out (pushes, publishing), each admitted by the site's policy (#2). The site's API is one route table and one error shape.
  • The terminal's PTY pair is opened by the front server (STC-PTS1): a site process that opened its own pairs needed all of /dev/pts, where one site's terminal could open another's. shell/peer_pty.rs takes the pair the front server passes over (ToFront::Pty); off Linux the old portable-pty path stays.
  • Over the storage limit, no site code runs (SHB-STORAGE1): StorageLimitState::over_now asks now rather than trusting a cached flag, because a script that rewrites history grows the backup with no request to trigger a recount.
  • The site holds no owner session (SITE-FRONT-BOUNDARY unit 9b): credentials.rs and owner.rs keep only the types and the owner's public facts.
  • features.rs (−460) loses the git push wiring and the iroh runtime, which moved to the front server; it keeps the history acts under /cms for a server without a dashboard.
  • runtime.rs/runtime_build.rs: the runtime knows its hub, its dashboard URL ("" on the desktop, none for a single site) and whether the shortcode cache is on.
  • contract/cms-api.json: the health route, git/pds-remote, git/commit-to-hub, /auth/handoff, which routes a single site serves, and GET+POST where a GET no longer acts.

info: Plans: SITE-FRONT-BOUNDARY-2026-10-17.md (decision 4: the terminal pair; units 9b, 11), LICHEN-SANDBOX-AND-PERMISSIONS-2026-10-13.md L2d (the site's groups), OPERATOR-REVIEW-REVISIONS-2026-10-13.md (N8), DASHBOARD-REACT-2026-10-07.md (A2: the desktop's dashboard URL), and the fixes STC-PTS1 and SHB-STORAGE1.

Files (crates/lichen-site/ unless noted)

  • src/api.rs — the route table in groups. Read first.
  • src/shell/peer_pty.rs — new: the PTY pair from the front server (STC-PTS1). src/shell/pty.rs, shell/router.rs, shell.rs — use it on Linux.
  • src/types.rs — StorageLimitState::over_now, what over-limit refuses; the publish hook type goes.
  • src/features.rs (+137/−460) — the site's feature wiring, smaller.
  • src/runtime.rs, src/runtime_build.rs — the hub handle, dashboard URL, shortcode-cache flag.
  • src/credentials.rs (−79), src/owner.rs (−93), src/host.rs — no session, no relay opener, no storage question.
  • src/settings.rs, src/settings/server.rs — auto_publish read as the site's; use_shortcodes_cache; the mode the launch carried.
  • src/api/api_utils.rs — the API's one error shape applied to the dashboard's /api too, and json_only: ?format=html refused inside a route's permission group, so a refused caller gets the group's answer, not a 406 that reveals the route.
  • src/api/build.rs, api/files.rs, api/site.rs, api/batch.rs, api/frontend.rs, api/plugins.rs — a build installed with errors fails the route; a refused body is drained; the settings link; over_cached().
  • src/symlink.rs — the escaping-symlink check takes git env, for the hub's pre-receive (#5).
  • src/events.rs, src/lib.rs, Cargo.toml — module list; lichen-sandbox, shlex, tokio-util in; iroh-blobs, n0-error, http-body and the old iroh test targets out.
  • contract/cms-api.json (repository root) — the site API contract.

Moved in: contract/cms-api.json (the starting map called it generated; it is hand-written, with route notes, and the server's tests compare the routes with it).

Lives elsewhere

  • The site's other modules have their own PRs: sandbox, permissions, site process, storage and share, hub, git, publishing, builds, iroh, dashboard (Tera removal). See the stack.
  • Tests (src/tests/*.rs, tests/*.rs) are in main.
Commits 0