Repository navigation
Conversation
The floor is the seller's negotiation reserve, which the shared Negotiation primitive keeps off the wire, but the catalog still published it: ext.floor_cpm on GET /products, floor_cpm on the ungated MCP list_products, the default floor and PG/PD knobs on the ungated MCP get_config/get_setup_status, floor_price on AuthenticatedPackageView (served to any non-public effective tier, including a body-claimed one on /media-kit/search), and the floor-derived minimum and floor_cpm on AgentCore create_deal_direct. With real ad-server floors served (AI-6), each told a buyer the lowest price the seller would accept. Drop the floor from those responses; the MCP pricing policy is returned only to an operator. Pricing, quotes and negotiation still read floors internally, and deal-level bidfloor is unchanged.
|
Pulled 11d2bbe and checked it against a real server, base (bcc22d4) vs PR. Each leak this closes is there on main and gone here: /products ext.floor_cpm, MCP list_products, and MCP get_config/get_setup_status for callers with no key or a buyer key. An operator key over MCP HTTP still gets the full pricing policy, and local stdio still counts as operator. I also reintroduced each leak one at a time (8 cases, including the threshold in the AgentCore message and an operator gate that never opens), and the new tests fail every time. One surface is still leaking the floor: DiscoveryInquiryFlow (flows/discovery_inquiry_flow.py:167) sets price_info["floor"] = product.floor_cpm for tiers that see exact prices. To reproduce, call POST /discovery with an agency or advertiser buyer key and a pricing query (e.g. "What is the pricing for video?"). The response includes every product's floor, e.g. price: 13.5, floor: 10.0. The field is named "floor", not floor_cpm, so it's easy to miss with a grep. It already leaks on main, but it's the same floor this PR removes from AuthenticatedPackageView, so key holders can still read it. Could you drop that line and add a /discovery case to test_catalog_floor_disclosure.py? On the open question: I'd keep the floor hidden from key-holding buyers too. A key proves who the buyer is, not that they should see the seller's reserve, and exact_price already tells them what they pay. /discovery needs the same treatment for that to hold. Minor: docs/guides/media-kit.md:266 still shows floor_price in the authenticated package response. Everything else held up: buyer-agent doesn't read ext.floor_cpm, and its media-kit client treats floor_price as optional. The full unit suite passes on 3.12. |
DiscoveryInquiryFlow returned each product's floor under the bare key "floor" to any tier that sees exact prices. Drop it (the buyer's price stays), add the bare name to the floor-disclosure sweep, and cover /discovery pricing and catalog answers. Also remove floor_price from the authenticated package example in docs/guides/media-kit.md.
|
Thanks Kishore, confirmed and fixed in |
…oors # Conflicts: # CHANGELOG.md
Kishore-2572
left a comment
There was a problem hiding this comment.
Re-checked 2bec746. /discovery pricing answers (price and cost queries) carry no floor for agency/advertiser keys or a body-claimed tier, live on a real server, and the rest of the sweep from last round is still clean (operator still gets the pricing policy over MCP). Putting the floor line back fails both new /discovery pricing tests. 1849 unit passed, integration green. And thanks for the correction on the query wording — "pricing" alone does fall to the catalog answer. Approving from my side.
Problem
The floor is the seller's negotiation reserve. The shared
Negotiationprimitive keeps it off the wire, and the negotiation routes already strip it (#95). The catalog surfaces still published it. Since #117 serves real ad-server floors, each of these told a buyer the lowest price the seller would accept:GET /products,GET /products/{id}ext.floor_cpmon every productlist_productsfloor_cpmget_config,get_setup_statuspg_floor_multiplier,pd_discount_maxAuthenticatedPackageView(media kit)/media-kit/searchfloor_pricecreate_deal_directfloor_cpmon the booked dealPOST /discoverypricing answersfloor(bare key name)Change
floor_cpmfrom the shared Productext(REST, and AgentCore's product tools, which call REST) and from MCPlist_products.get_config/get_setup_status: the pricing policy fields are returned only to an operator (operator key over HTTP, or local stdio, the same model as the CLI). Everyone else getscurrency.floor_pricefromAuthenticatedPackageView.exact_price, which is what the buyer pays, stays.create_deal_direct: the below-floor rejection no longer states the threshold, and the booked deal no longer carriesfloor_cpm.DiscoveryInquiryFlow: pricing answers no longer includefloor(the buyer'spricestays). Found by @Kishore-2572 in review.docs/guides/media-kit.md: removedfloor_pricefrom the authenticated package example.Unchanged: quotes, the floor clamp (#92) and negotiation still read floors internally, and deal-level auction bid floors (
bidfloor) are still published, since a PA buyer needs them. Theseller_minimum_cpmon the REST below-floor 422 stays: there it is the buyer's own tier price, not the floor.Open question
AuthenticatedPackageView.floor_priceis removed by default. If key-holding buyers should keep seeing the package floor, that's a one-line revert plus one test. Note that this view is chosen by effective tier, not only by key.Testing
tests/unit/test_catalog_floor_disclosure.py(15 tests): each surface is swept for floor field names at any depth, including the barefloor. The 12 leak tests fail onmainand pass here; the other 3 pin what stays (the rest ofext, operator access to the pricing policy, and the/discoverycatalog answer).ruff check src/andruff format --check src/ tests/clean.main,ext.floor_cpmon both product routes,floor_priceon claimed-tier media-kit search, andflooron/discoverypricing answers; on this branch, none.main(26718ae) clients against this branch:OpenDirectClient.list_products,MediaKitClient.get_media_kitandsearch_packagesall parse. The buyer only readsfloor_pricewithdata.get()into an optional field.