Skip to content

feat(protocol)!: adopt the signed AdCP 3.3.0-beta.6 bundle - #1901

Merged
bokelley merged 1 commit into
nextfrom
chore/adopt-adcp-3-3-0-beta-6
Nov 13, 2026
Merged

bokelley merged 1 commit into
nextfrom
chore/adopt-adcp-3-3-0-beta-6

Conversation

@bokelley

@bokelley bokelley commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Adopts the signed AdCP 3.3.0-beta.6 bundle on the SDK 10 / next line, following #1866. It ships as 10.0.0b17; 10.0.0b16 went out with the 3.3.0-beta.5 pin.

Pin

  • schemas/releases/3.3.0-beta.6.json records:
    • Source commit aa94f361d7cd, taken from the Fulcio certificate. The v3.3.0-beta.6 tag (bf4aa6db) is its "Version Packages" child.
    • Bundle sha256 99c0ba47f42c…, 27,719,655 bytes, plus the .sig, .crt and .sha256 sidecars.
  • cosign verify-blob against release.yml@refs/heads/main prints Verified OK.
  • make regenerate-schemas took the audited-pin path: checksum and signing identity verified, no fallback.
  • The types were regenerated from the beta.5 tree, so SCHEMA_DELTAS.md is the full beta.5 → beta.6 delta.
  • The wheel ships the beta.6 cache and _compliance tree. The beta.5 trees stay in the repo as history and are pruned from distributions.

What beta.6 changes, and what the SDK does

