Skip to content

chore(main): release 9.0.0-beta.4 - #1465

Merged
bokelley merged 2 commits into
mainfrom
release-please--branches--main--components--adcp
Oct 18, 2026
Merged

bokelley merged 2 commits into
mainfrom
release-please--branches--main--components--adcp

Conversation

@aao-ipr-bot

@aao-ipr-bot aao-ipr-bot Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

🤖 I have created a release beep boop

9.0.0-beta.4 (2026-10-18)

⚠ BREAKING CHANGES

  • reporting: row storage tables, provider inputs and locators are renamed to the AdCP names above, REPORTING_ROW_ENCODING_V1 is replaced by REPORTING_ROW_FORMAT_V1 and REPORTING_ROW_ALGORITHM_V1, and {period_date} renders the source timezone date as YYYY-MM-DD instead of the UTC date as yyyy/MM/dd, and a custom key template without {revision_key} is refused unless its binding is read_only. create_schema migrates existing databases; stop older writers first.

Features

  • client: cap agent response size by default (#1504) (d5195a9)
  • identity: add experimental AdCP 3.3 agent identity (#1502) (3961d1c)
  • property-lists: unify resolution and validate seller inventory (#1532) (734bf3a)
  • reporting: add current-revision host reads (#1473) (13ca2c5)
  • reporting: add GCS, S3 and Azure Blob row providers (#1468) (fde127d)
  • reporting: add the shared host change feed and registered consumers (#1472) (b7012e0)
  • reporting: align row storage with AdCP stored names and the period date rule (#1485) (47084e8)
  • reporting: migrate legacy inline rows to verified chunks (#1466) (bf7e3a6)
  • reporting: retire expired periods with tombstones and holds (#1474) (c527b18)
  • reporting: schedule retention in the production worker (#1476) (5c23598)
  • reporting: store revision rows as verified chunks in PostgreSQL (#1464) (54a133e)
  • reporting: sweep abandoned uploads and prune expired row sets (#1469) (e32daba)
  • reporting: write row chunks to object storage with fenced uploads (#1467) (83f62c9)

Bug Fixes

  • protocol: adopt signed AdCP 3.2.4 on SDK 9 beta (#1479) (0ad2a8f)
  • reporting: answer unreadable exact revision reads with SERVICE_UNAVAILABLE (#1471) (623b2c1)
  • reporting: keep feed consumer checkpoints forward-only (#1515) (0de3f57), closes #1509
  • reporting: keep retention moving past stuck work and make it visible (#1482) (4623104)
  • reporting: reject a change page that crossed a concurrent prune (#1516) (73d1261), closes #1508
  • reporting: truncate account feed pages at the first in-flight change and match JS backoff (#1483) (21f4216)
  • server: advertise compact output schemas so discovery is servable (#1507) (d908aaa)
  • server: collect stranded defs, memoize the escape hatch, soften a claim (#1513) (fc285b0), closes #1507
  • types: model macro_resolution_capabilities on Format (#1505) (eb66de8)
  • types: preserve custom targeting validation errors (#1484) (275e520)

Performance Improvements

  • types: reduce canonical creative serialization overhead (#1521) (bde770b)

Reverts

  • move experimental AdCP 3.3 identity from main to next (#1534) (1e6d4b9)

This PR was generated with Release Please. See documentation.

@aao-secretariat

Copy link
Copy Markdown

Ladon does not review bot-authored PRs.

@aao-ipr-bot
aao-ipr-bot Bot force-pushed the release-please--branches--main--components--adcp branch 13 times, most recently from 6cc61e0 to 01bbf24 Compare October 13, 2026 03:12
@aao-ipr-bot
aao-ipr-bot Bot force-pushed the release-please--branches--main--components--adcp branch 7 times, most recently from 6bda3ba to d138462 Compare October 16, 2026 18:03
@aao-ipr-bot
aao-ipr-bot Bot force-pushed the release-please--branches--main--components--adcp branch from aec9a2c to 28c609b Compare October 18, 2026 00:43

Copy link
Copy Markdown
Contributor

Hold this release PR until #1534 merges.

#1534 reverts #1502, the experimental AdCP 3.3 agent identity code, on main, so 9.0.0-beta.4 doesn't ship draft-spec code (#1525). The code stays on next, which releases 10.0.0-alpha.N pre-releases. After #1534 merges, release-please regenerates this PR with the revert in it. Merge this PR after that.

Right after #1534 merges, record the revert on next with the -s ours sequence in #1534's description (also in RELEASING.md, #1535). Otherwise the next main → next sync deletes the identity code from next.

Copy link
Copy Markdown
Contributor

Could #1475 land in this beta? The Embedded Sales Agent (scope3data/embedded-sales-agent#652) is blocked on two things, and beta.4 fixes only one:

Both are needed before ESA can leave 8.1.x. As ESA tracks 8.1.x, any further 8.1.x backport also needs to be present in the 9.0 beta it moves to.

@bokelley bokelley mentioned this pull request Oct 18, 2026
12 of 13 tasks
bokelley added a commit that referenced this pull request Oct 18, 2026
This reverts commit 3961d1c, the squash
merge of #1502, feat(identity): add experimental AdCP 3.3 agent identity.

#1502 added experimental AdCP 3.3 agent identity code written to open
drafts. main releases the 9.x line on AdCP 3.2.x, so the drafts would
ship in 9.0.0-beta.4 (#1465) and every later 9.x release. Per
adcp-client-python#1525, draft-spec work lives on next, which already
carries #1502 and releases 10.0.0-alpha.N pre-releases.

Conflict resolution: src/adcp/client.py. #1532 added the
product_property_policy parameter to ADCPClient and ADCPMultiAgentClient
next to #1502's experimental_agent_identity parameter. The resolution
keeps product_property_policy, its docstrings, its attribute, and its
forwarding to per-agent clients, and removes only the
experimental_agent_identity parameter, docstrings, attribute, and
forwarding. No later main commit uses code that #1502 added.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@aao-ipr-bot
aao-ipr-bot Bot force-pushed the release-please--branches--main--components--adcp branch from 7a90273 to b17c960 Compare October 18, 2026 17:14
@bokelley
bokelley merged commit de6c53b into main Oct 18, 2026
42 checks passed
@bokelley
bokelley deleted the release-please--branches--main--components--adcp branch October 18, 2026 17:36
@aao-ipr-bot

aao-ipr-bot Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Created releases:

🌻

bokelley added a commit that referenced this pull request Oct 20, 2026
… directory (#1543)

* chore(main): release 9.0.0-beta.4 (#1465)

* chore(main): release 9.0.0-beta.4

* chore: normalize prerelease version to PEP 440

---------

Co-authored-by: aao-ipr-bot[bot] <279263549+aao-ipr-bot[bot]@users.noreply.github.com>

* docs(releasing): write the main, release/N.x, and next branch rules (#1535)

Record the branch model from adcp-client-python#1525 in RELEASING.md:
which branch carries which spec line, how fixes move between them
(backports, regular main to next merges, forward-port and backport
labels), how next cuts 10.0.0-alpha.N pre-releases from its own
release-please setup, the one-time procedure that keeps #1502 on next
after main reverts it, and how next merges into main at ratification.
CONTRIBUTING.md points feature branches at the right base.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(governance): require crit markers with their claims, and run the signing tests CI skips (#1539)

* test(webhooks): pass operation_id to send_mcp in the webhook sender tests

operation_id became a required keyword of WebhookSender.send_mcp in
#1066. Twenty-five calls in test_webhook_sender_e2e.py,
test_webhook_sender_alt_auth.py, and test_webhook_sender_from_pem.py
still omitted it, so 24 tests raised TypeError before they reached the
behavior they test. CI doesn't install fastapi, so the modules skip there
and nothing reported it (#1524). Each call now passes operation_id.

* test(webhooks): give the proxy-env test's fake client the stream method the sender calls

Since #1066 the sender posts through client.stream, which bounds the
response body it keeps. The fake httpx.AsyncClient in
test_owned_client_ignores_https_proxy_env still had only post, so the test
failed with AttributeError once the operation_id fix let it run. The fake
now yields its response from stream.

* test(webhooks): retry with the first delivery's timestamp in the dedupe test

An idempotency key binds the payload. test_retry_with_same_idempotency_key_dedupes
called send_mcp twice with the same key and no timestamp, so each call
stamped its own time, the second body differed, and the receiver answered
409 instead of a duplicate 200. send_mcp's docstring names the
conflict. Both calls now pass one timestamp, so the retry repeats the
first body and the receiver dedupes it.

* test(signing): sign the digest-off FastAPI case with the 3.1 profile

Since #1038 the 3.2 signer refuses a non-empty body without
content-digest, as AdCP 3.2 request signing requires. The either-False
case of test_signed_request_verifies_end_to_end asked the 3.2 signer for
exactly that and raised ValueError before it reached the verifier. The
case now signs with the 3.1 profile, where content-digest is optional,
which is what the either policy accepts; the required case still signs
with 3.2.

* test(webhooks): re-sign the retry in the HTTP dedupe test

test_duplicate_retry_dedupes_over_real_http posted the same body twice
with the same Signature and nonce, so the receiver refused the second POST
with 401 webhook_signature_replayed before it reached deduplication. A
sender's retry repeats the body under a fresh signature, as
WebhookSender.resend does. Each POST now carries its own signature, and the
second one gets 200 with duplicate=true.

* ci: install fastapi and svix with the dev extra

Every CI job installs the package with .[dev] or .[dev,pg], and neither
extra resolved fastapi or svix. Five signing test modules skip whole on
pytest.importorskip("fastapi"), and test_standard_webhooks.py skips its
two svix interop tests, so CI never ran them and their failures went
unseen (#1524). The dev extra now carries both packages, so each job
that runs the signing suite runs these files too.

Closes #1524

* fix(governance): require each critical marker, its crit entry, and its claim together

security.mdx checklist step 4 (AdCP 3.2.1 to 3.2.5) requires, for
authorized_commitment, authorized_task, and authorized_payload_hash,
"each boolean protected-header marker, its crit entry, and its payload
claim to appear together", and the unknown-extension rule says verifiers
"MUST also reject when the critical marker and its corresponding claim
do not appear together". verify_governance_authorization compared the
claim only against a crit entry with a true marker, so it accepted a
marker for a claim the payload doesn't carry: a crit entry with a false
marker, a marker with no crit entry, or a false marker alone.

The check now requires the three to be present together, with the
marker true. test_critical_marker_crit_entry_and_claim_appear_together
re-signs the accepted vector with each header, so only the crit check
can refuse it; it failed before this change.

* fix(governance): answer a non-string token alg with governance_token_invalid

verify_governance_authorization tested the header's alg for membership
in a set. A JSON list or object there is unhashable, so the verifier
raised TypeError instead of refusing the token. It now refuses an alg
that isn't a string as governance_token_invalid, the code the other
malformed-header cases get. test_a_non_string_alg_is_an_invalid_token
failed before this change.

* fix(signing): decode base64url strictly

JWS and JWK members are base64url: the RFC 4648 section 5 alphabet with
the padding omitted (RFC 7515 section 2). RFC 4648 section 3.3 says
implementations MUST reject encoded data that contains characters outside
the base alphabet. b64url_decode used the standard library's lenient
decoder, which accepted padding and the standard alphabet's + and /,
dropped other characters, and ignored trailing bits. Verifier step 8
decodes the signer's JWK through public_key_from_jwk, so the request and
webhook verifiers accepted a JWK whose x member had "!!" inserted.

b64url_decode now refuses padding, + and /, and decodes the rest with
base64.b64decode(altchars=b"-_", validate=True), which refuses any other
character. It also refuses non-zero trailing bits (RFC 4648 section 3.5),
so each value has the one spelling b64url_encode produces. Every caller
already handles the ValueError it raises.
test_jwk_members_are_strict_base64url failed before this change.

* feat(identity): verify JWS artifacts on the issuer's Web Bot Auth key directory

Implements specs/agent-identity-3-3.md R4 as amended by
adcontextprotocol/adcp#8299 (WG-approved 2026-10-19). A governance
context, designated-task response signing or rights attestation whose
issuer origin O is listed by the trust record derived from O is verified
with a key from O's key directory: alg EdDSA, kid the JWK thumbprint, no
use/key_ops/adcp_use checks, revocation by O's list. Historical
governance verification uses the governance key archive at O. A trust
record that cannot be read never selects the 3.2 profile; issuers no
trust record lists stay on it.

adcp.signing.jws_artifacts adds select_jws_artifact_profile,
verify_wba_jws_artifact, WbaJwsArtifactVerifier, HttpGovernanceKeyArchive
and compact_jws_from_envelope, reusing TrustRecordEvaluator,
DiscoveredSignerKeys and OriginRevocationChecker.
verify_governance_authorization takes web_bot_auth= and keeps every other
check; verify_historical_governance_context verifies retained tokens
through the archive. Outages on the new path are
governance_jwks_unavailable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(identity): treat any key lookup failure as an outage on the JWS artifact path

A custom key directory or governance key archive that raises anything
other than JwsArtifactError now yields jws_key_unavailable
(governance_jwks_unavailable) instead of escaping the verifier. An archive
entry whose alg is not a string is skipped rather than raising TypeError,
and a key the cached archive lacks is refetched at most every 30 seconds,
so a key rotated into the archive is not reported unknown for a whole
cache period.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: aao-ipr-bot[bot] <279263549+aao-ipr-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Constantine Mirin <konstantin.mirin@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

save_feed_consumer_cursor can move a consumer backward changes_after can return a page that skips pruned changes

1 participant