Repository navigation
fix(reporting): make the managed seller pass the SDK's own capability validation - #1779
Conversation
The producer row-upload test stamps its worker lease with the settling harness clock, fixed at 2026-11-01T02:10Z, while the row store checks the lease against the database's clock_timestamp. Once the wall clock passed that instant plus the lease, every run failed with STATE_UNAVAILABLE: no live worker lease covers this row upload, on next and on every pull request. The test now runs its turn at the wall clock, so the lease lies in the real future. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit ae15bab)
… validation adcp-client-python#1771: a managed reporting-subscriptions seller advertised capabilities the SDK's own client rejected, and needed undocumented wiring over MCP. The principal block now carries optimistic_concurrency true and lists reporting_destinations only when the seller supplies the destination facts the schema requires with it. supported_versions is advertised when the seller does not state it, so a buyer negotiates the 3.3 line. A reporting task with an authenticated caller but no resolved account, as a plain ToolContext over MCP has, reads the account the request names, behind the subscription grant check. The seller guide lists what the host still supplies: adcp.idempotency, the destination facts, and the context factory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean, well-scoped fix for #1771.
Checked: the security-sensitive _managed_caller fallback reads account_id from the request body but is properly guarded — consumer_id comes from the authenticated context, the grant check runs, and ledger reads stay consumer_id-scoped, so multi-tenant isolation holds; unauthenticated callers re-raise fail-closed. advertise_principal's conditional reporting_destinations and the supported_versions injection are correct and tested against the response schema. No public-API/semver, generated-code, forward-compat, or import-layering surface touched. No credentials routed through ctx_metadata. CI gates remain armed.
No blocking findings. No high-risk paths, no gated paths, no author team gate. Falls through to row 9.
Fixes #1771, found by the cross-SDK interop matrix (adcontextprotocol/adcp#8679). This is an early, standalone PR into
next, because any seller built from the guide hits it.Problem
A seller on the managed path (
ReliableReportingService(subscriptions=SubscriptionOptions(...))) advertised aget_adcp_capabilitiesthat the Python SDK's own client rejects against the 3.3.0-beta.3 schemas. Serving it over MCP also needed wiring the guide never mentions.Fix
adcp.principal.optimistic_concurrency: trueis now always advertised; the principal runtime enforcesexpected_configuration_version.reporting_destinationsis listed only when the seller's block carries the facts the schema then requires:max_reporting_destinations,reporting_destination_offeringsandsuspension_interval_seconds. This matches TS, which adds the section only withprepareReportingDestination.adcp.supported_versionsis advertised on the managed path when the seller doesn't state it (the SDK's served releases, without RCs). Without it, a buyer negotiates down frommajor_versionsand gets "get_principal is unavailable in AdCP 3.1".ToolContextfromserve()) reads the account the request names.consumer_id.adcp.idempotency, a fact only the seller knows;reporting_destinations;context_factory=auth_context_factory.Tests (the #1771 repros)
test_issue_1771_managed_capabilities_pass_the_sdk_response_validation: the managed capabilities, with the seller'sidempotency, validate againstprotocol/get-adcp-capabilities-response.jsonwith zero errors, and include3.3-beta.3insupported_versions.test_issue_1771_status_is_served_to_a_plain_mcp_caller:get_reporting_statusservessubscription_coverageto a plainToolContext(caller_identity=...).reporting_destinations.The managed, service and reliable-reporting suites are green. ruff and mypy are clean.
The reference seller in #1776 (PR 6) carries the same principal fix; this PR lands it on
nextwithout waiting for the stack. It also cherry-picks the row-lease test fix from #1767, so the Postgres job is green.🤖 Generated with Claude Code