Spec change SDK
Withdrawals from deprecated tasks (adcp#8501): the 3.3 additions to get_products, create_media_buy / update_media_buy and the sync_creatives assignments[] row Removed from the generated types. Examples: price_adjustments (PriceAdjustments, PriceAdjustmentsMismatchDetails), include_collections / collections / execution_readiness on get_products (execution readiness moves to list_products), lineage_reason, predecessor_media_buy_id, target_audiences, counting_mechanisms, PackageForecastInput, and start_requires_all_creatives_approved on every package except PackageControl. The control_media_buy start-policy gate (#1872/#1878) stays, because beta.6 keeps the field there. The dead PackageForecastInput forward-compat bridge is removed.
Schemas open within a major (DR-0036) 113 generated models stay closed; the rest now keep unknown keys. Three SDK checks relied on closed schemas and now enforce their rule directly (next section).
Origin-only authorized_agents[].url (adcp#8862) find_authorized_agent_entries, and every adagents verifier that uses it, now lets an entry with root path and no query authorize any agent at that origin. An entry with a path still matches exactly. fetch_publisher_signing_pins applies the same rule, but an exact URL entry still wins.
Installment refinement and per-installment creatives (adcp#8967, #8968) Generated. adcp.negotiation now:
• treats installment_changes as a typed revision;
• gates it on supported_dimensions;
• applies the constraint_unsatisfiable rules to unsatisfied_installment_changes;
• checks each unsatisfied entry repeats a requested change.
remove_media_buy_frequency_cap (pre-existing) also counts as a typed revision now.
Report definitions at contract_version 1.2 (adcp#8971) Generated. The manifest inspector also validates the definition against the pinned schema, so the 1.1 official_correction_mode rule and the 1.2 package_id rule apply. The generated model omits both. The spec's report-definition vectors run through the SDK's validator.
Signed terms bind every member Already the case: compute_terms_digest hashes the raw wire mapping.
HTTPS reporting push (adcp#8793), supported_delivery_types, supports_registry_policy_enforcement, geo labels, card_image_sizes, video containers, UNRECOGNIZED_TERMS Generated. #8793 adds descriptions and one token, so no ledger or storage-contract change.

SDK fixes for opened schemas

  • Reporting delivery scope. The post-generate fixer turned any scope without a known selector into all_media_buys: true. With the scope open, a future {"x": ...} selector would have been widened to every buy. It now keeps an unknown selector as received, refuses a second key (maxProperties: 1), and expands only an empty scope.
  • proposal.created. Its schema is open, but its text still says "identifiers only… cannot inject terms or instructions". WebhookSender.prepare_proposal_created now refuses undeclared keys itself.
  • Receipt history. The result arms opened. Retained results must carry exactly the keys the store writes, or the batch is RECEIPT_HISTORY_CORRUPT.
  • Tests. Tests that relied on a closed object now use one that stays closed, or assert that the unknown key is kept. Examples: open-objects, compact output schemas, targeting overlay error order, macro capabilities, adjustment evidence. sync_principal is now graded by schema parity. Tests that used get_products as a 3.3-only example now use list_products, because beta.6 keeps get_products at its 3.2 shape.

Reporting vectors and storage contract

  • The six vendored reporting-subscription coverage files are byte-identical to the beta.6 bundle's, so SPEC_COMMIT is unchanged. All 138 vectors, 8 offering checks and 3 differential regressions pass.
  • #8797 (the timezone-cutover stub) is not in beta.6.
  • Storage contract unchanged: REPORTING_STORAGE_CONTRACT == STORAGE_CONTRACT == 2, and no ledger column changes.

Not done

  • extend_hold, which predates beta.5: preflight still refuses it, and the finalize checks would fail a successful one.
  • Checking that a partial result's drafts satisfy the installment changes the seller left out.
  • Serving only 1.0/1.1 report definitions to callers pinned below 3.3. The seller chooses its offerings; the SDK doesn't check this.

Breaking

  • The SDK speaks 3.3-beta.6 and no longer accepts 3.3-beta.5. get_supported_adcp_versions() returns 3.0, 3.1, 3.2, 3.3-beta.6, 3.2-rc.7. There is no alias, per the one-beta rule.
  • The #8501 withdrawals remove generated types and fields.
  • Most generated models keep unknown keys instead of refusing them.
  • A 1.1 or 1.2 report definition that breaks its schema conditionals now fails manifest inspection.

All of this is recorded in MIGRATION_v9_to_v10.md and in docs/adcp-3.3-sdk-inventory.md section 16.

Verification

Local, on f6f78f094:

  • make validate-generated: pass. make lint: pass. The pre-commit ruff, mypy and adopter type-check hooks pass.
  • Targeted run, 336 passed: adoption identity, report-definition vectors, public API snapshot, reporting reconciliation and inspector, reporting-subscription parity and beta4 vectors, negotiation, open objects, error codes.
  • Earlier full-suite run on the #8801 dry run (5f891597): 21,990 passed. The only failures were release identity and snapshot values, now filled in, and python -m build timeouts caused by load on this host (average about 160).
  • Full suite on this commit: 22,017 passed. The only error is a python -m build timeout caused by host load (CI runs packaging separately). The one failure was test_targeting_overlay_schema's list of bare advertised fields, which now includes beta.6's geo_value_labels: the generator emits that inline object as its own class, like age_restriction. The fix is folded into f6f78f094.
  • make typecheck-all: mypy, adopter mypy-strict, pyright and the type-ignore contract all pass.
  • First CI run (00e7a88ef): everything passed except the Python matrix, which failed only on that targeting test. That includes Postgres conformance, installed production reporting and the frozen feed.
  • Pre-commit black and bandit were skipped for this commit, as for feat(protocol)!: adopt the signed AdCP 3.3.0-beta.5 bundle #1866. Both flag only code that was already that way on next, and CI runs neither.

BREAKING CHANGE: the SDK no longer advertises or accepts AdCP 3.3-beta.5. get_supported_adcp_versions is 3.0, 3.1, 3.2, 3.3-beta.6 and 3.2-rc.7; an adcp_version pin of 3.3-beta.5 or 3.3.0-beta.5 raises ConfigurationError, and a peer that advertises only 3.3-beta.5 for the 3.3 line negotiates down to 3.2. Re-pin to 3.3-beta.6 or omit the pin. Generated types withdrawn by adcp#8501 are gone, most generated models now keep unknown keys instead of refusing them, and a 1.1 or 1.2 report definition that breaks its schema conditionals now fails manifest inspection with INVALID_CONTRACT.

🤖 Generated with Claude Code

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — clean adoption of the signed AdCP 3.3.0-beta.6 schema bundle.

What I checked:

  • high_risk: true is driven entirely by (added) files under schemas/** (the 3.3.0-beta.6 cache bundle). New files matching a high-risk glob are normal scaffolding/codegen for a schema bump and are not escalation-worthy on the flag alone — nothing existed to break.
  • gated_paths: false, so the deterministic hard approval gate (row 2) does not apply.
  • No no-auto-approve team match (row 7 N/A).
  • Semver signal is correct: commit carries feat(protocol)!: + BREAKING CHANGE: footer with migration notes for the beta.5→beta.6 swap.
  • The five hand-written SDK fixes for now-open schemas are fail-closed (reporting scope, receipt-history arms, inspection revalidation, proposal webhook key rejection).
  • Origin-only agent matching is sound (scheme/trailing-slash normalization, prefix-attack boundary, consistent path == "/" handling).
  • _forward_compat/_ergonomic changes and packaging bumps are consistent and tested; domains/ churn is expected codegen.

Reviewer surfaced no Critical/High/Medium findings. No escalation trigger (no deletions, no medium on a modified sensitive file, no prior escalate). Falls through to row 9.

Pin src/adcp/ADCP_VERSION to 3.3.0-beta.6 from the audited, cosign-verified
release: schemas/releases/3.3.0-beta.6.json, source commit aa94f361d7cd from
the Fulcio certificate (the tag is its Version Packages child), bundle sha256
99c0ba47f42c. Resync the schema cache, packaged compliance inputs and
request-signing vectors through the audited pin, regenerate the types from the
beta.5 tree and the public API snapshot. The wheel ships the beta.6 schemas
and compliance tree; the beta.5 trees stay in the repository as history.

Withdrawals (adcp#8501): the 3.3 additions to the deprecated get_products,
create_media_buy / update_media_buy and the sync_creatives assignments[] row
leave the generated types, among them price_adjustments, execution_readiness
on get_products (moved to list_products), include_collections,
lineage_reason, predecessor_media_buy_id, target_audiences,
counting_mechanisms and start_requires_all_creatives_approved off every
package but PackageControl. The control_media_buy start-policy gate stays;
the dead PackageForecastInput forward-compat bridge is removed.

Schemas open within a major (DR-0036), so three checks no longer lean on a
closed schema: a reporting delivery scope keeps an unknown selector as
received and never widens it to all_media_buys; prepare_proposal_created
refuses undeclared keys, since proposal.created stays identifiers-only; and
receipt history accepts only the keys the store writes.

Spec rules applied in hand-written code: an origin-only
authorized_agents[].url authorizes every agent at that origin (adcp#8862),
in find_authorized_agent_entries and fetch_publisher_signing_pins, where an
exact URL entry still wins; adcp.negotiation treats installment_changes as a
typed, capability-gated revision and its unsatisfied entries under the
constraint_unsatisfiable rules (adcp#8967); the reporting manifest inspector
validates a report definition against the pinned schema, so the 1.1
official_correction_mode and 1.2 package_id rules apply (adcp#8971), and the
spec's report-definition vectors run through the SDK's validator.

The post-generate reporting scope fixer keeps an unknown selector and refuses
a second key, mirroring maxProperties: 1.

BREAKING CHANGE: the SDK no longer advertises or accepts AdCP 3.3-beta.5.
get_supported_adcp_versions is 3.0, 3.1, 3.2, 3.3-beta.6 and 3.2-rc.7; an
adcp_version pin of 3.3-beta.5 or 3.3.0-beta.5 raises ConfigurationError, and
a peer that advertises only 3.3-beta.5 for the 3.3 line negotiates down to
3.2. Re-pin to 3.3-beta.6 or omit the pin. Generated types withdrawn by
adcp#8501 are gone (PriceAdjustments, PriceAdjustmentsMismatchDetails,
PackageForecastInput, AudienceEvidenceTarget and the fields above), most
generated models now keep unknown keys instead of refusing them, and a 1.1 or
1.2 report definition that breaks its schema conditionals now fails manifest
inspection with INVALID_CONTRACT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bokelley
bokelley force-pushed the chore/adopt-adcp-3-3-0-beta-6 branch from 00e7a88 to f6f78f0 Compare November 13, 2026 22:48

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — AdCP 3.3.0-beta.6 bundle adoption.

No blocking findings. Clean reviewer pass with zero critical/high/medium findings.

Decision table walk-through:

  • Row 1 (critical/high): no findings — skip.
  • Row 2 (gated_paths + not APPROVED): gated_paths is false — skip. (Also review_decision is APPROVED.)
  • Row 3 (high_risk + deleted): high_risk is true, but all high_risk_reasons entries are (added) — new schema cache files, normal regeneration scaffolding. No (deleted) entry — skip.
  • Row 4 (medium + data-loss/schema/infra): no findings — skip.
  • Row 5 (high_risk modified + medium): all entries are (added), no (modified), no medium findings — skip.
  • Row 6 (sticky escalate): prior decision was approve, not escalate — skip.
  • Row 7 (no-auto-approve team): no team match — skip.
  • Row 8 (3+ medium): zero medium findings — skip.
  • Row 9: approve.

The high_risk flag fires solely on added schema cache files matching schemas/** — inherently low risk per the change-kind guidance (nothing existed to break). The reviewer confirmed the diff is overwhelmingly regeneration churn paired with the ADCP_VERSION bump, with hand-written changes being deliberate, spec-cited, and test-covered: origin-only authorization is fail-closed, installment_changes verification has new tests, wire.py exact-key tightening and reporting-scope fail-closed improvements are sound, and breaking removals carry the feat(protocol)! marker plus MIGRATION_v9_to_v10.md satisfying the semver-signal gate. No V1 contamination, no credential-in-metadata issue, no CI-gate disabling, no forward-compat union regressions.

@bokelley
bokelley merged commit ce9b30c into next Nov 13, 2026
41 checks passed
@bokelley
bokelley deleted the chore/adopt-adcp-3-3-0-beta-6 branch November 13, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant