A site process now runs as two halves. site_process_main starts an admin thread first, which keeps the site process's full grants (its folder and its admin area). The process's own thread then narrows itself, and it builds the main runtime that serves the site's routes and starts every child. The admin thread owns the control channel and serves the front server's admin acts with a router of its own that has no listener.
The order in start.rs is the containment. Landlock applies per thread, and a new thread starts in its creator's domain.
- The admin thread is started, keeping the grants, and waits.
- The process checks it has exactly two threads, its own and the admin thread. A thread made earlier would keep the full grants (the plan check's D5a).
- Its own thread narrows itself to the rules the sandbox mode handed over (
NARROW_VAR). - That narrowed thread builds the main runtime, so every worker, blocking thread, library pool and child from here on is narrowed.
- The globals that start a thread on first use (the watchdog's patrol, the SSR and script-generator sweeps) are touched here, on the narrowed side (D5b).
- Only then is the admin thread let go (
Admin::go).
An unconfined site process (local mode, use_sandbox = false) is handed no rules. It still starts its admin thread, so there is one shape, and narrows nothing.
What the admin thread does (admin.rs, FULL-SITE-PROCESS 6b onward):
- It opens the control channel and checks the channel is the front server's. It reads the launch, then every frame:
- client connections (
ToSite::Connection) are handed to the main runtime (MainSide), at most 64 waiting; - the front server's admin connections (
ToSite::Admin) are served here byadmin_router; - the owner's lent session (
ToSite::Credentials) and the iroh node key (ToSite::NodeKey) are kept here.
- client connections (
admin_routerserves the site's hub routes (clients' smart HTTP, the site's own push, its iroh endpoint's asks, the backup's status and the owner's compact, each admitted again by the forwarded identity) and the test probes undertest-routes.- Admin code runs only on this thread's own runtime and calls nothing of the main runtime's. Its jobs carry their own deadlines (E4).
- The admin door guards against a logic bug, a smuggled request or a confused path in the main runtime passing a connection off as the front server's admin one. It is not a guard against code running in the main runtime, which shares the process's memory and descriptors; the plan accepts this.
Files (crates/lichen-site/src/site_process/)
start.rs— new:site_process_main, the start-up order above. Read this first.admin.rs— new (697 lines):Admin,MainSide, the frame loop,admin_routerandhub_routes.
Lives elsewhere
- The narrow rules and every other sandbox, as data:
sandbox/spawns.rsin #39. The mechanism that narrows a thread:lichen-sandbox'ssandbox.rsin #17. - The control channel's frames (
control.rs), the launch,serve.rsand the site process's lifecycle: #19. The lent session (site_process/session.rs): #19. The node key (site_process/node_key.rs): #28. - The hub's handlers the admin router serves (
site_process/hub.rs,git/hub_http.rs): #21. The child-routes socket, also served by this thread: #40. SANDBOX.mdanddocs/SECURITY.md(the picture of the three kinds of process) are in the base commit, as are the tests (src/tests/site_process__admin.rs, the structure test inworkspace_structure.rs).
Category: The site process's start-up and its admin thread
Size: 2 files, +766/−0
Rounds: round 0 at b66397c0 (new in this round).
Plans and ledger: FULL-SITE-PROCESS-2026-10-25.md ("Two runtimes in the site process, and one narrow sandbox"; units 1, 3a, 6b–6h) with FULL-SITE-PROCESS-U0-DESIGN-2026-10-26.md (D5a, D5b, E4); machine-docs/reviews/FULL-SITE-PROCESS-PLAN-CHECK-2026-10-25.md; lichen-builder 1b (4c06e295), 6b (855ee8aa), 6c step 2 (756e8213).
Inline #[cfg(test)] modules: none. admin.rs points to a test file with #[path].
Bucket moves: a new subject in this round, given a PR of its own. It belongs beside the site process (#19), but it sits on top of the stack: Tangled cannot retarget a PR, so a PR inserted lower would make the one above it show the inserted commit.
Round 1: none: new in this range.