Summary
Operators running the proxy for both open-source and commercially sensitive (e.g., joint-venture) repos need to control who can see which push records in the dashboard. Today every authenticated user sees all push history for all repos. Two related capabilities are needed:
- Repo-level visibility restriction: mark specific repos as private so their push records are only visible to users with an explicit permission grant (contributor or reviewer)
- "My repos" filter: an opt-in UI/API filter that scopes the push list to repos where the authenticated user is assigned — useful for both private deployments and large open deployments where noise is the problem
Current state
PushController.list() (GET /api/push) accepts status, project, repo, user, and search filters but has no concept of per-user visibility. Every authenticated user sees every push record. The RepoPermission store already holds the data needed to answer "which repos is this user assigned to" — RepoPermissionStore.findByUsername(username) returns all grants for a user.
PushRecord carries provider and url (the upstream repo URL), which can be compared against RepoPermission.path to determine whether a record is accessible.
Proposed approach
1. restricted flag on URL allow rules
Add a restricted: true field to RuleConfig (the YAML allow-rule entry). A restricted rule means push records for matching repos are hidden from users who have no RepoPermission grant (PUSH or APPROVE) for that repo. Unrestricted repos (the default) are visible to all authenticated users as today.
git-proxy:
rules:
allow:
- slugs: [acme-jv/private-repo]
restricted: true
This is intentionally coarse — the visibility flag lives at the rule level, not per-repo, which keeps the config surface small.
2. GET /api/push?mine=true filter
New optional filter param on PushController.list(). When mine=true and the user is authenticated:
- Fetch all
RepoPermission grants for the user via RepoPermissionService.findByUsername()
- Filter the returned push records to those whose
provider + url match at least one grant
mine=true does not imply visibility restriction — it works on both open and restricted repos. It's the "show me my work" view.
3. Visibility enforcement
When the configured rule set contains at least one restricted: true rule, PushController.list() (and getById) must enforce visibility:
- ROLE_ADMIN bypasses visibility — always sees everything
- Authenticated non-admin users see: all non-restricted repo pushes, plus restricted repo pushes where they have a grant
- The set of accessible restricted paths is derived from
RepoPermissionService.findByUsername(auth.getName())
The restriction check does not need to be in the DB query — post-filter in Java is acceptable for the initial implementation given typical push list sizes. A DB-level predicate is a follow-on optimisation.
4. Dashboard UI
- Add a "My repos" toggle to the push list filter bar
- Restricted repos that the current user cannot see should not appear in search suggestions or repo dropdowns
- Admins should see a visual indicator that a repo is restricted (e.g. a lock icon in the push detail)
Constraints
- The
restricted flag needs to round-trip through the live config reload path (LiveConfigLoader) so operators don't need a restart to restrict/unrestrict a repo
RepoPermission.path uses /owner/repo convention; PushRecord.url is a full upstream URL — the visibility check needs a normalisation step to compare them (strip host prefix, strip .git suffix)
- Org-level tagging for repos (filtering by topic/team) is a related quality-of-life improvement worth tracking as a follow-on but is out of scope here
Summary
Operators running the proxy for both open-source and commercially sensitive (e.g., joint-venture) repos need to control who can see which push records in the dashboard. Today every authenticated user sees all push history for all repos. Two related capabilities are needed:
Current state
PushController.list()(GET /api/push) acceptsstatus,project,repo,user, andsearchfilters but has no concept of per-user visibility. Every authenticated user sees every push record. TheRepoPermissionstore already holds the data needed to answer "which repos is this user assigned to" —RepoPermissionStore.findByUsername(username)returns all grants for a user.PushRecordcarriesproviderandurl(the upstream repo URL), which can be compared againstRepoPermission.pathto determine whether a record is accessible.Proposed approach
1.
restrictedflag on URL allow rulesAdd a
restricted: truefield toRuleConfig(the YAML allow-rule entry). A restricted rule means push records for matching repos are hidden from users who have noRepoPermissiongrant (PUSH or APPROVE) for that repo. Unrestricted repos (the default) are visible to all authenticated users as today.This is intentionally coarse — the visibility flag lives at the rule level, not per-repo, which keeps the config surface small.
2.
GET /api/push?mine=truefilterNew optional filter param on
PushController.list(). Whenmine=trueand the user is authenticated:RepoPermissiongrants for the user viaRepoPermissionService.findByUsername()provider+urlmatch at least one grantmine=truedoes not imply visibility restriction — it works on both open and restricted repos. It's the "show me my work" view.3. Visibility enforcement
When the configured rule set contains at least one
restricted: truerule,PushController.list()(andgetById) must enforce visibility:RepoPermissionService.findByUsername(auth.getName())The restriction check does not need to be in the DB query — post-filter in Java is acceptable for the initial implementation given typical push list sizes. A DB-level predicate is a follow-on optimisation.
4. Dashboard UI
Constraints
restrictedflag needs to round-trip through the live config reload path (LiveConfigLoader) so operators don't need a restart to restrict/unrestrict a repoRepoPermission.pathuses/owner/repoconvention;PushRecord.urlis a full upstream URL — the visibility check needs a normalisation step to compare them (strip host prefix, strip.gitsuffix)