Federated collaboration: roadmap
Forward-looking plan for growing federation from follow-and-feed (what ships today) into cross-instance collaboration — discovering people's work on other instances, forking it, and contributing back with a merge request that travels over ForgeFed.
This document is the why and the sequence. For how the current subsystem is built see ForgeFed architecture; for operating it see the deployment guide; for the user view see the user guide.
The vision
A contributor on instance A wants to help with a project on instance B without opening an account on B:
- Follow the author on B and see all their public repositories aggregated in one place, with recent activity.
- Click through to a repository's activity and open it.
- Fork it onto instance A (their home instance).
- Push a contribution branch to the fork and open a merge request back against the upstream on B — over federation, no account on B.
- See the outcome (accepted / rejected / merged) back on A.
Steps 1–3 are mostly discovery and plumbing that build on existing pieces. Step 4 is the protocol epic.
Where we start
Today federation is repository-follow + push feed (see the "What works today" list in forgefed.md). You follow repositories, not people; there is no cross-instance fork and no federated merge request. Local issues, MRs, and forks do not cross the instance boundary.
Stories
Story 1 — Follow a user, see their aggregated repositories (done)
Follow a remote Person actor and see their public repositories, grouped, with
recent push activity per repo — instead of following each repository one by one.
-
✅
Personactor exposes arepositoriescollection (/ap/users/{username}/repositories, public repos only) and advertises it in the actor document. -
✅ Follow a remote user:
RemoteFollowService.followUserresolves thePerson, reads their repositories collection viaRemoteRepositoryDirectory, and fans out to a repository follow per public repo (taggedviaUserActorId), reusing the existing Follow/Accept/Push machinery. -
✅ Followed users persisted (
remote_user_follows); the/followingUI groups repositories and their push activity under each followed user. -
✅ A periodic
FederationResyncSchedulerre-scans each followed user's repositories collection (add-only) so repos created after the follow are picked up automatically — no re-follow needed.
Remaining follow-ups are add-only reconcile limits (no unfollow on remote delete/private) and collection pagination — see the gap list in forgefed.md.
Story 2 — Cross-instance fork with upstream tracking (issue #12)
Fork a remote public repository into the caller's local namespace; persist the upstream link (remote actor URL + clone URL). The clone works over plain git today — the new work is the upstream model and the UI surface.
Key risk: cloning a remote-supplied git URL is a new outbound network
surface. RemoteUrlGuard today guards HTTP fetches only; git clone/fetch must
get the same SSRF discipline. Security review required.
Story 3 — Merge request via federation (issue #13, epic)
The submitter forks upstream (Story 2), pushes a branch, and opens a merge request against the upstream repo on the other instance; the outcome flows back.
Protocol shape: fork-and-pull via Offer(Branch) (chosen over patch-offer).
| Option | How | Verdict |
|---|---|---|
| A. Patch-offer | Offer{Ticket + embedded patch} to upstream inbox; target rebuilds MR from the diff | Simpler wire, but no shared git objects; large patches are ugly. Rejected for v1. |
| B. Fork-and-pull | Fork → push branch → Offer{Branch} carrying the branch fetch URL; target git fetches it and opens a local MR referencing it | Matches the user's mental model, keeps real git objects (reviewers see real commits/diffs, can pull the branch), degrades gracefully. Chosen. |
Build order inside Story 3:
- Outbound
Offer(Branch)— new activity type, enqueued viaDeliveryService. - Inbound
OfferHandler— validate,git fetchsubmitter branch (SSRF-guarded), create a local MR referencing the remote branch. - Status back-channel —
Accept/Reject/merge-notify so the submitter sees the outcome.
Cross-cutting prerequisites
These bite across Stories 2–3 and should be tracked as they land:
- Outbound git fetch/clone SSRF guard — extend
RemoteUrlGuard(or a sibling) to cover the git transport, not just HTTP. New attack surface introduced by Story 2, reused by Story 3. - Actor lifecycle (
Delete/Update/Move) — still on the gap list in forgefed.md. A federated MR that references a deleted or moved remote fork goes stale silently until this exists. - Interop scope — everything here targets git-shark ↔ git-shark first. Forgejo/Vervis federation is early and likely incompatible; broadening is a later, separately-scoped effort.
Explicitly out of scope (for now)
- Federated review comments / inline discussion on a merge request.
- Open (non-allowlisted) federation — the mutual peer allowlist stays the trust boundary throughout this roadmap.
- Keeping a fork continuously in sync with its upstream beyond the initial clone.