A child that may ask for a publish or a push (a Python script's child, the Lua/JS/SSR/mdBook engine children, the terminal's shell) holds no credential. Instead it is handed one end of a fresh socketpair at a descriptor of its own, and asks on it. The site process's admin thread, which holds the publish and the pushes, serves the other end with a child router that has exactly two routes.
What it settles (FULL-SITE-PROCESS part 3, the operator's O3 and O4, unit 6g):
- The origin is the socket's. It is set at accept from the kind of child the socket was made for (
Origin::Child(kind)), never from the request. An identity header on it is refused, and the kind's principal is admitted (ChildKind::principal). - Each child's pair is fresh. Its far end is in that child alone, and a socketpair has no address another child could reach.
- One ask in flight per kind. A second ask is answered 429 at once, and a publish asked while one runs is refused by the publish's own lock, so a script in a loop queues nothing. A child has 10 s to send an ask's headers.
- The child router is
POST /cms/api/publishand the editor's push routes (git::editor::push_routes), each in the site'sPUSHESgroup, which a script and the terminal hold. Nothing else is on it. ask(method, path)is the child's side: one request on the inherited descriptor (ROUTES_FD).
Files
crates/lichen-site/src/site_process/child_routes.rs— new: the socket per child, the router, the one-at-a-time layer, and the child'sask. Read it top to bottom.
Lives elsewhere
- The permissions a child kind holds (
TriggerPushToPds,TriggerPushToRemoteand theScriptandTerminalprincipals): #18. The publish run it reaches:lichen-site/src/publish/run.rsin #25. The push routes:git/editor.rsin #23. - Where a child is given its end (the spawn paths of scripts, engines and the shell): #26 (scripts), #36 (shell), and
lichen-sandbox'sROUTES_FD, #17. The admin thread that serves it: #38. - The tests (
site_process__child_routes.rs, e2e) are in the base commit.
Category: The child-routes socket: what a credential-less child may ask
Size: 1 file, +329/−0
Rounds: round 0 at b66397c0 (new in this round).
Plans and ledger: FULL-SITE-PROCESS-2026-10-25.md (part 3, "How children reach the site's routes"; O3, O4; units 3f and 6g) with FULL-SITE-PROCESS-U0-DESIGN-2026-10-26.md; lichen-builder 6g (e665510d).
Inline #[cfg(test)] modules: none. child_routes.rs points to a test file with #[path].
Bucket moves: a new subject in this round, given a PR of its own: the per-child route socket. 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.