Skip to content

v1.4.0

Choose a tag to compare

@coopernetes coopernetes released this 12 Sep 18:59
· 145 commits to main since this release
Immutable release. Only release title and notes can be modified.
v1.4.0
7ca7afc

fogwall 1.4.0

fogwall 1.4.0 turns the push gateway into a broader SCM control plane: it now proxies the SCM CLIs (gh, glab, tea, fj) so pull/merge requests, issues, comments and merges flow through the same inspection and audit path as pushes, and it links proxy users to their upstream SCM accounts (GitHub, GitLab, Forgejo/Gitea) for real identity enforcement. The default developer push workflow is unchanged, but operators upgrading from 1.3.2 have several config renames and tightened defaults to review below.

Breaking changes & upgrade notes

  • Server mode routing — /server/ is now canonical, /push/ is a deprecated alias. The mode formerly called "store-and-forward" is now "server mode", served at /server/<provider>/<owner>/<repo>.git. Existing /push/… remotes keep working through the alias, so nothing breaks on upgrade, but move remotes and scripts to /server/ — the alias will be removed in a future release. The dashboard REST field pushPath is renamed serverPath. (#538, #540)
  • SSH is now a property of a provider entry, not a separate provider. One providers: entry serves both HTTP and SSH to the same upstream, and identity/permissions/OAuth links apply across both. A top-level ssh:// uri no longer enables SSH and warns at startup — consolidate any separate github-ssh-style entries into the HTTP entry. Additive config only, no DB migration. See https://rbc.github.io/fogwall/configuration/ssh-transport.html (#531, #534)
  • commit.identity-verification renamed to commit.attribution-policy. The old key still binds with a startup deprecation warning and will be removed in a future release. The legacy commit.*.email.domain.allow / local.block keys are likewise kept as deprecated aliases for one minor release. See https://rbc.github.io/fogwall/configuration/commit-attribution.html (#146, #552)
  • Tightened push size defaults. A new server.max-object-size-bytes (default 512 MiB, 0 = off) bounds the decompressed size of any single object, and the shipped size defaults are lower than before. These apply only to deployments that omit the keys — operators who relied on the previous 256 MiB / 100 MiB behaviour should set the old values explicitly when upgrading. (#532)
  • Forwarded-header trust is now an explicit setting. server.trust-forwarded-headers (default true) gates the forwarded-header filter. The default keeps existing ingress deployments working unchanged, but set it deliberately — when on, the listener must be reachable only through the ingress that sets the headers. See https://rbc.github.io/fogwall/configuration/server.html (#587, #635)
  • Dashboard API mutations are now default-deny. Every POST/PUT/PATCH/DELETE under /api requires ROLE_ADMIN unless it is an explicit user-facing exception (own profile, push review, issues, OAuth links). Reads are unchanged. Custom integrations that called a mutating endpoint as a non-admin will now get a 403. (#647)
  • Controls that cannot run now fail closed. Malformed pushes, a validation control whose dependency is unwired, and a secret scan whose objects cannot be resolved now block the push instead of silently passing; admin self-approval whose entitlement cannot be verified is rejected. Correctly-wired deployments see no change. (#532, #547, #558, #643)
  • Database migrations V15, V16 and V17 apply automatically on startup (SCM API entities, SCM token/login cache, SCM API merge records). No action required.

New features

  • Contribution lifecycle through the SCM API proxy. Open, edit, comment on, close and merge pull/merge requests and issues via gh, glab, tea and fj routed through fogwall, with the same content inspection applied to outbound PR/MR and comment bodies and a full audit record of every mutation. Enabled per provider under scm-api. See https://rbc.github.io/fogwall/configuration/scm-api.html and https://rbc.github.io/fogwall/admin/scm-api.html (#264, #565, #578, #606, #619)
  • SCM OAuth account linking with strict identity mode. Link proxy users to their GitHub, GitLab or Forgejo/Gitea accounts; in strict mode a push identity resolves only from OAuth-imported SSH keys and the push record names the account the token actually belongs to. See https://rbc.github.io/fogwall/configuration/scm-oauth.html (#40, #380, #528, #575, #599, #603)
  • PROPOSE and MAINTAIN permission grants. PROPOSE allows opening PRs/MRs, issues and comments; MAINTAIN bundles push, propose and merge. Both assignable from the dashboard. See https://rbc.github.io/fogwall/configuration/permissions.html (#563, #564, #600, #604, #633)
  • require-validated-head control for contributions. Refuses a PR/MR-create whose head commit has no fogwall push record, keyed on the commit SHA. On by default. (#572, #619)
  • Commit-trailer policy and unified email-match rules. Enforce Signed-off-by and Co-Authored-By trailers and match author/committer/trailer emails through one rule model; annotated tag messages are now content-validated and taggers held to the committer email policy. See https://rbc.github.io/fogwall/configuration/commit-attribution.html (#146, #474, #541, #552)
  • OpenTelemetry observability. Traces, metrics and log correlation across the push and SCM API proxy paths, opt-in via config. See https://rbc.github.io/fogwall/configuration/observability.html (#327, #641, #642, #648)
  • Fetch toggle and configurable clone depth for server mode. Run a push-only gateway by disabling clone/fetch globally or per provider, and set the local mirror clone depth. (#476, #478, #537)
  • Dashboard: admin, setup and inspection. Admin navigation grouped behind a dropdown with a responsive drawer; an in-app developer setup guide that generates git config and remote routing; an admin page to inspect and invalidate the local mirror cache; advanced push-record filters; error toasts with server detail and a per-provider SCM API availability badge; and an audit log of every administrative action with actor, target and outcome. (#98, #288, #340, #475, #548, #555, #585, #607, #626, #627, #628, #634)
  • Runtime build version and commit exposed at runtime and in the dashboard. (#579, #596)

Security

  • Closed an admin self-approval bypass of self-certify. An admin could approve their own push through admin override without holding self-certify, forwarding it end to end in the transparent proxy. Self-review now always runs the self-certify gate; admin override is redefined as break-glass for another user's push only, and a stale unentitled approval demotes to ERROR on re-push. (#643)
  • Default-deny authorization for dashboard API mutations — a newly added mutating endpoint fails closed for non-admins instead of inheriting any-authenticated access. (#647)
  • Secret scanning now reaches quarantined push objects. Since rejected-push objects moved to a quarantine store, gitleaks (which shells out to git) could not resolve the pushed commits and recorded a false PASS; the quarantine object directory is now exposed to the scan, which fails closed if the tip is unresolvable. (#558)
  • Bounded decompressed push size and fail-closed malformed pushes to cap resource use and reject truncated/malformed packs. (#532)
  • Fail closed on missing control dependencies and bound permission-regex matching against pathological patterns. (#547)
  • Stopped leaking configured API-key length via comparison timing, and routed unknown-op request diagnostics through slf4j with Cookie/Proxy-Authorization redaction. (#535)
  • OIDC ID tokens are always fully validated; two authorization read-path bugs affecting config-declared users were fixed (both already fail closed). (#524, #559)

Bug fixes

  • Nested repository paths are preserved — GitLab subgroup paths are no longer truncated to two segments by URL rules and permissions. (#577, #590)
  • Repository paths match case-insensitively in access rules and grants. (#576, #595)
  • Push options are rejected in both proxy modes. (#594)
  • Signed pushes are rejected by name instead of being misreported as multi-branch. (#536)
  • One lifecycle record per push in server mode, not three. (#533)
  • checkTrailers push feedback is consistent with the other validation steps. (#608, #609)
  • Adding a config-declared user to a group no longer 500s. (#631)
  • Abandoned pending pushes expire and are superseded in transparent proxy mode. (#591, #615)

Performance

  • Virtual-thread request handling finished — shared heartbeat scheduler and thread configuration. (#452, #557)
  • Repository-cache concurrency — per-key clone lock, per-repo push serialization, and a server-tuned JGit pack cache. (#556, #561)

Maintenance

  • PMD static analysis with a starter ruleset, constructor injection throughout the dashboard, a canonical PushStepKind identity for hooks and filters, a chain-drift guard test, a captured-fixture UI regression suite, and the guides split into pages published with mdBook. (#543, #549, #560, #586, #612, #613, #637, #639)
  • Renamed the contribution surface: "Contributions" in the UI, "SCM API" in config and internals. (#650)

Dependencies

  • Java — grouped dependency updates plus a netty transitive pin at 4.1.137.Final. (#529, #583, #624, #629)
  • Frontend (npm) — grouped dependency updates. (#525, #526, #584)
  • GitHub Actions — grouped action and CodeQL updates. (#522, #523)

Upgrade

  1. Review the config renames above and update your YAML: store-and-forward//push/ → server mode and /server/, SSH consolidated into the provider entry, commit.identity-verification → commit.attribution-policy. The old keys still bind with a deprecation warning, so this can be staged.
  2. If you relied on the previous push size limits, set server.max-object-size-bytes and the size keys explicitly — the shipped defaults changed.
  3. Set server.trust-forwarded-headers deliberately for your ingress topology.
  4. Confirm any non-admin integrations against /api mutating endpoints still have the access they need — mutations are now default-deny.
  5. Migrations V15, V16 and V17 apply automatically on first startup — no manual step.
  6. Pull the new images.

Full Changelog: v1.3.2...1.4.0