Repository navigation
feat(git)!: Tell misconfiguration apart from bad grants and transient failures - #171
Merged
Merged
Conversation
Porting Sentry and Seer to the Ed25519 grants showed that neither could tell its own misconfiguration from a bad or oversized grant. A bad key raised plain ValueError or TypeError from the same calls that parse untrusted grants. So Sentry called require_public_keys before every verify_grant and caught both types, and Seer called public_key_of only to check its key at startup. GitGrantKeyError now covers every bad-key case on both sides. It's a ValueError, so existing handlers still catch it, but not an SCMCodedError: a bad key is the server's fault, and a coded error would be answered as a refused grant. The oversized-grant error stays a plain ValueError. require_private_key gives signers the startup check that verifiers already had, and generate_private_key replaces the cryptography calls that bin/git-server, the tests and both consumers' tests each copied. The key-material tests now check each base64 line on its own. Before, they joined the lines into one string, which never matched a multi-line key (RSA, EC, Ed448), so those cases passed without checking anything. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vaind
marked this pull request as ready for review
October 30, 2026 07:52
A remote that isn't https, a host the relay's adapter refuses, and a TLS certificate Sentry doesn't trust are misconfigurations of the integration or the host, and no retry fixes them. As 502s, Seer's checkout retried each one for about a minute before failing, because it retries a 502 or a 503. As 500s, it fails at once, like the other misconfigurations already mapped to 500. The 502s that stay mean the provider failed or Sentry couldn't get or use a token. 503 and 504 still mean a retry can succeed. GitServer already answered a coded error from get_token by its code, but nothing said so. Sentry now relies on it to turn an unreachable control silo into a 503 that Seer retries, so GetToken and GitServer document it and a test pins it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Right after "a client closing its request is not reported", "answered the same way" read as "not reported either". GitServer does report it, and the test checks that. Also drops a test comment about the HS256 behavior, which the 3.0.0 release notes record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mujacica
approved these changes
Oct 30, 2026
3 tasks done
vaind
pushed a commit
to getsentry/sentry
that referenced
this pull request
Oct 30, 2026
Bumps `sentry-scm` from 2.0.0 to [3.0.0](https://github.com/getsentry/scm-platform/releases/tag/3.0.0). The lockfile also picks up `cryptography` as a direct dependency of sentry-scm; the locked `cryptography` (50.0.0) and `pyjwt` (2.15.0) already meet 3.0.0's new floors (`>=48.0.1`, `>=2.14.0`). No code changes are needed on master. The 3.0.0 breaking changes are all in `scm.git` (Ed25519 grants, `GitServer(public_keys=...)`, `get_token` returning an `scm.Secret`, `GitRelay(map_error=...)`, `GitGrantKeyError`, and the 502 → 500 status changes), and nothing on master uses `scm.git` yet. The only user is the git endpoint in #128444, which is already written against 3.0.0 and only needs this bump to pass CI. The one other change that touches master's code, getsentry/scm-platform#169, is backward compatible for `RpcServer`'s callers. Landing this first lets #128444 drop its "bump sentry-scm" checklist item after a rebase. If you'd rather keep the bump inside #128444, close this one. This PR needs no deploy config or secrets. `SCM_GIT_GRANT_PUBLIC_KEYS` (Ed25519 public keys as PEM, matching Seer's signing key) comes in with #128444. Upstream: getsentry/scm-platform#168, getsentry/scm-platform#170, getsentry/scm-platform#171 Refs CW-2222 <!-- junior-request-attribution:start --> via **Ivan Dlugos**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A19a84388325b8be5736899297f85ece4 --> -- [View Session](https://junior-prod.sentry.dev/conversations/agent%3A19a84388325b8be5736899297f85ece4) [[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A19a84388325b8be5736899297f85ece4/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Porting Sentry and Seer to the Ed25519 grants from #170 found gaps that should be fixed before 3.0.0:
ValueError/TypeErrorfrom the same calls that parse untrusted grants, so callers couldn't tell their own misconfiguration apart from a bad or oversized grant.bin/git-serverand every test suite copied the samecryptographycalls.Follow-up to #170 (CW-2334).
Approach
scm.errors.GitGrantKeyError(SCMError, ValueError)for every bad key, on both sides. It isn't anSCMCodedError, because a bad key is the server's fault:GitServerraises it from its constructor rather than answering requests with a 403. An oversized grant still raises a plainValueError.require_private_key(Secret) -> Secret, the signer's counterpart torequire_public_keys, to check a key at startup.generate_private_key() -> Secret, which replaces the copiedcryptographycalls inbin/git-serverandmake_key_pair.GitServeranswersgit_remote_not_https,git_remote_refusedandresource_certificate_invalidwith a 500 instead of a 502. The integration or host is misconfigured, so no retry helps. 502 still means the provider or the token failed; 503 and 504 still mean a retry can succeed.GetTokenandGitServernow document thatget_tokenmay raise a coded error, whichGitServeranswers by its code. Sentry relies on this to answer an unreachable control silo with a 503.Not included, as decided: a public
key_id(), or reporting which key matched a grant.Release notes
Craft uses this section for the changelog in place of the title. The last item covers earlier PRs whose titles don't show a breaking change.
Changelog Entry
GitGrantKeyErrorfor a missing or unusable git grant key, so callers can tell their own misconfiguration apart from a bad grantValueError, not anSCMCodedError. A public key that isn't a string used to raiseTypeError.verify_grant([], token)raises it. 2.x refused the grant withGitInvalidGrant(a 403 fromGitServer).require_private_keyto check a signing key at startup, andgenerate_private_keyto make one for testsget_tokenmay raise a coded error, whichGitServeranswers by its code, e.g.ResourceServiceUnavailableas a 503GitServer'sget_tokenmust return anscm.Secret, or every relayed request fails withTypeError(#167).RestrictedIPAddresstoGitRemoteRefusedwithGitRelay(map_error=...), its refusal of internal addresses changes from a 503 to a 500 (#168).Tests
Each bad-key case raises
GitGrantKeyErroron both sides, and no message quotes the key. That check also now works for multi-line keys: it used to join the lines, so it never matched RSA, EC or Ed448 keys. A generated key round-trips throughsign_grant,public_key_ofandverify_grant. NewGitServertests cover the three 500s and a coded and an uncoded error fromget_token. The suite, ruff, mypy and prek pass, and I smoke-testedbin/git-server's key loading.🤖 Generated with Claude Code