You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Export the webhook key-purpose accept-set as a named constant instead of an inline literal #1448
webhook_verifier.py builds the webhook key-purpose accept-set as an inline literal, so a
conformant receiver that wants to assert the same set has to restate it — and a restated
literal can be widened undetected.
Measured against 9.0.0b1+prs1435.1415.
Where it is
src/adcp/signing/webhook_verifier.py:179, inside the VerifyOptions the webhook route
builds for verify_request_signature:
That set is exactly what security.mdx step 8 (:1478) and the taxonomy row (:1560) mandate:
the accept-set is {request-signing, webhook-signing}, with webhook-signing deprecated per
:1438 but still required to be accepted. The value is correct — thank you for
adcp-client-python#1018, which is what made it correct. It is just not reachable by name.
grep over adcp/signing/* and adcp/webhooks* finds no exported constant for it, only this
literal and the two single-value ADCP_USE_* names it is built from.
Why that matters to a caller
A seller-side conformance shim that verifies webhooks through verify_request_signature
(rather than verify_webhook_signature) must pass accepted_adcp_uses itself, and today the
only way to match the SDK's own behaviour is to retype the literal:
A restated literal can drift from its source silently, and in the widening direction nothing
catches it. Demonstrated on our side: adding "response-signing" to that restated set left our
whole key-purpose test module green (7/7), because the tests grade the shim's behaviour against
the spec's two values and cannot see a third one the shim also accepts. "response-signing" is
precisely a value :1027 reserves for a different primitive and says MUST NOT be used for
RFC 9421 transport signatures, so that is not a hypothetical widening.
A derivation from the SDK cannot drift from the SDK. A restatement can.
Request
Export the set as a named constant so callers can consume it instead of retyping it — e.g. in adcp/signing/constants.py alongside ADCP_USE_REQUEST / ADCP_USE_WEBHOOK:
#: The key purposes a conformant webhook verifier accepts (security.mdx step 8 / :1560).WEBHOOK_ACCEPTED_ADCP_USES: frozenset[str] =frozenset({ADCP_USE_REQUEST, ADCP_USE_WEBHOOK})
and have webhook_verifier.py:179 use it, so the exported name and the verifier's behaviour are
the same object rather than two copies that agree today.
No behaviour change is being asked for — the set is already right. This is only about making it
nameable, so a receiver asserting the same obligation derives it rather than restating it.
Classification: Enhancement — additive constant export, no behavior change Bucket(s): signing (label gap noted below) Status: ready-to-implement Milestone: omitted — no version target stated
What the experts said:
code-reviewer: non-breaking, correct; add a unit test asserting the constant's value and document the export-scope decision in the PR body
ad-tech-protocol-expert: accept-set {request-signing, webhook-signing} is correct per spec; motivation is technically sound; fix the malformed :1560 docstring reference (use #1560 or a proper RST cross-reference role)
My take: Both experts converge — the change is additive and non-breaking. The inline literal is replaced by a named constant derived from the same two ADCP_USE_* values, so the SDK's own verifier and external callers share a single definition that cannot drift independently.
Implementation scope:
src/adcp/signing/constants.py — add WEBHOOK_ACCEPTED_ADCP_USES: frozenset[str] = frozenset({ADCP_USE_REQUEST, ADCP_USE_WEBHOOK}) and add it to __all__. Fix the proposed docstring: use #1018 / #1560 (plain) rather than the malformed :1560 RST cross-reference.
src/adcp/signing/webhook_verifier.py:179 — replace the inline literal with accepted_adcp_uses=WEBHOOK_ACCEPTED_ADCP_USES, and import the constant. No logic change.
adcp/signing/__init__.py — ADCP_USE_REQUEST and ADCP_USE_WEBHOOK are in constants.__all__ but are not re-exported from the package __init__. Decide explicitly: either add WEBHOOK_ACCEPTED_ADCP_USES (plus the two ADCP_USE_* names for consistency) to __init__.__all__, or leave all three out and note in the PR body that callers should import from adcp.signing.constants directly. Document the decision; do not silently omit it.
tests/signing/test_constants.py (or nearest equivalent) — add a unit test: assert WEBHOOK_ACCEPTED_ADCP_USES == frozenset({ADCP_USE_REQUEST, ADCP_USE_WEBHOOK}) to guard against future drift.
Run pytest on the signing subset, mypy src/adcp/signing/, ruff check ., black --check . before opening the PR.
Non-breaking rationale: Only a new constant is added; no existing public symbol is removed, renamed, or changed in value. The verifier's accepted_adcp_uses argument receives the same frozenset contents as before.
Label gap: No signing label exists in this repo. Bucket is noted in this comment; no label applied for it.
Activity
bokelley commentedon Oct 8, 2026
Triage
Classification: Enhancement — additive constant export, no behavior change
Bucket(s): signing (label gap noted below)
Status: ready-to-implement
Milestone: omitted — no version target stated
What the experts said:
{request-signing, webhook-signing}is correct per spec; motivation is technically sound; fix the malformed:1560docstring reference (use#1560or a proper RST cross-reference role)My take: Both experts converge — the change is additive and non-breaking. The inline literal is replaced by a named constant derived from the same two
ADCP_USE_*values, so the SDK's own verifier and external callers share a single definition that cannot drift independently.Implementation scope:
src/adcp/signing/constants.py— addWEBHOOK_ACCEPTED_ADCP_USES: frozenset[str] = frozenset({ADCP_USE_REQUEST, ADCP_USE_WEBHOOK})and add it to__all__. Fix the proposed docstring: use#1018/#1560(plain) rather than the malformed:1560RST cross-reference.src/adcp/signing/webhook_verifier.py:179— replace the inline literal withaccepted_adcp_uses=WEBHOOK_ACCEPTED_ADCP_USES,and import the constant. No logic change.adcp/signing/__init__.py—ADCP_USE_REQUESTandADCP_USE_WEBHOOKare inconstants.__all__but are not re-exported from the package__init__. Decide explicitly: either addWEBHOOK_ACCEPTED_ADCP_USES(plus the twoADCP_USE_*names for consistency) to__init__.__all__, or leave all three out and note in the PR body that callers should import fromadcp.signing.constantsdirectly. Document the decision; do not silently omit it.tests/signing/test_constants.py(or nearest equivalent) — add a unit test:assert WEBHOOK_ACCEPTED_ADCP_USES == frozenset({ADCP_USE_REQUEST, ADCP_USE_WEBHOOK})to guard against future drift.pyteston the signing subset,mypy src/adcp/signing/,ruff check .,black --check .before opening the PR.Non-breaking rationale: Only a new constant is added; no existing public symbol is removed, renamed, or changed in value. The verifier's
accepted_adcp_usesargument receives the same frozenset contents as before.Label gap: No
signinglabel exists in this repo. Bucket is noted in this comment; no label applied for it.Triaged by Claude Code. Session: https://claude.ai/code/session_01RHMZtjWdRzwCbBuTVU6uUT
Generated by Claude Code