fix(reporting): integrate reviewed reporting and signing corrections - #1208
Conversation
Explicit media-buy scopes no longer acquire the all-media selector, and exact revision reads omit absent aggregate defaults. Preserve aggregate defaults and reject explicitly conflicting selectors in generated models and regeneration. Preserve received integral decimal lexemes exactly in reporting feed bindings; reject fractional precision loss before snapshots or continuations change. Keep financial receipt canonicalization and bounded pagination unchanged. Route mounted A2A feed number failures through the ordinary closed preflight. Regress typed production MCP/A2A onboarding, exact zero/503-row reads, principal isolation, and numeric cursor/checkpoint replay across memory and PostgreSQL.
…ation Reject mixed standard/Base64URL characters on the selected webhook Signature token with webhook_signature_header_malformed before key lookup, crypto or replay state. Keep webhook-v1 route selection distinct from request profile 3.2. Preserve legacy pure-alphabet decoder tolerance without treating standard Base64 emission as webhook-profile conformance. Leave Content-Digest and shared request/JWK/JWT decoding unchanged. Exercise the protocol-owned rc.4 vectors, label selection, binary controls, early rejection without side effects, and configured public revocation state.
The webhook signer incorrectly selected the AdCP 3.2 request-signing encoding, emitting padded standard Base64 that conformant webhook receivers reject. Select webhook-v1 Signature encoding internally across public sign_webhook and WebhookSender paths without changing caller options or request profiles. Preserve existing vector-compatible Content-Digest bytes. Its protocol wording discrepancy is separate from the settled webhook Signature encoding contract. Regress both algorithms, selected labels, digest bytes, request profiles and real HTTP callbacks through direct, JWK and PEM sender entry points. Installed Python-to-TypeScript and reverse controls cover the Node 22.12 floor.
Reset the materializer sampling continuation only after a committed account turn moves its durable served_at rank. Keep continuation across lock misses so a busy prefix cannot block later eligible accounts. Cover continuous producer activity, both account orders, size-one pools, more than two busy pages, concurrent workers, commit rollback and fencing. Exercise typed public enrollment, real HTTP/PG delivery, 503-row exact reads, receipts, reconciliation and restart under continuing catch-up load. Include the store regression in installed production distributions.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean integration of six previously-reviewed reporting/signing corrections onto rc6 main.
What I checked:
- No Critical, High, or Medium findings from the reviewer.
high_risk: trueflags only(modified)files (decisioning/dispatch, a2a_server, signing/*). Per the reading of thehigh_riskflag, modified sensitive files with no medium-or-higher findings are presumed safe; row 5 requires a medium finding, and none exist.gated_paths: false, so row 2 does not fire despitereview_decision: REVIEW_REQUIRED.- No no-auto-approve team match (row 7 N/A).
- Source changes fail closed and are covered by new tests: publication-timing clock-regression guards, fail-closed revocation classification, unpadded Base64URL webhook signatures with mixed-alphabet precheck, exact feed-number handling, materializer cursor reset, and generated-model selector validators paired with a matching generator repair.
- The dispatch/CLAUDE.md credential-gate change is documentation-only;
_CREDENTIAL_SHAPED_KEY_SUFFIXESand gate logic are byte-identical — no weakening of the no-credentials-in-ctx_metadata guard.
None of rows 1–8 fire; falls through to row 9 = approve.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean review, no blocking or medium findings.
Checked the decision table top-down:
- Rows 1, 4, 5, 6, 8: no findings at any severity (reviewer reports zero Critical/High/Medium).
- Row 2 (gated paths):
gated_paths: false— does not fire despitereview_decision: REVIEW_REQUIRED. - Row 3 (high-risk deletions):
high_riskis true, but all five high-risk reasons are(modified), none(deleted). - Row 7 (no-auto-approve team): no team match.
- Falls through to row 9 → approve.
The high_risk flag is true only from modifications to decisioning/, server/, and signing/ paths; per the change-kind guidance, modifications with no medium-or-higher findings are presumed safe. The reviewer confirms the changes are spec-faithful and internally consistent: typed reporting selector validators paired with matching generator repair (generated code stays regeneration output), the Scope.all_media_buys wire-fidelity fix, fail-closed revocation-checker classification, consistent webhook 3.1 profile on emit/verify, publication-clock-regression rejection, and a materializer cursor reset scoped to committed turns. _CREDENTIAL_SHAPED_KEY_SUFFIXES is unchanged (doc-only reframing), so the no-credentials gate is intact.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve
Clean delta pass with no critical, high, or medium findings.
What I checked:
- The
Mappingimport infix_reporting_request_selectorsis now gated behind aneeds_mappingflag, added only when the scope class matches (exactly whereMappingis used) — sound conditional-import behavior with added test coverage. - The now-unused import was removed from the regenerated delivery-request model — consistent with generated-code posture.
- Webhook signing tests repointed from rc.4 to rc.6 vectors, verified byte-identical.
- No public-surface/semver break, no import-layering violation, no credential-in-metadata concern, no CI-gate disabling.
High-risk flag: true, but all reasons are (modified) files with no accompanying medium-or-higher finding — presumed safe per the change-kind heuristic. No deletions.
Gate checks: gated_paths is false, so row 2 does not fire despite review_decision: REVIEW_REQUIRED. No no-auto-approve team match. Prior decision was approve, not a sticky escalation. No findings of any tier.
Rows 1–8 do not fire; falls through to row 9 → approve.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean subsequent pass, no blocking or medium findings.
This delta-only review covers a single test file change (tests/conformance/reporting/test_reporting_publication_time.py, +2/-2) bumping the request adcp_version pin 3.2-rc.4→3.2-rc.6 and the validator pin 3.2.0-rc.4→3.2.0-rc.6. Both pins are correct: main now gates on is_adcp_version_at_least "3.2-rc.6" (ADCP_VERSION=3.2.0-rc.6) and the 3.2.0-rc.6/core/reporting-revision.json schema is shipped so the validator resolves. Test-only change — no public surface, schema, generated-code, or credential path touched.
Decision path: no critical/high/medium findings (rows 1, 4, 5, 8 don't fire). gated_paths is false (row 2 n/a). high_risk is true but all high-risk reasons are (modified) with no medium finding on them, and none are (deleted) — rows 3 and 5 don't fire. Prior decision was approve, so row 6 is n/a. No no-auto-approve team match (row 7 n/a). Falls through to row 9 → approve.
Note: high_risk flag is a heuristic on the modified signing/decisioning/server files; the reviewer surfaced no concerns there in this delta, so the flag alone does not warrant escalation.
Publication validator correction
Installed production conformance requested an rc4 revision validator that the rc6 package does not ship. This child changes the publication-clock helper's request and validator pins to the shipped rc6 contract. All 30 assertions, historical offline controls, SDK code, packaged schemas, version policy, workflow selectors and budgets remain unchanged.
Current head
8d6eba964b86c209a26df5decfef4f47d1c0a576, treeae7e33d462bde2eb8862000e94479e6d3445b0d0, sole parenta124afd3b72f3fb81e30e40b298222a683e71d5f; base remains940c95e0c2d93758ed334b3edff59cbe933362d4. Child: one file, +2/-2, binary-diff SHA256da32f920940cc03b018761ef0b8dd58084d44b5c7b1a1d18dffe41aeab6c3fd0. Full 34-path composition diff SHA256ef3b9c4831750624c1930c0e8fee809d23b0a9a0e899e2dfbe1844ead2937084.Fresh exact-source Python3.12.14 validation: 11 passed, 11 existing PostgreSQL-URL-absent skips. Ordinary commit hooks passed on the first attempt without changing bytes. Separately, the same candidate test bytes against the retained original CI wheel
d484dfd9fe20f0bad212b2948d0feee41be07a464f783c0f0ef54b22e5df14b9yielded 24/24 real PostgreSQL/HTTP cases on Python3.10.21, and 11 passed/11 driver-route skips in the base probe; the original helper reproduced 4 failures/7 passes/11 skips. That wheel was built at original mergee85285428b859a9abd5a43a3a080dae6d03d9e6f, not this new child. These diagnostics do not qualify a new child distribution. The named revision-validator closure is five documents: four identical, and the revision schema differs only in versioned references; this is no whole-protocol equivalence claim.Parent a124's six original attempt-1 runs are sealed. CI36124859608 remains FAILURE: 39 jobs, 34 success/5 failure. All four installed-production routes failed (base:1053 passed/4 failed/386 skipped; PG:1435 passed/8 failed/0 skipped), and the strict aggregate correctly failed. Their failures, original artifacts, full logs and independently passing controls are retained under seal
1265eeae72e3fe3e78c6790a911b9474e43b0b28833c6656c3afded2c147259d; no original was retried, cancelled or relabelled. New independent review and complete fresh CI/installed controls are pending for this head.Fresh head-specific Gitleaks disposition SHA256
eb84c226c810fcb272e9b4d6caf01a7bfa42893d6871eb433799ac8d7de57bfc: all 34 files and 17 commits/merge-parent additions covered, positive/negative controls passed, 113 public schema/example matches freshly adjudicated with zero unadjudicated matches or confirmed private credentials. This is owner evidence, not a vendor success or policy substitution. No merge, release or complete rollout acceptance is claimed.Retained a124 history and acceptance map
The following evidence belongs to its explicitly named earlier heads; current-head wording inside this retained history refers to a124 or its stated parent. All new-head gates above remain required.
Prior a124 correction and validation
Current head:
a124afd3b72f3fb81e30e40b298222a683e71d5f, tree6d9aa7b80597e806d9cf7fef6cb13eea6f3e702b, sole parentc28907bbadadd83dadfa1e1c1dc2e80694ffabbe. Base remains940c95e0c2d93758ed334b3edff59cbe933362d4.Installed conformance failed to collect because four signing fixtures selected the historical rc4 compliance directory, which is not shipped. The current rc6 directory contains the same 31 webhook vector paths and byte-identical blobs. The child selects those shipped files while retaining historical version/model tests. It also removes the unused generated Mapping import, makes the generator emit it only for the scope model that uses it, and strengthens the generator idempotence/import regression. No schema, signed vector, packaging, workflow, runtime guard or timeout is relaxed.
The seven-file child is +19/-8 (Git binary/abbrev=8 SHA256
6f92f8cd2fd6f982fe2bd2cb9a0cf91d711546fdaf50d962abba9506f11e44f5). The full range remains the same 34 paths, +4644/-72 (SHA256c0e176fdf1aebbb090df81a0c8a54d3a02af22465d199a27f978be4ff872df73).Focused source validation on Python 3.12.14: 94 passed, 0 skipped, including generator/idempotence, scope/exact selector models, signing vectors/emission and a separate real HTTP receiver. Ordinary commit hooks passed without adjustments or bypass. Command:
python -m pytest -q tests/test_reporting_selector_generation.py tests/test_reporting_scope_models.py tests/test_reporting_exact_request_models.py tests/conformance/signing/test_webhook_rc4_vectors.py tests/conformance/signing/test_webhook_signature_emission.py tests/conformance/signing/test_webhook_signature_http.py. This is source validation, not new installed qualification.Parent original CI36118568262 remains 34 success / 5 failure, 39 jobs. The four installed-production routes had two collection errors each and zero executed cases; their strict aggregate correctly failed. Its terminal guard seal
e926b7e56a4a2681595efb57599d3b810df4ae29f44bc4d62d0cd81e5b67b53aand all originals are preserved. The parent source approval and successful controls do not transfer to this child. Fresh independent child review and all 39 CI jobs, four installed routes, complete lifecycle controls, current scanner disposition and final checks are required.Fresh exact-child scan disposition:
1b3bce5150a4ec5d96378ec1078c5702aedf33d232ba43b371419353b1181744; current 34 files and all 16 commit/merge-parent additions independently reconciled, positive/negative controls executed, 113 public schema/example matches source-adjudicated with no unadjudicated match. This is owner evidence, not GitGuardian success or policy acceptance. One finalizer invocation used a system Python without tomllib; the completed scanner outputs were unchanged and finalization then used the existing Python3.12 environment.Typed reporting requests could add incompatible selectors or defaults, numeric cursor binding could change received values, and webhook emission used the wrong Signature encoding. A continuously due account could also exclude newly enrolled accounts, while acquisition-time finality could be published with an earlier revision creation time. This integrates the reviewed corrections with actual rc6 main, preserving main's restatement checkpoints and version policy.
Reviewed parent composition and retained behavior
940c95e0c2d93758ed334b3edff59cbe933362d4(PR1193 merge, tree1185c7483786a4f4583f83b4c09d44ba07ff5248).25e0c7278a19493345975881d1578c76fc64dc1b; original feature base1f953c40d761be71d11fde84c78359ff2074fe7c.1acd02dc2885242976519b483bb363cd350e958b, ordered parents[25e0c727, 940c95e0].c28907bbadadd83dadfa1e1c1dc2e80694ffabbe, treeed191eee6c08a919803fc96dc1bc73894db0178f, sole parent composition.021f4fd3590699250a2eecf7745b420f8f05ea6ca9103bcfeb1dd25891b9f429. Corrective composition-to-head diff: 8 files, +51/-29; SHA256a0a326d1d4ba1e886e4e676aaf07cf9179697744b345117f9dcd807e4154df39.All five component branches and ordinary merge ancestry remain reachable: wire/numeric/webhook
b203bbcf(#1202), runtime progressdba15b6b(#1206), publication/replay26151fc5(#1207), revocation classificationccb7713f(#1205), and fallback hygienefe1a1cbd(#1204). Those verdicts and executions remain attributed to their original objects. This composition requires fresh review and CI.Integration details
The sole textual conflict was in
ReportingProducer.acquire_obligation. The resolution keeps main's unchanged-snapshot early return and both restatement-checkpoint paths. It samples the publication clock after staged reads and the unchanged-snapshot branch, rejects clock regression, commits using that publication instant, and then records the checkpoint using the original dispatch instant. Reversing only that publication delta recovers main's acquisition-method AST exactly; both checkpoint blocks equal main. Immutable replay, finality bounds and changed-content rejection from the feature are retained.The materializer clears its sampling hint only after a successful committed account turn. Main's native timestamp ordering, account/row locking, fences and rollback remain; lock misses retain continuation. The hint remains unsynchronized instance state: correctness is protected by database locking, while concurrent hint races can affect sampling fairness.
Other retained corrections preserve typed scope and exact-read selectors, exact received integral values, webhook Base64URL emission and mixed-alphabet rejection, the documented revocation fetch/parse/freshness classification, and sanitized fallback behavior. Generated-model changes have a matching generator repair; no schema-cache regeneration occurs. The Content-Digest wording discrepancy remains separate. Credential-key screening remains best effort, not a proof that metadata contains no credentials.
The corrective child changes tests only. Five current live-route pins in three harness/test files move from rc4 to rc6, matching the existing packaged default and resolver. Historical offline webhook vectors and the direct legacy-contract tests retain their original versions. Main already rejects the old explicit live pin; no SDK version support or guard is relaxed. Nineteen awaited predicates across five existing files move to ordinary assignments (five outer-await and fourteen whole-predicate forms); inverse AST reconstruction preserves expressions, short circuit, assertion messages and all other logic after accounting for the declared live-pin edit.
All eight schema manifests remain byte-identical to main (1693 entries). SQL, schema cache, version tables, project/dependency metadata and signed compliance inputs are unchanged. Every CI job object equals main: 24 keys expand to 39 jobs, with the strict eleven-result required gate, receipt shard verification, permissions, budgets and coverage floor intact. Only the two inherited pull-request branch-filter additions differ from main's workflows. Current installed-production module selection derives to 63 unique module keys from 46 literal occurrences and 20 glob matches; duplicates are deduplicated. The corrective installed-contract append adds decisioning.dispatch and signing.verifier to the origin/hash map so every changed runtime module is covered, and adds the later revocation boundary file to the installed test selection. The 16 assets remain unchanged. Fresh distribution bytes and actual test counts must be derived again, not inherited.
Local validation and limits
The original normal composition hook attempt stopped during editable build provisioning with ENOSPC. After cleaning only disposable adcp build-cache files, the same normal hooks passed and the composition committed. Both streams are retained. One read-only structural recorder initially selected the wrong checkpoint method name; its zero-match comparison supplies no proof. The corrected exact-name read independently matched both real checkpoint blocks. Neither incident is SDK or CI evidence.
Fresh CI must complete all 39 jobs, the eleven-result gate, complete Python coverage, all installed-production VCS/sdist and base/PG routes, receipt shards, materializer/feed/hardening/production frozen controls, real installed origins and whole job lifecycles. No old four-cell artifact, source-only probe, collection or partial log qualifies this head. The inherited Python 60-minute job / 45-minute coverage step and 80% floor are unchanged. Translator PARTIAL 8 pass / 47 skip remains a bound, not full interoperability.
Historical and standing boundaries
PR1203 remains superseded evidence, not rewritten: its invalid conventional-merge subjects and original failed CI remain unchanged. PR1208's original
25e0c727ancestry replaced those metadata merges without changing their corresponding source trees; that content/history attribution is retained. Earlier component supervisors, unknown original failures, separate complete runs and any partial observations stay on their original objects. No historical failure is waived or relabelled here.Nine rolling release-note boundaries remain open: pre-17ee A, pre-0f34 B, pre-967 C, pre-5487 B1, pre-3fd B2.1, pre-09fd B2.2, pre-2d777 B2.3, pre-e16 hardening and pre-34c production. Historical schema availability is offline support, not live-version advertisement. The 9rLB source half is attributable to merged PR1191 only, with no under-load or closure claim; schema materialization caching is a distinct object. F-SX remains inherited fail-closed with no snapshot-retention promise. Epoch-zero, quarantine and advertisement/readiness non-promotion remain.
Secret scanning is separate: fresh exact-head Gitleaks disposition
6deceb8fd3d1219416f6f9e851585cb6937f0017ffbaf30e7450c1982a4c9d4cis prepared but not yet accepted as a substitute. Root alone may apply standing train policy after authenticating fresh GitGuardian output. Neutral/size-skipped is never clean-scan credit. Genuine CodeQL full output and annotations must be inspected, including any positive alert despite a success conclusion. The documented wildcard/optional-auth/five-B104 exposure remains recorded; no new exposure is waived. The missing literal check/App binding, visible 14/17 inventories and full-protection 403 remain separate, without exclusive-blocker claims.No artifact, release, activation, #1172, #1199 or TypeScript acceptance. Guard #1201 remains draft
d6e7c228and LAST; legacy workflow204238826remains disabled. Final main artifacts must independently retain Pydantic 2.13.0 / MCP 2.0.0 floor support; candidate version metadata is not registry artifact identity.