feat: add scoped image sync endpoint

This commit is contained in:
2026-08-06 14:58:41 +00:00
parent 5078f6f3b1
commit 2fb618aa5c
11 changed files with 229 additions and 6 deletions
+24
View File
@@ -80,6 +80,30 @@ Use branch filter `master`. Disable the old PHP webhook before enabling the new
writer. The legacy PHP files remain in `hook/` for an explicit rollback, but
PHP and Node must never mutate the checkout concurrently.
### Fallback sync callers
If Gitea webhook delivery is missed, Core and Core2026 can request a restricted
reconciliation through `POST /v1/sync`. This endpoint cannot select or change a
branch: it only fetches the current active branch and applies the same clean
worktree and fast-forward checks as a webhook deployment.
Each caller has a separate secret:
- `secrets/image_sync_core_secret` for legacy Core
- `secrets/image_sync_core2026_secret` for Core2026
The caller sends its name, a timestamp, a unique request ID, and an HMAC-SHA256
signature over `timestamp.request-id.<exact JSON body>`. Requests expire after
five minutes and successful request IDs are persisted for replay protection.
The body is either `{}` or `{ "commit": "<full-image-commit-sha>" }`; all other
fields are rejected. The optional commit asserts the expected remote tip and
does not grant checkout selection.
Distribute only the matching caller secret through an ignored secret file.
Never give either caller `image_admin_secret`, which also authorizes explicit
branch changes. This fallback handles webhook delivery outages; if the image
service itself is stopped, restore it and run the caller command again.
Legacy HTTP mutation is disabled by default. An emergency PHP rollback must
first stop `image-hook`, then create the ignored `hook/legacy-enabled` sentinel
in the legacy checkout before restoring its Caddy/Gitea route. Remove the