Skip to content

feat(server): seller helper for wholesale feed versions - #1718

Merged
bokelley merged 1 commit into
mainfrom
claude/issue-1676-wholesale-feed-version-9x
Oct 30, 2026
Merged

bokelley merged 1 commit into
mainfrom
claude/issue-1676-wholesale-feed-version-9x

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Backport of #1706 (merged into next) to SDK 9.x for 9.4.0. #1676 is additive, and the AdCP 3.2 get_products / get_signals schemas have the same wholesale fields, if_wholesale_feed_version / if_pricing_version rules, unchanged: true response requirements and forecast generated_at fields as 3.3.

API (adcp.server)

  • wholesale_feed_version(items, *, cache_scope, ignore=FRESHNESS_FIELDS, extra=None) returns a content token. Each item is RFC 8785 canonical JSON hashed with SHA-256; the token hashes the sorted item digests, so top-level item order doesn't matter. Ignored freshness fields are given as paths. cache_scope is part of the hash.
  • pricing_version(items, *, cache_scope) is an optional separate token for the pricing layer.
  • check_feed_preconditions(request) enforces the rules: either token needs a wholesale read, and if_pricing_version needs if_wholesale_feed_version. A violation raises AdcpError(INVALID_REQUEST, field=...).
  • feed_unchanged(request, *, feed_version, pricing_version=None) says whether the buyer's tokens are current.
  • products_response / signals_response no longer write unchanged: false, and refuse unchanged=True with items or without a version. The schema already rejected both outputs.

Differences from #1706

  • The extra= docstring and doc no longer name the 3.3-only collections / signal_pricing_group_rules.
  • test_model_and_wire_dict_items_give_the_same_token compares a model with its own wire form. SDK 9 dumps unset schema defaults (max_bid: false, *_targeting_allowed: false), so a model and its sparse input dict are different wire payloads, and the token rightly follows the wire.

Tests

tests/test_feed_version.py (60) passes on main, alongside test_server_dx.py and test_feed_mirror.py. black, ruff and mypy are clean on the touched modules.

Refs #1676

🤖 Generated with Claude Code

Backport of #1706 to SDK 9.x (AdCP 3.2), whose get_products / get_signals
wholesale fields, if_wholesale_feed_version / if_pricing_version rules and
unchanged: true response are the same as 3.3's.

adcp.server gains wholesale_feed_version and pricing_version (RFC 8785
canonical, SHA-256, order-independent across items, path-addressed freshness
fields ignored, keyed on cache_scope), check_feed_preconditions (the mode and
pairing rules, INVALID_REQUEST with field) and feed_unchanged.
products_response / signals_response no longer write unchanged: false, and
refuse unchanged=True with items or without wholesale_feed_version, both of
which the schema already rejects.

Differences from #1706: the extra= docs no longer name the 3.3-only
collections / signal_pricing_group_rules, and one test compares a model with
its own wire form, since SDK 9 dumps unset schema defaults.

Refs #1676

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
"check_feed_preconditions",
"feed_unchanged",
"pricing_version",
"wholesale_feed_version",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: Six new public adcp.server exports land here — wholesale_feed_version, pricing_version, check_feed_preconditions, feed_unchanged, FRESHNESS_FIELDS, PRICING_FIELDS — but none appear in AGENTS.md. The repo rule is explicit: a new public export without a matching entry in AGENTS.md's handler/helper reference is a Medium. docs/wholesale-feed-versions.md is thorough, but it is not the agent-consumable surface a coding agent reads. Add a row under DX Helpers (or a short Response Builders note for the unchanged=True path).

@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 — additive seller-side wholesale feed-version helpers (backport of #1706 to SDK 9.x).

The reviewer found exactly one Medium finding and no critical/high findings. Walking the decision table top-down:

  • Row 1 (critical/high): no such findings.
  • Row 2 (gated_paths): gated_paths is false — does not fire despite review_decision=REVIEW_REQUIRED.
  • Row 3 (deleted high-risk path): high-risk reasons are (modified) and (added) only, no deletions.
  • Row 4 (medium + data-loss/schema/infra): the single medium is an AGENTS.md documentation gap (docs/API-surface category), not data-loss/schema/infra — does not fire.
  • Row 5 (high_risk modified + medium): init.py and responses.py are (modified) high-risk files AND there is a medium finding — BUT the medium finding is on src/adcp/server/init.py:381, which IS a modified high-risk file. This row fires.

Correction: Row 5 requires high_risk true (yes), a (modified) reason (yes — init.py and responses.py), AND any medium finding (yes). All three conditions are met → escalate.

Medium findings

  • src/adcp/server/init.py:381 — New adcp.server exports absent from AGENTS.md

This is a documentation-table gap on a modified high-risk-path file, triggering row 5 (escalate).

Medium findings

  • src/adcp/server/init.py:381 — New adcp.server exports absent from AGENTS.md

@bokelley
bokelley merged commit 7088ebf into main Oct 30, 2026
47 checks passed
@bokelley
bokelley deleted the claude/issue-1676-wholesale-feed-version-9x branch October 30, 2026 00:31
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