July release candidate (DO NOT MERGE) - #919
Draft
ChristianPavilonis wants to merge 361 commits into
Draft
Conversation
…nto rc-july-resolve
…main The navigation-path AuctionObservationContext still took its publisher_domain from the incoming edge Host header, so telemetry rows for initial and SPA navigations were attributed to the edge/staging host while /auction rows and outbound bid requests used the configured publisher domain. Both observation constructors now use settings.publisher.domain. Add handler-level coverage for both navigation paths: the previous regression test called build_auction_request directly and would keep passing if a call site reverted to request_info.host, since both sources are &str. The new tests drive handle_publisher_request and handle_page_bids with a divergent edge host, capture the dispatched AuctionRequest through a recording provider, and assert both the bid request fields and the emitted telemetry rows carry the configured domain. Verified they fail when either the builder argument or the observation argument is reverted.
The #937 squash on main and rc/july's copy of the same change diverged on one line: rc/july renamed MatchedSlotsContext::request_path to request_path_and_query. Keep rc/july's field name — request_path no longer exists on this branch. # Conflicts: # crates/trusted-server-core/src/publisher.rs
…-to-creatives # Conflicts: # crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts # trusted-server.example.toml
HEAD Content-Length describes the corresponding GET representation, not a body that will be buffered. Applying the buffered-response limit to that metadata prevents valid S3 Image Optimizer preflights from reaching their streamed GET request. Resolves: #950
# Conflicts: # crates/trusted-server-adapter-fastly/src/platform.rs # crates/trusted-server-core/src/publisher.rs
…isolation Creative sanitization ran unconditionally on every markup bid, stripping `script`/`object`/`embed`/`form` and friends together with their inner content. For script-based creatives — the majority of programmatic display — that leaves nothing renderable, and the slot goes blank with no error: the leftover markup is usually a tracking pixel, so the ad server reports a successful render. Measured over 291 creative deliveries on a live publisher: a median 43% of bytes removed, 29 creatives reduced by more than 80%, and 20 reduced below 500 bytes. One bidder lost 100% of every creative; another lost 76% across 43 of them. Add `auction.sanitize_creatives` so sanitization can be disabled where creatives render in a foreign-origin frame (the Prebid Universal Creative inside the ad server's iframe), and make both creative controls opt-in: `sanitize_creatives` and `rewrite_creatives` now default to false, so a creative ships exactly as the bidder returned it unless a publisher asks for processing. Removing `allow-same-origin` from the creative iframe sandbox is part of the same change rather than a follow-up. Sanitization was documented as "the primary defense against malicious markup", with the sandbox as defense-in-depth — but the sandbox granted `allow-same-origin` alongside `allow-scripts`, which removes its origin isolation entirely. With sanitization now optional, that pairing would leave creative markup able to reach publisher cookies, storage, and same-origin fetches. The two sibling sandboxes (APS_RENDERER_SANDBOX, ADM_IFRAME_SANDBOX) already omit the token for exactly this reason; this brings the third in line, so the origin boundary no longer depends on an optional transform. Note the default change alters behaviour for deployments that never set `rewrite_creatives`: creative URL rewriting is now off unless enabled explicitly. Verified end to end: creatives pass through byte-for-byte (triplelift 8902 -> 8902, openx 22069 -> 22069, previously 100% and 35% losses), page renders with ads serving and no hydration errors.
Carry bid_id through adserver_mock mediation. The reconstruction restored
nurl, burl, ad_id and the cache fields from the original SSP bid but
hard-coded bid_id to None, so a mediated bid whose only hb_adid source is
the OpenRTB bid id lost it and never rendered — the exact failure this
branch fixes, re-opened on the mediated path. Mediated APS bids were
worse off still: they carry no ad_id or cache_id for the restore to
recover, so they reached the page with no hb_adid at all. The mediation
response is itself OpenRTB, so prefer the mediated bid's own id and fall
back to the original SSP bid's.
Reject blank identity strings before applying the cache_id -> ad_id ->
bid_id precedence. Option::or treats Some("") as present, so a blank
cacheId or adid outranked a valid bid id and emitted an empty hb_adid —
falsey on the page, so GPT skips the targeting key and the render bridge
has nothing to match. Prebid's parse_bid likewise treats an empty
OpenRTB id as absent.
Emit hb_cache_host and hb_cache_path only alongside a real Prebid Cache
UUID. PBS reports the cache url and cacheId independently, so a bid with
coordinates but no UUID pointed the Universal Creative at
?uuid=<non-cache-id>, a guaranteed miss, instead of letting it fall
through to the inline adm.
Warn when the chosen hb_adid exceeds GAM's 40-character targeting value
limit. GAM drops an over-long value, so the creative echoes nothing and
the bridge's equality check never matches. Log rather than truncate: a
truncated id is no longer unique per bid, which is what lets one slot's
render claim another slot's creative.
Brings the PR #996 review fixes onto rc/july. The original fallback commit was already merged; this adds the follow-ups plus two conflict resolutions where rc/july had since moved. hb_adid precedence keeps rc/july's renderer tier and gains blank rejection on every tier, so a bidder emitting an empty cacheId or adid no longer outranks a usable identifier: non_empty(cache_id) -> non_empty(renderer_bid_id) -> non_empty(ad_id) -> non_empty(bid_id) Cache coordinates keep rc/july's placement inside the processed_adm match and gain the cache_id requirement as a second, independent condition: absent a UUID the coordinates would send the Universal Creative to ?uuid=<non-cache-id>. Mediation bid_id precedence is inverted relative to the main-targeted branch, deliberately. On main, APS bids carry no bid_id, so preferring the mediation response's own id was the only way to give them an hb_adid. On rc/july, aps.rs populates bid_id and a typed renderer envelope is minted against it, and build_bid_map derives hb_adid from that pairing — so substituting the mediator's id would key targeting to an id the renderer does not know. The original SSP bid's id therefore wins here, with the mediated id as the fallback for an upstream bid that carried none.
Bring the GPT delivery-evidence and refresh-attribution diagnostics onto the July release branch. rc/july already carried a later evolution of the auction-ID plumbing (PR #922 render tracing, the delivered-winner-slot telemetry, and the APS renderer bridge), so the overlapping Rust and JS changes keep the rc/july implementation and layer the new diagnostics on top of it. Conflict resolutions: - publisher.rs: keep the rc/july `write_bids_to_state` -> delivered winner slots contract and prebuilt page-bids bid map; keep both new tests; update the incoming test provider to the current `ProviderRequestOutcome` trait. - gpt/index.ts: keep the render-trace and APS renderer paths and add the creative request/response/failure diagnostics around them. The attempt is recorded after the APS branch, which is served by the APS universal creative and has no Trusted Server creative response to resolve. - prebid/index.ts: keep the resolved bare-refresh slot list and dispatch it through the diagnostics-aware refresh wrapper. - store.ts: adopt the incoming response-based `slotOnload` correlation. - Drop the pre-squash `gpt_diagnostics_bootstrap.js` and its test, which the upstream #974 squash removed as superseded by server-recognized activation. Verified: cargo fmt, clippy (fastly/axum/cloudflare/cloudflare-wasm/spin-native/ spin-wasm), test-fastly, test-axum, test-cloudflare, test-spin, parity, vitest (812 tests), JS and docs format.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Consolidates the July release-candidate changes for review and integration testing before the individual changes merge to
main.Included pull requests
Already included through
mainPending Review / Merge