Reading copy of lichen.page.review: one PR per unit, product changes only

OCTOBER-REVIEW-REVISIONS subunits 2b-2d: commit push as a wake-up, iroh on the admin thread, and a restart race fixed #66

targeting base/october-review-revisions-unit-2b-2d from view/october-review-revisions-unit-2b-2d
Open opened by and assigned to notplants-bot.bsky.social
targeting base/october-review-revisions-unit-2b-2d from view/october-review-revisions-unit-2b-2d

A site's commit push into its hub becomes a wake-up, iroh moves to the admin thread, and one race is fixed.

  • Push as wake-up: the admin thread makes a watch of Committed { main, dist } and hands the sender down once at launch; the main runtime sends the ids it committed and gets nothing back. On each wake-up the admin thread takes the commits through the one receive, in a new push mode. The commit-making calls (hold, publish build, commit_to_hub) answer only once the hub holds their commit, offering up to three times if a client's push moves the hub meanwhile. A per-site lock serialises a site's offers. The admin router's and the front's relay of /hub/git-receive-pack are deleted.
  • iroh on the admin thread: the endpoint, node key and git sync start from admin.rs; a narrow IrohHub / SiteRooms interface separates the hub half from the rooms half. lichen-server's ipc/router.rs, ipc/transport.rs and ipc.rs, FrontLink::request (and its 1 MiB cap, which fixes iroh sync over 1 MiB), the five /hub/iroh/* routes and the related roles are deleted.
  • Fix: a request arriving right after the git remote is set no longer reaches the stopping site process (the route answers only once the old process has exited; a call cut short by a stop answers 503).

OCTOBER-REVIEW-REVISIONS, unit 2 (subunits 2b, 2c, 2d combined, replacing their per-subunit PRs). Plan: https://tangled.org/notplants-bot.bsky.social/lichen-orchestrator/blob/main/machine-docs/plans/OCTOBER-REVIEW-REVISIONS-2026-10-28.md

This is a reading copy: only this PR's product changes, applied in order on its base. Nothing here is to be merged.

