~bigbes/sr-ht-spec

ref: f82d90a4317a0f36bb56eb4ba402f0c0c6d09950 sr-ht-spec/hooks/server_test.go -rw-r--r-- 16.5 KiB
c7e4f9f9 — Eugene Blikh 27 days ago
feat: hooks — the receive path, its daemon RPC, and the specsrht daemon

The hooks are thin shims that RPC into the running daemon over a unix
socket under the repos root, so validation lives in one place and the
push path cannot drift from the API. They fail closed: an unreachable
daemon rejects the push.

Three hooks are installed, not two, because of two properties of git
verified against 2.55 rather than inferred:

  - GIT_PUSH_OPTION_* reaches pre-receive and post-receive only; the
    update hook observably runs without them, so it cannot see
    --push-option=skip-validation on its own.
  - during pre-receive the pushed objects are still in receive-pack's
    quarantine and unreadable by any other process, so the daemon
    cannot validate there. git migrates them out before the first
    update hook, which makes update the earliest hook that works.

pre-receive therefore forwards the push options and the ref list; the
daemon records them keyed by (repository, receive-pack pid) and by the
exact ref update; update does the rejecting; post-receive notifies.
An update with no recorded pre-receive phase is refused rather than
assumed unskippable.

Each hook is a symlink to the specsrht binary, which dispatches on the
name git invoked it as. Install also sets receive.advertisePushOptions,
without which the escape hatch fails client-side. The daemon refreshes
every space's hooks at startup and treats a failure as fatal.

cmd/specsrht validates every config key at once before opening
anything, serves /healthz on -b (default localhost:5091), runs the
reconciler, and warm-shuts-down on SIGINT and SIGTERM alike by
bridging SIGTERM into the SIGINT core-go's server.Run waits for.

Tested with a real git push against a real bare repo with the hooks
installed: a valid push lands, bad frontmatter is rejected with a
readable message, skip-validation waives it, a force-push to the
approved branch is refused with or without skip-validation, a mistyped
push option is refused rather than ignored, and a push with no daemon
is rejected.