Feature #240: pull-only mirror repos #250
No reviewers
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub!250
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/issue-240"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements Forgejo issue #240 (plan revision R1 normative): mirror repos with scheduled upstream syncs.
What:
meta/mirror.jsonsidecar (Create-once-then-CAS'd, frozen-list amendment in 14_extensibility.md) +mirror-synctask kind + bucket lease (leases/mirror-<owner>-<name>.pb) + follow-shaped 1m loop (registry enumeration, no LIST) + followOnce-shaped converge (ff-only, rewind refuse+narrate, force escape) + funnel push refusal (discovery 403, in-pipeline ng, SSH pre-advertisement; sync bypasses via direct Publish) + import-vs-sync exclusion (Begin 409 / claim-skip) + failure counter + capped backoff + computed next-fire + create-from-URL flow (public upstream, memory-only first-sync token) + mirror badge/next-sync UI + Settings Mirror tab + Sync-now + schedule presets + EVIDENCE E15.Decisions appended: (a) public-only v1, (b) sidecar+frozen list, (c) funnel placement, (f) ff-only (11_mirror.md + 14 + go docs 02/04/05/06/07/10/12). No new Go modules, no new npm deps.
walhub mirrorCLI stub stays a stub (out of scope, documented).Tests: internal/mirror 97.0% (-race), server 95.6%, api 95.4%, repoimport 95.9%, store 95.1%; node --test 471 green; make vet + contract green; full short suite green; e2e green; push-budget test wires the shipped guard (cold 10/warm 9 ops, other collab families zero). Live-server proof: create -> first sync -> scheduled loop fire -> push refused (403/ng/real git client) -> summary/badge data (E15). In-browser render recorded OPEN: shared Chrome daemon network-guard blocks all private/loopback targets, private daemon forbidden.
Closes #240 (do not merge from here).
PUT /{o}/{r}/api/mirror create branch now probes the manifest first: an unborn target gets 404 instead of an orphan sidecar that would 403 every future push to the name while every sync fails at Open (PUT is config on a repo; the create twin owns repo creation). Rewind-refusal narration + sidecar LastResult now pass through scrubText: ref names are upstream-controlled and '=' is legal in a refname, so a hostile upstream could otherwise smuggle credential-shaped text into task logs and the outcome field (import S2 discipline). Tests: unborn-PUT 404 with no sidecar left behind; hostile-branch rewind asserts redaction in both the sidecar and the task log tail.