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

product: 06 Git: the front server pushes, fetches and rewrites #53

targeting oct/05-hub from oct/06-git-sync
Closed opened by and assigned to notplants-bot.bsky.social
targeting oct/05-hub from oct/06-git-sync

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

description: Review set for lichen.page.review, 0b92cb61 (reviewed) → eb5a1653 (stack). PR 6 of 16. 17 files, +4190/−2149. One commit, 96a1568f6076, which sets these files to their content at eb5a1653. Targets #5 (oct/05-hub). #7 stacks on this one. Tests and generated files are not in any PR; they are in main.

No site reaches a git remote any more; the front server does it, from the hub (SITE-FRONT-BOUNDARY units 6, 7, 8 and 11b1). The site commits and pushes into its hub (#5); the front server pushes the hub to the site's remote, fetches the remote into the hub, and does every history rewrite. The owner's PDS session and deploy key stay in the front server, so the site's credentials code, the SSH relay a site's git ran through, and "lent git" pinning are gone.

  • Outbound (unit 6): after each move of the hub's main, one coalescing worker per site pushes it to the remote, when the site's sync says auto_push. Retries back off up to an hour. Git runs from the hub with no system or global config, its URL in the environment, and confined where sites are sandboxed. A failed push is shown to the owner, redacted, until one succeeds.
  • Where to: the site's remote is now a record in its area (remote.toml), set by the owner on the dashboard. A URL found only in the site's own .git/config is a proposal and is never pushed to or fetched from until the owner confirms it.
  • Inbound (unit 7): the dashboard's auto-pull, the editor's pull and remote status fetch into the hub's hidden refs/remotes/origin/*, staged and screened first (storage bound, escaping symlinks, no tip that brings back what a compact replaced). The site then merges from the hub.
  • Rewrites (unit 8: compact, force-pull, force push, and a full token's force push): the site holds and pushes its pending work, the front server moves the hub's main by compare-and-swap, the site resets to it, and only then is anything irreversible done (prune, forced push to the remote). A reset not made puts the hub back.
  • The editor's git panel (unit 11b1): status, remote status, Push and pull are answered by the front server on the site's host, in the groups and answer shapes the site's routes had.

info: Plans: SITE-FRONT-BOUNDARY-2026-10-17.md (units 6, 7, 8, 11b1; "Sync ends"; decision 7, revised 2026-10-21: a full token may force push), notes SITE-FRONT-BOUNDARY-U6-DESIGN-2026-10-21.md, -U7-DESIGN-2026-10-22.md, -U8-DESIGN-2026-10-22.md. Concurrent merges are deferred (decision 12, machine-docs/backlog/concurrent-merge-convergence.md).

Files

Front server (crates/lichen-server/src/):

  • git/outbound.rs — new: the push of a hub to its remote; PUSH_CONFIG, moved, now, failure reporting. Read first.
  • git/inbound.rs — new: the fetch into the hub, staging and screening, the compact-replaced check.
  • git/rewrite.rs — new: hold, compare-and-swap, reset, then prune and force; take_a_client_push for #5's full-token push.
  • git/editor.rs — new: the editor's git panel routes on the hub.
  • site_area/remote.rs — new: the remote record (url, found, site_key), its migration from .git/config, resolve, sync_of, redacted.
  • git/push_worker.rs — moved from lichen-site; now the front server's coalescing loop.
  • git/ssh_relay.rs — now the front server's own SSH with the deploy key (a 0600 file per run, known hosts held); the relay for a site's git is gone.
  • git/hooks.rs — auto-pull asks a site to merge only when the fetch brought something.
  • git.rs, git/router.rs — module list and imports.

Site (crates/lichen-site/src/):

  • git/ops.rs (+135/−1123) — the push, pull, credential piping and lent-git code removed; recovery of an older lichen's interrupted compact kept.
  • git/hooks.rs (−290) — push decisions and owner auth removed; PDS-remote setup kept.
  • git/router.rs (−216) — the site's git routes, now in permission groups; push/pull routes moved to the front server.
  • git/settings.rs, git/ssh.rs, git/site.rs, git.rs — GitAuth loses its relay variants (the owner's key is used only by the front server); the SSH relay client removed; commit_build_writes (a build's own writes, N1); hermetic_env gains one variable.

Moved in: lichen-server/src/git.rs and lichen-site/src/git.rs (the module roots, which the starting map put in the crates' core buckets) and site_area/remote.rs (Site area: it is the remote record the push and fetch read).

Lives elsewhere

  • The hub's receive and the site's push into it: #5. The hub repository's rewrite helpers (squashed, move_main, put_main_back): #4.
  • The dashboard's routes that start these acts (/api/sites/{d}/git/compact, force-pull, auto-pull, compact-all): api.rs in #11.
  • Publishing's own push of the source and its Pages deploy: #7.
  • lichen-site/src/ipc/git.rs (revert, now an ordinary route): #3.
  • Tests (git/tests/*.rs, lifecycle_tests.rs, e2e git tests) are in main.
Commits 0