Repository navigation
feat(reporting): apply the AdCP 3.3 reporting rules - #1707
Merged
Merged
Conversation
Surface a report definition's source.custody claim on ReportingRevisionVerifier and fail closed on a value outside the enum; the claim stays covered by report_definition_sha256 because the SDK hashes the installed bytes. The test-controller dispatcher now rejects injected property_delivery, installment_delivery and installment_property_delivery rows sent with delivery_date, and rejects them when the store override cannot accept them instead of dropping rows the seller must report verbatim. Pin that rows without impressions are never zero-filled or totalled by the inline source, and that delivery webhooks carrying aggregated_totals are accepted. Document each 3.3 rule and the snapshot compaction plan in the reporting release notes. Refs #1669 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — AdCP 3.3 reporting rules applied cleanly across three surfaces with no blocking or medium findings.
What I checked:
high_risk: trueis driven solely bysrc/adcp/server/test_controller.py (modified)matchingsrc/adcp/server/**. Per the risk model, a modification with no medium-or-higher finding is presumed safe. The reviewer confirmedsimulate_deliverydispatch correctly reads the bound override's real signature viagetattr(store, scenario)+inspect.signature—_LegacyStoreis refused,**kwargsstore passes (test_controller.py:1413-1420) — and refuses undated injected rows rather than silently dropping and reporting success. That satisfies the DR-0032/DR-0033 pathway rule (Refused path, with a test).ReportingRevisionVerifier.custodyfail-closes on malformed claims via_runtime()in__post_init__(verification.py:96, 127-135), covered by the definition digest.- Semver signal
feat(reporting):is correct: additive property, no public export removed/renamed/retyped, no required↔optional flip. - New 488-line test file pins real behavior (control-total omission at tests/test_reporting_33_rules.py:351; digest coverage at :522). The 4 disclosed test failures are documented subprocess-import load flakes on an unchanged path, not validation gaps.
Gates: gated_paths false; no no-auto-approve team match; no prior decision. Decision table rows 1–8 do not fire (no critical/high, no medium, high_risk modification with zero findings) → row 9 approve.
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.
Refs #1669
The SDK does not produce
get_media_buy_deliveryitself. I checked each AdCP 3.3 reporting rule against the SDK code that reads, derives, injects, validates or stores delivery and reporting data, and fixed only the real gaps.impressionsoptional on delivery rowsInlineReportingSourceprojects delivery into rows and control totals._metricsalready omits absent metrics, and_control_totalsskips a metric that some rows lack. New tests pin both. No SDK reader derivescpm,ctr,completion_rateorviewable_rate.totals.aggregated_totalsin delivery webhooksWebhookReceiver,ADCPClient.handle_webhookcomply_test_controllerdispatch ofsimulate_deliveryproperty_delivery,installment_deliveryandinstallment_property_deliverywithINVALID_PARAMSwhen they come withdelivery_date(the arrays are undated). It also rejects them when the store override does not declare the parameter. Before, it dropped those rows and reported success. Docstring updated for injected rows and optionalimpressions.source.custodyon report definitionsReportingRevisionVerifier, which hashes and parses the installed definition bytesReportingRevisionVerifier.custodyproperty. A custody value outside the enum fails construction withUNSUPPORTED_VERIFICATION. The digest already covered the claim because raw bytes are hashed. The reference definition asset is unchanged, so its digest does not move.docs/reporting-release-notes.md.No
adcp-reporting-storagechange was needed. Its row codecs are opaque JCS rows, and itsdefinitioncolumn stores the URI and digest binding, not the definition document.Tests
tests/test_reporting_33_rules.py(new, 22 tests)make lint,make typecheck-all: passpytest tests -n 8 -k "reporting or test_controller or webhook": 4942 passed, 4 failed. All 4 are subprocess import tests (test_lazy_typesx2,test_reporting_staging_reuse,test_reporting_production_public). They pass when re-run on their own, so they appear to be load flakes.tests/test_server_dx.pyandtests/test_account_mode_gate.py: 141 passed.🤖 Generated with Claude Code