Repository navigation
fix(governance): backport crit-marker and alg checks to 8.x - #1581
Merged
Merged
Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean backport of #1539 to release/8.x with no blocking or medium findings.
Checked:
src/adcp/governance.py: the newtogether = (name in claims) == (name in critical) == (name in header)plusheader.get(name, True) is not Truecorrectly rejects the three previously-accepted malformed combinations per security.mdx step 4;type(alg) is not strroutes a non-stringalgtogovernance_token_invalidinstead of raising TypeError. Both changes are strictly stricter — no legitimate token flips to rejected (fail-closed, correct).- Holding back the strict base64url change is the right public-surface call:
b64url_decodeis exported and the change would break padded/legacy input on a minor. - Test-only changes (added
operation_id, thestreamfake, payload-bound idempotency) match existing 8.x SDK behavior now that fastapi/svix install in CI.
Gates: no critical/high findings (row 1 clear), gated_paths false, high_risk false, no no-auto-approve team match, no prior decision, zero medium findings. Falls through to row 9 → approve.
Backport of #1539 to release/8.x. verify_governance_authorization now requires each critical marker, its crit entry, and its claim to appear together with the marker true (security.mdx checklist step 4), and rejects a non-string header alg as governance_token_invalid instead of raising TypeError. The dev extra gains fastapi and svix so the 26 signing tests that skipped on pytest.importorskip run in CI; the tests are updated for the required operation_id, the streaming sender, payload-bound idempotency keys, per-delivery nonces, and the 3.2 content-digest requirement. Strict base64url decoding from #1539 is held: it would reject padded or standard-alphabet input 8.x accepts today. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bokelley
force-pushed
the
claude/issue-1539-8x-governance-crit
branch
from
October 24, 2026 18:49
8d6529f to
90940cc
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean backport of #1539 to release/8.x with no blocking or medium findings.
Checked:
src/adcp/governance.py(sole production change): the non-stringalgguard correctly prevents a TypeError on unhashable JSONalg, now surfacing asgovernance_token_invalid. The critical-marker triad check (together+header.get(name, True) is not True) is a correct fail-closed tightening that matches security.mdx step 4, verified across claim/crit/header presence combinations.- Test additions (operation_id, stream fake, timestamp-pinned dedupe, 3.1-profile digest-off case) align with already-required base signatures; newly armed fastapi/svix dev deps surface previously-skipped modules — CI gates remain armed, nothing disabled.
- Deliberately holding the strict base64url change off the minor is the correct semver call.
No critical/high/medium findings. gated_paths: false, review_decision: APPROVED, no author team gate, high_risk: false. No decision-table trigger fires (rows 1–8), so this falls through to row 9 = approve. Prior decision was also approve; this is consistent.
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.
Summary
Backport of #1539 to
release/8.x.On this line
src/adcp/governance.pywas byte-identical tomainbefore #1539, so the governance fixes apply unchanged:verify_governance_authorizationcompared each claim only with acritentry whose marker istrue. So it accepted a marker orcritentry for a claim the payload doesn't carry: acritentry with afalsemarker, a marker with nocritentry, or afalsemarker alone. The marker, itscritentry and its claim must now appear together, with the markertrue(security.mdx, governance verification checklist step 4: "Verifiers MUST also reject when the critical marker and its corresponding claim do not appear together").alg. A headeralgthat is a JSON list or object raisedTypeError, because the verifier tested it for membership in a set. It is nowgovernance_token_invalid, like the other malformed headers.CI install. The
devextra addsfastapi>=0.100andsvix>=1.0. Every CI job installs.[dev]or.[dev,pg], so the five signing modules that skip onpytest.importorskip("fastapi")now run in CI, along with the svix Standard Webhooks interop test. With them installed, 26 tests failed onrelease/8.x, the same 26 as onmain. The fixes are to the tests, not the SDK, and match #1539:operation_idtosend_mcp(24 tests).streammethod the sender uses.timestamp, because the idempotency key binds the payload. A second body under the same key is a409.WebhookSender.resendexpects).content-digest.None of them revealed an SDK defect on 8.x.
Held: strict base64url decoding
#1539 also made
adcp.signing.crypto.b64url_decodestrict, refusing padding,+//, other characters and non-zero trailing bits. That part is not backported.b64url_decodeis exported, and the strict version would reject padded or standard-alphabet input that 8.x accepts today, including input on theallow_legacy_base64urlfallback path. A key published that way would stop verifying on a minor release.test_jwk_members_are_strict_base64urlfromtest_crypto.py, which only tests that change, is left out too.Tests
tests/test_governance_authorization.py:test_critical_marker_crit_entry_and_claim_appear_together(3 cases) andtest_a_non_string_alg_is_an_invalid_token(2 cases). Each re-signs the accepted governance vector, so only the header check can refuse it.test_a_re_signed_vector_is_acceptedchecks the re-signing helper.tests/conformance/signing+ governance: 970 passed, 2 skipped (psycopg not installed locally).make lintandmake typecheck-allpass.make test: 13053 passed, 2426 skipped, 10 deselected, 1 xfailed (Python 3.12, local; Postgres-backed tests skip without psycopg).🤖 Generated with Claude Code