Source PRs on lichen.page.review (product), in order, with their original descriptions #

  • #3394 s/762-orr-u2b-wake-up — ORR 2b: the site's commit push becomes a wake-up; the committing calls answer once the hub holds them

    OCTOBER-REVIEW-REVISIONS unit 2b, product: the site's commit push into its hub becomes a wake-up. The site's .git is still read only under the narrow rules (the operator's Open 5 decision (ii)).

    • The signal: the admin thread makes a tokio::sync::watch of Committed { main, dist }, keeps the receiver, and hands the sender down once at launch (MainSide.committed). The main runtime sends the ids of what it committed and gets nothing back, so no call goes from the main runtime to the admin thread.
    • The take: on each wake-up the admin thread takes the commits through 1c's from_the_site, in a new push mode. The pack crosses by file, the receive is staged, and push_from_the_site runs every check, then the remote push, auto-publish and the owner's note. A main that does not contain the hub's is not offered; the site is asked to merge the hub's in, and its commit wakes the loop again.
    • The three direct calls that commit (the hold, the publish build with refs/dist/latest, commit_to_hub) answer only once the hub holds their commit (ThenTheHub). If a client's push moves the hub between the site readying its main and the receive, the call offers again, three times in all. After the third it is refused: "the hub moved under each of 3 offers of the site's main: the site's commits are kept, and go with the next". That is not noted as a refused push; a refusal by a check is.
    • A per-site lock (admin_area::hub::offering) makes the site's offers into its hub one at a time and skips a commit the hub already holds. Nothing on the main side takes it.
    • Deleted: the admin router's and the front's relay of /hub/git-receive-pack, receive_from_the_site, OWN_PUSH, Role::OwnPush, Identity::own_push, host.rs's FrontHub, HubTransport, push_main and push_dist. iroh's routes, the router, transport.rs, link.rs's request side and told() stay for 2c.
  • #3396 s/764-orr-u2c-iroh-on-admin — ORR 2c: iroh on the admin thread, self-contained; the router, transport and link's request side go

    OCTOBER-REVIEW-REVISIONS unit 2c, product: iroh's endpoint moves to the admin thread (the operator's Open 4 decision (a), iroh kept self-contained), and the site process makes no requests of its own: the router, the transport and the link's request side go.

    • iroh on the admin thread. The endpoint, the node key and git sync start from admin.rs through iroh_hub::start. The key is checked against the launch's node id, and the main side never holds it. iroh's tasks run on the admin thread's runtime and call the hub directly, with no new runtime or channel. iroh-blobs stays on MemStore.
    • The narrow interface. iroh/ defines IrohHub (the hub half) and SiteRooms (the rooms half), with start, the_sites_key and main_moved. Only site_process/iroh_hub.rs implements them. Every other change outside iroh/ is a call through that interface or a deletion.
    • The rooms half is the main runtime's: a room's exchange is a future handed to it through on_main, with the QUIC stream moved inside. The open-room list and the peers panel cross as plain data.
    • Deleted:
      • lichen-server's ipc/router.rs, ipc/transport.rs and ipc.rs, and the internal group;
      • FrontLink::request with its 1 MiB answer cap (backlog iroh-sync-over-1mib-fails.md closes);
      • ask_the_front, iroh's FrontHub and ToFront::Connection;
      • the admin router's five /hub/iroh/* routes, Role::Iroh and Identity::iroh.
    • Rehomed: SiteRequests and told() go to lichen-server's site_process/front.rs. told() acts only while its launch is the site's current process, so an old launch's frame never reaches a recycled successor. SiteRequests keeps its name for unit 7's renames.
    • Docs: SANDBOX.md's diagram and rows, docs/SECURITY.md and docs/SITE-IROH.md. 2b's ready_again gains the doc sentence lichen-adversary asked for.
  • #3398 s/766-orr-u2d-spindle-fixups — ORR 2d: the git-remote route waits for the old process; a stop answers restarting; the node-key check end to end

    OCTOBER-REVIEW-REVISIONS fix-up 2d, product: two fixes from the first full lichen e2e on Spindle (lichen-adversary's item (b)) and from 2c's review (item (f)).

    • (b) A push right after the git remote is set. set_git_remote recycled the site without waiting, so a request could reach the stopping process. A direct call there was cancelled by the main runtime's shutdown and answered 500 ("task N was cancelled").
      • The route now answers only once the old process has exited (SiteProcesses::recycled, under the site's lifecycle lock).
      • A direct call cut short by a stop answers 503 with the forward's own wording, "the site is restarting; try again shortly", not 500.
      • This closes the backlog entry git-remote-set-races-the-site-restart.md.
    • (f) A test-routes-only hook in site_process/front.rs, so a test can send a launch another node key, or none, and see the admin thread's node-key check refuse it end to end.

Commits #

  • e8ce61138 OCTOBER-REVIEW-REVISIONS unit 2b-2d: subunit 2b
  • 1f81f1e3b OCTOBER-REVIEW-REVISIONS unit 2b-2d: subunit 2c
  • 304fdcfb7 OCTOBER-REVIEW-REVISIONS unit 2b-2d: subunit 2d

Count and shas #

count-product-code-lines f1d4968a1e11..304fdcfb735b: NET +63 · counted +1075 -1012 · moved out of the counted set +0 · comment-only deletions flagged 171 · macros flagged 0 · tests-folder code flagged 0

Base f1d4968a1e11a3ed0dfd0583d7ae0a954f41ab73 (tip of s/761-orr-u1c-one-receive-tests). Head 304fdcfb735b069fa02434cc7743554b8ec5f81b. 41 files changed.

Check #

Every changed file is a file one of the product PRs changed, and each is identical at the head to the same file at the last product branch s/766-orr-u2d-spindle-fixups.

No file here was changed by any tests PR of this unit.

Commits 0