Fix #347: push guardrails #357

Merged
crueber merged 1 commit from fix/issue-347 into main 2026-09-12 00:47:04 +00:00
Owner

Repo-scoped write check at receive-pack dispatch on BOTH transports (SSH exec gate + HTTP handler) via one shared rule: owner (incl. slug-namespace self mirrored from #346) / org-attached / explicitly bound / admin, else deny (anon 401, foreign 403 naming the repo, probe errors 503).

  • identity.CheckPush: P6 minus the host-write grant (flags stripped); CheckCreateOwner reused verbatim for auto-create (no fork, per the #346 reuse contract).
  • SSH: exec host-write pre-check removed (the hole); SSHReceivePack takes the full sshd.Principal; 17_ssh.md S3 constraint honored (flags stay unset on the pipeline principal). git argv unchanged (law 2).
  • HTTP: discovery + body (direct + broker-fallback) gated via the PushGate seam; nil gate keeps legacy behavior.
  • Tests: identity matrix, server HTTP/SSH matrix, auto-create admitted/denied, probe-error 503, legacy fallback; real-git e2e on both transports; -race; coverage (identity 97.2, sshd 96.5, server 98.3); push-budget test wires the live gate and passes unmodified (auth-none short-circuits to zero reads); repo-wide fast tier + internal/e2e green (only pre-existing TestUIAssetConcepts failure, also red on main).
  • Docs: 06 S4.4 + decision, 17.7, 01 S5.3 + decision.

Closes #347.

Repo-scoped write check at receive-pack dispatch on BOTH transports (SSH exec gate + HTTP handler) via one shared rule: owner (incl. slug-namespace self mirrored from #346) / org-attached / explicitly bound / admin, else deny (anon 401, foreign 403 naming the repo, probe errors 503). - identity.CheckPush: P6 minus the host-write grant (flags stripped); CheckCreateOwner reused verbatim for auto-create (no fork, per the #346 reuse contract). - SSH: exec host-write pre-check removed (the hole); SSHReceivePack takes the full sshd.Principal; 17_ssh.md S3 constraint honored (flags stay unset on the pipeline principal). git argv unchanged (law 2). - HTTP: discovery + body (direct + broker-fallback) gated via the PushGate seam; nil gate keeps legacy behavior. - Tests: identity matrix, server HTTP/SSH matrix, auto-create admitted/denied, probe-error 503, legacy fallback; real-git e2e on both transports; -race; coverage (identity 97.2, sshd 96.5, server 98.3); push-budget test wires the live gate and passes unmodified (auth-none short-circuits to zero reads); repo-wide fast tier + internal/e2e green (only pre-existing TestUIAssetConcepts failure, also red on main). - Docs: 06 S4.4 + decision, 17.7, 01 S5.3 + decision. Closes #347.
Shared rule: owner (incl. slug-namespace self, mirrored from #346) /
owning-org-attached / explicitly bound / host admin, else deny (anon
401, foreign 403 naming the repo, probe errors 503). identity.CheckPush
strips the host write flag (P6 minus step-3 grant); auto-create gates the
owner segment through CheckCreateOwner verbatim (no fork, per the #346
reuse contract).

SSH: exec host-write pre-check removed (the hole); Transport
SSHReceivePack now takes the full sshd.Principal and the server gates
repo-scoped after sshGate. 17_ssh.md S3 constraint honored (Write/Admin
stay unset on the pipeline principal). HTTP: discovery + body
(direct/broker-fallback) gated via the PushGate seam; nil gate keeps
legacy behavior. git argv unchanged (law 2).

Tests: identity matrix, server HTTP/SSH matrix + auto-create + probe-503
+ legacy fallback, real-git e2e on both transports; budget test wires the
live gate (auth-none short-circuits to zero reads). Docs: 06 S4.4 +
decision, 17.7, 01 S5.3 + decision.
Sign in to join this conversation.
No description provided.