Problem
jgit-proxy-server is supposed to run standalone (proxy-only, no dashboard), but store-and-forward mode is functionally broken without a dashboard.
GitProxyServletRegistrar.registerGitServlet() hardwires UiApprovalGateway:
var approvalGateway = new UiApprovalGateway(pushStore);
UiApprovalGateway polls PushStore every 5 seconds waiting for a human approval via the REST API — which only lives in jgit-proxy-dashboard. Every push lands in BLOCKED and hangs the git client for 30 minutes before timing out.
Proxy mode (/proxy/) works fine standalone today. Store-and-forward does not.
Root Cause
Three hardcoded concerns:
ApprovalGateway selection — UiApprovalGateway is constructed directly despite ApprovalGateway being an interface with multiple implementations
- Store-and-forward hook chain — fixed array of hooks inline;
persistenceHook != null branch exists but no other extension points
- Proxy filter chain —
AllowApprovedPushFilter (dashboard concern) is unconditionally registered by the server-level registrar
Plan
Phase 1 — Fix standalone server (high ROI, minimal change)
Phase 2 — Decouple filter and hook chains
Module Changes
| Module |
Change |
jgit-proxy-core |
Add AutoApprovalGateway |
jgit-proxy-server |
Add approval-mode config; buildApprovalGateway(); ApprovalGateway param on registerGitServlet; split registerFilters |
jgit-proxy-dashboard |
Pass UiApprovalGateway explicitly; call registerApprovalFilters() |
Non-Goals
- Full plugin SPI for hooks/filters
- Removing
PushStore from standalone (useful for audit logging; memory backend needs no infra)
- Changing the transparent proxy path (works correctly standalone today)
Problem
jgit-proxy-serveris supposed to run standalone (proxy-only, no dashboard), but store-and-forward mode is functionally broken without a dashboard.GitProxyServletRegistrar.registerGitServlet()hardwiresUiApprovalGateway:UiApprovalGatewaypollsPushStoreevery 5 seconds waiting for a human approval via the REST API — which only lives injgit-proxy-dashboard. Every push lands inBLOCKEDand hangs the git client for 30 minutes before timing out.Proxy mode (
/proxy/) works fine standalone today. Store-and-forward does not.Root Cause
Three hardcoded concerns:
ApprovalGatewayselection —UiApprovalGatewayis constructed directly despiteApprovalGatewaybeing an interface with multiple implementationspersistenceHook != nullbranch exists but no other extension pointsAllowApprovedPushFilter(dashboard concern) is unconditionally registered by the server-level registrarPlan
Phase 1 — Fix standalone server (high ROI, minimal change)
AutoApprovalGatewaytojgit-proxy-core— auto-approves clean pushes instantly, rejects violations immediately (no polling)approval-modeconfig key (auto|ui); defaultautofor the server-only entry pointJettyConfigurationBuilder.buildApprovalGateway(PushStore)to instantiate from configApprovalGatewaythroughregisterGitServlet(...)as an explicit parameter — remove hardwirednew UiApprovalGateway(pushStore)GitProxyWithDashboardApplicationalways constructs and passesUiApprovalGatewayregardless of configPhase 2 — Decouple filter and hook chains
registerFiltersintoregisterCoreFilters()(always runs) andregisterApprovalFilters()(dashboard calls additionally) — mirrors the existingpersistenceHook != nullconditionalGitProxyWithDashboardApplicationcalls both; standalone server calls onlyregisterCoreFilters()Module Changes
jgit-proxy-coreAutoApprovalGatewayjgit-proxy-serverapproval-modeconfig;buildApprovalGateway();ApprovalGatewayparam onregisterGitServlet; splitregisterFiltersjgit-proxy-dashboardUiApprovalGatewayexplicitly; callregisterApprovalFilters()Non-Goals
PushStorefrom standalone (useful for audit logging; memory backend needs no infra)