From e209d63ec8fba7a09a5a1be66f6b5641dea334aa Mon Sep 17 00:00:00 2001 From: qingxinwu <6334674+qingxinwu@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:59:52 -0500 Subject: [PATCH] Add downsampling debug reports section to explainer. (#1020) * Add downsampling debug reports section to explainer. Co-authored-by: Qingxin Wu Co-authored-by: Paul Jensen Co-authored-by: Michael Kleber --- FLEDGE.md | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/FLEDGE.md b/FLEDGE.md index 4eea4b6fd..479bafe7d 100644 --- a/FLEDGE.md +++ b/FLEDGE.md @@ -46,9 +46,10 @@ See [the Protected Audience API specification](https://wicg.github.io/turtledove - [6.2.3 Additional Bid Keys](#623-additional-bid-keys) - [6.3 HTTP Response Headers](#63-http-response-headers) - [6.4 Reporting Additional Bid Wins](#64-reporting-additional-bid-wins) - - [7. Temporary Debugging Extensions](#7-temporary-debugging-extensions) + - [7. Debugging Extensions](#7-debugging-extensions) - [7.1 forDebuggingOnly (fDO) APIs](#71-fdo-apis) - [7.1.1 Post Auction Signals](#711-post-auction-signals) + - [7.1.2 Downsampling](#712-downsampling) - [7.2 deprecatedReplaceInURN()](#72-deprecated-replace-in-urn) @@ -1206,7 +1207,7 @@ All `Ad-Auction-Additional-Bid` response headers are intercepted by the browser For additional bids that win the auction, event-level win reporting is supported, just as it is for bids generated from stored interest groups. However, additional bids have distinct security concerns. The browser can guarantee that bids generated from stored interest groups were, in fact, generated by the buyer's origin, but it cannot provide this same guarantee for additional bids. An additional bid can only win if none of the negative interest groups specified by the additional bid are present on the user's device, and so the signature validation described above in section [6.2.3 Additional Bid Keys](#623-additional-bid-keys) also can't help with this. To ensure that buyers understand that they're being asked to report on an additional bid, which cannot be verified having been generated by the buyer's origin, the reporting for additional bids is done by calling reporting functions with a slightly different name. Instead of `reportWin()`, the browser instead calls a function named `reportAdditionalBidWin()`to report a winning additional bid. -### 7. Temporary Debugging Extensions +### 7. Debugging Extensions #### 7.1 forDebuggingOnly (fDO) APIs @@ -1217,8 +1218,8 @@ If the bid being generated or scored loses the auction, the URL will be fetched. generateBid(interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, browserSignals, directFromSellerSignals) { … - forDebuggingOnly.reportAdAuctionLoss(“https://buyer.com/debug_loss_report”); - forDebuggingOnly.reportAdAuctionWin(“https://buyer.com/debug_win_report?winningBid={winningBid}”); + forDebuggingOnly.reportAdAuctionLoss("https://buyer.com/debug_loss_report"); + forDebuggingOnly.reportAdAuctionWin("https://buyer.com/debug_win_report?winningBid={winningBid}"); ``` @@ -1228,19 +1229,20 @@ In a multi-seller auction, the following forDebuggingOnly win reports may be sen * forDebuggingOnly *win* report from `scoreAd()` of the top-level seller when scoring the bid from the component auction that wins the whole auction. * forDebuggingOnly *loss* report from all other `generateBid()` and `scoreAd()` invocations. +In order to accomplish our dual goals of helping with adoption and preserving user privacy, we plan to keep the forDebuggingOnly APIs available post third-party cookie deprecation, albeit in a heavily downsampled fashion (as described in [section 7.1.2](#712-downsampling)) to address the re-identification risk. While third-party cookies are available, they will remain unsampled to help with adoption, and instead will have a label, exposed in `generateBid()`'s `browserSignals.forDebuggingOnlyInCooldownOrLockout`, to indicate whether the particular report would have been downsampled. ##### 7.1.1 Post Auction Signals A post auction signal is a signal which is only available after the auction completes, such as the highest scoring other bid. The forDebuggingOnly APIs support the text placeholders below, which will be replaced with the corresponding value from the auction when found in the reporting URL's query parameters. -* “${winningBid}” - The value of the winning bid. In component auctions, this value comes from the component auction and not the top-level auction. -* “${winningBidCurrency}” - If the auction has a `sellerCurrency` configured, this will be its currency tag; otherwise it is `'???'` to denote that it's in the bidder's original currency. -* “${madeWinningBid}” - A [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) value representing whether the owner of this interest group made the winning bid, either via this interest group, or another interest group with the same owner. In component auctions, this value comes from the component auction and not the top-level auction. -* “${highestScoringOtherBid}” - The value of the bid that was scored as second highest by the seller’s scoreAd script. Note that this may not be the second highest bid value, since scores and bids may be independent. This value comes from and is only reported in component auctions but not top-level auctions, and is not reported to losing bidders. -* “${highestScoringOtherBidCurrency}” - The currency `highestScoringOtherBid` is in. If the auction has a `sellerCurrency` configured, this will be its currency tag; otherwise it is `'???'` to denote that it's in the bidder's original currency. -* “${madeHighestScoringOtherBid}” - A [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) value representing whether the owner of this interest group made the ${highestScoringOtherBid} bid, either via this interest group, or another interest group with the same owner. This value comes from and is only reported in component auctions but not top-level auctions, and is not reported to losing bidders. If there’s a tie for ${highestScoringOtherBid} from more than one owner, this is false for all. -* “${topLevelWinningBid}” - The value of the bid that won the top-level auction. This value is only reported to component sellers. -* “${topLevelWinningBidCurrency}” - The currency `topLevelWinningBid` is in. +* "${winningBid}" - The value of the winning bid. In component auctions, this value comes from the component auction and not the top-level auction. +* "${winningBidCurrency}" - If the auction has a `sellerCurrency` configured, this will be its currency tag; otherwise it is `'???'` to denote that it's in the bidder's original currency. +* "${madeWinningBid}" - A [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) value representing whether the owner of this interest group made the winning bid, either via this interest group, or another interest group with the same owner. In component auctions, this value comes from the component auction and not the top-level auction. +* "${highestScoringOtherBid}" - The value of the bid that was scored as second highest by the seller’s scoreAd script. Note that this may not be the second highest bid value, since scores and bids may be independent. This value comes from and is only reported in component auctions but not top-level auctions, and is not reported to losing bidders. +* "${highestScoringOtherBidCurrency}" - The currency `highestScoringOtherBid` is in. If the auction has a `sellerCurrency` configured, this will be its currency tag; otherwise it is `'???'` to denote that it's in the bidder's original currency. +* "${madeHighestScoringOtherBid}" - A [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) value representing whether the owner of this interest group made the ${highestScoringOtherBid} bid, either via this interest group, or another interest group with the same owner. This value comes from and is only reported in component auctions but not top-level auctions, and is not reported to losing bidders. If there’s a tie for ${highestScoringOtherBid} from more than one owner, this is false for all. +* "${topLevelWinningBid}" - The value of the bid that won the top-level auction. This value is only reported to component sellers. +* "${topLevelWinningBidCurrency}" - The currency `topLevelWinningBid` is in. If the top-level auction has a `sellerCurrency` configured, this will be its currency tag; otherwise it is `'???'` to denote that it's in whatever currency the component auction made the bid in. * `${rejectReason}` - The seller can optionally add a `rejectReason` field to its `scoreAd()` return object to convey to the bidder a more detailed reason why the bid was rejected. A component auction's bidders only get reject reasons from its component seller, but not reject reasons from the top-level seller. The reject reason returned by `scoreAd()` must be one of: * "not-available", which is the default value, when a bid @@ -1255,6 +1257,20 @@ If the top-level auction has a `sellerCurrency` configured, this will be its cur * "language-exclusions" * "category-exclusions" +#### 7.1.2 Downsampling + +This design has three main goals: +* Prevent sending fDO reports very often to protect user privacy: + * Only sending reports 1/1000 times the forDebuggingOnly API is called, and + * If a report is sent, "lock-out" all adtechs out of sending a report for 3 years, and + * If an adtech calls the API, put them in a "cool-down" period where calls to the API by that given adtech are not able to send reports. +* Prevent one adtech from substantially compromising a different adtech's access to debugging information. The "cooldown" period means that any particular adtech can only cause a very small fraction of people to send debug reports and be removed from the potential debugging pool. +* Prevent adtechs who accidentally (e.g. due to a bug in their code) call the API repeatedly for all users, from locking themselves out of sending any more reports for years. This is accomplished by 90% of the time putting that adtech in a 2 week cooldown period, and only 10% of the time putting that adtech in a 1 year cooldown period. + +See [issue 632](https://github.com/WICG/turtledove/issues/632) for more information. + +Both `generateBid()` and `scoreAd()`’s `browserSignals` have a new boolean field `forDebuggingOnlyInCooldownOrLockout`. It’s true when the API is in the global "lock-out" period, or when this particular buyer or seller, respectively, is in "cool-down" period. + #### 7.2 navigator.deprecatedReplaceInURN() To help with ease of adoption, [until at least 2026](https://github.com/WICG/turtledove/issues/286#issuecomment-1682842636) Protected Audience will support the `navigator.deprecatedReplaceInURN()` API. It takes two parameters: