Skip to content

July release candidate (DO NOT MERGE) - #919

Closed
ChristianPavilonis wants to merge 390 commits into
mainfrom
rc/july
Closed

July release candidate (DO NOT MERGE)#919
ChristianPavilonis wants to merge 390 commits into
mainfrom
rc/july

Conversation

@ChristianPavilonis

@ChristianPavilonis ChristianPavilonis commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

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 main

Moved to August RC #1019

@aram356 aram356 changed the title July release candidate July release candidate (DO NOT MERGE) Jul 16, 2026
@aram356
aram356 marked this pull request as draft July 17, 2026 15:44
prk-Jr and others added 24 commits July 23, 2026 15:11
Introduce query-activated diagnostic sessions, trace identities and telemetry, bounded GPT and Prebid render ownership, creative acknowledgements, and the browser timeline overlay. Add deterministic integration fixtures and coverage across edge adapters and browser render paths.
…-to-creatives"

This reverts commit 58706b4, reversing
changes made to 96fec88.
Introduce query-activated diagnostic sessions, trace identities and telemetry, bounded GPT and Prebid render ownership, creative acknowledgements, and the browser timeline overlay. Add deterministic integration fixtures and coverage across edge adapters and browser render paths.
# Conflicts:
#	crates/trusted-server-adapter-fastly/src/backend.rs
#	crates/trusted-server-adapter-fastly/src/platform.rs
#	crates/trusted-server-core/src/auction/orchestrator.rs
…ping

APS bids are bid-by-reference: interpretResponse sets the renderer descriptor on
the Prebid bid as the custom `trustedServerRenderer` field, and a bidResponse
listener registers it in window.tsjs.apsPrebidRenderers keyed by Prebid's generated
adId so the Universal Creative can later request it.

Prebid normalizes each bid into its own object during addBidResponse and drops
unknown top-level fields, so the custom field can be gone before the bidResponse
listener runs (observed in production: absent as early as bidAccepted). The listener
then saw renderer === undefined and returned without registering, leaving the
registry empty; the Universal Creative's request found nothing and Prebid's default
renderer threw "Missing ad markup or URL" (reason noAd) for every APS bid.

Also stash the descriptor keyed by `requestId` (a first-class field Prebid
preserves) when the bids are built, and have the bidResponse listener fall back to
that stash when the custom field is absent. Additive: the existing field path is
unchanged, so cases where the field survives behave exactly as before; the fallback
engages only when Prebid has stripped it. Bounded map. Adds a unit test that
registers via requestId with the custom field removed.
auction/orchestrator.rs:
- Combined imports (http::Request + std::collections::{HashMap, HashSet}).
- Kept main's post-launch backend-name collision defense and resolved-name
  correlation on both parallel and sequential dispatch, while preserving #918's
  per-provider effective_timeout in the backend_to_provider 4-tuple (declarations
  and read sites already expect the 4th element).
- Took main's test provider fields (configured_timeout_ms / predicted_timeouts)
  and its DivergentBackendProvider; updated a #918 test stub to the merged struct
  shape (configured_timeout_ms: 125 to preserve its capped-launch-timeout assertion).

publisher.rs:
- Advertise the configured publisher_domain in the page URL (main's fix; the edge
  Host must not leak into the bid request per the in-code comment) using #918's
  request_path_and_query field (the field the merged MatchedSlotsContext exposes);
  updated a stale test literal accordingly.

Verified: cargo check (axum) clean; orchestrator + build_auction_request tests pass.
…ping

APS bids are bid-by-reference: interpretResponse sets the renderer descriptor on
the Prebid bid as the custom trustedServerRenderer field, and a bidResponse listener
registers it in window.tsjs.apsPrebidRenderers keyed by Prebid's generated adId.

Prebid drops unknown top-level fields when it normalizes bids during addBidResponse,
so the custom field can be gone before the bidResponse listener runs (observed in
production: absent as early as bidAccepted). The listener then saw renderer ===
undefined and returned without registering; the registry stayed empty, the Universal
Creative's request found nothing, and Prebid's default renderer threw "Missing ad
markup or URL" (reason noAd) for every APS bid.

Also stash the descriptor keyed by requestId (a first-class field Prebid preserves)
when the bids are built, and fall back to it in the bidResponse listener when the
custom field is absent. Additive: the existing field path is unchanged; the fallback
engages only when Prebid has stripped the field. Bounded map. Adds a unit test.
ChristianPavilonis and others added 19 commits August 6, 2026 13:20
# Conflicts:
#	crates/trusted-server-core/src/integrations/datadome.rs
#	crates/trusted-server-core/src/integrations/datadome/protection.rs
#	crates/trusted-server-core/src/publisher.rs
#	docs/guide/integrations/datadome.md
#	docs/superpowers/plans/2026-08-03-datadome-ip-excluded-client-tag.md
#	docs/superpowers/specs/2026-08-03-datadome-ip-excluded-client-tag-design.md
# Conflicts:
#	crates/trusted-server-core/src/integrations/aps.rs
#	crates/trusted-server-js/lib/src/core/render.ts
#	docs/guide/integrations/aps.md
# Conflicts:
#	CHANGELOG.md
#	crates/trusted-server-core/src/auction/endpoints.rs
The winning-bid `hb_auction_id` carried `AuctionRequest.id`, which is
`ts-{ec_id}` whenever an Edge Cookie ID exists. That value reached
`window.tsjs.bids` and the page-bids JSON for every visitor, handing any
script on the page the identifier the `ts-ec` cookie keeps HttpOnly, and
it could not distinguish one auction from the next because it is stable
per visitor.

Mint an unrelated `ts-auc-{uuid}` per auction instead, and emit it only
when the GPT diagnostics integration is enabled, since nothing else
consumes it. `AuctionRequest.id` is unchanged for SSPs.
Keep the operator API read-only: `window.tsjs.gptDiagnostics` now exposes
only snapshot, export, subscribe, show, and hide. The evidence writers
Trusted Server's own modules use move to a separate internal channel,
`window.tsjs.gptDiagnosticsRecorder`, so the documented contract matches
what the object actually offers.

Bound the store's deferred work by retained state rather than refresh
rate. Request-intent evidence now expires lazily when the slot is next
recorded or requested instead of owning a timer per source, which also
removes the WeakRef-absent fallback that strongly retained every marked
slot until expiry. Delivery-boundary notifications share one timer that
re-arms from retained cycles.

Stop reporting a source-agnostic GPT identifier as a reservation. Those
IDs are populated for reservation and backfill alike, so they classify
as `reservation` only alongside an explicit non-backfill fact.

Evict a creative attempt whose cycle rendered empty, so a late markup
response cannot claim a Trusted Server delivery against an empty render,
and label badges from the derived delivery state instead of re-deriving
the precedence rules from raw timestamps.

Also: attribute `refresh(null)`, make the presentation switches
exhaustive, hoist the snapshot out of the subscriber loop so every
subscriber sees one capture, and make the export's attribution fields
required.

Type-check the export contract: the `expectTypeOf` assertions were never
evaluated, and one of them was a genuine error. Scope `test.typecheck`
to the type tests, since a package-wide `tsc --noEmit` still fails on
pre-existing errors elsewhere.

Fix the replacement-after-eviction test, which passed vacuously because
ten open cycles made the final render ambiguous, and cover the paths the
review identified: publisher-refresh malformed input, the association
LRU trim, the out-of-order callback arms, a declined creative attempt,
the Prebid dispatch-context restore arm, and wrapper install ordering.

Correct the operator guide where it contradicted the implementation, and
record the auction-token revision in the design spec.
Conflict in the Prebid refresh handler: main (#965) documented that the
delegated refresh preserves the publisher's original bare form, while
this branch replaced that call with the diagnostics recording plus the
scoped dispatch context. Both hold — `dispatchPrebidRefresh` passes
`slots` and `opts` through unchanged — so the resolution keeps the
diagnostics calls and main's comment, extended to say the wrapper only
scopes the shared context.

Also add `bid_id` to the auction-ID test provider's `Bid` literal, a
field main added in #996 after this branch introduced the provider.
Brings in the PR #997 review fixes: the read-only diagnostics facade
split from the internal recorder channel, lazily expiring request-intent
evidence with one shared delivery-boundary timer, source-agnostic IDs no
longer reported as reservations, the empty-render attempt eviction, and
the scoped type-check gate for the export contract.

The branch also carries a merge of main, whose #965 and #996 arrive here
as squashes of work rc/july already implements more fully. Where the two
sides describe the same feature, rc/july's implementation is kept:

- APS, adserver_mock, auction/types.rs, auction/formats.rs — rc/july's
  OpenRTB provider, renderer-aware bid_id precedence, and typed renderer
  envelope supersede main's versions, which drop fields rc/july needs.
- prebid.rs — rc/july canonicalizes the excluded-suffix list at both the
  startup and build paths already, so main's `load_config` helper adds
  nothing. Main's test is taken instead of rc/july's: it builds from raw
  settings rather than reusing the config `validate_config_for_startup`
  already canonicalized, so it actually exercises the build path.
- prebid/index.ts — a bare refresh that filtered slots must deliver the
  resolved target list, not stay bare, so rc/july's `deliveredSlots`
  behavior and its test expectation both stand.

Three fixes are ported into rc/july's shapes rather than resolved away:

- The EC-derived auction ID reached page JavaScript here too, through
  different plumbing: both collect paths inlined `request.id.as_str()`
  into `write_bids_to_state`, and page-bids passed it to
  `build_bid_map_with_auction_id`. All three now mint a per-auction
  token via `diagnostics_auction_id()`, gated on the diagnostics
  integration being enabled.
- A blank Prebid Cache UUID no longer ships cache coordinates. It loses
  the hb_adid precedence to `adid` or the bid id, so the Universal
  Creative would fetch `?uuid=<non-cache-id>` and miss instead of using
  the inline adm. The gate moves from `is_some()` to `non_empty()`, and
  main's regression test comes along with rc/july's `Bid` fields added.
- The browser-side excluded-suffix list is validated before use. The
  server only de-duplicates it, so an empty suffix matched every ad unit
  path and pulled every slot out of the refresh auction, and a non-array
  value threw inside the publisher's own `refresh()`.

Also collapses a duplicated `hb_auction_id` write in `build_bid_map`
down to one guarded insert, and points the Prebid refresh recorder at
`gptDiagnosticsRecorder` to match the new channel.
# Conflicts:
#	crates/trusted-server-core/src/publisher.rs
#	crates/trusted-server-js/lib/src/core/types.ts
#	crates/trusted-server-js/lib/src/integrations/gpt/index.ts
#	crates/trusted-server-js/lib/src/integrations/gpt_diagnostics/api.ts
#	crates/trusted-server-js/lib/src/integrations/gpt_diagnostics/overlay.ts
#	crates/trusted-server-js/lib/src/integrations/prebid/index.ts
#	crates/trusted-server-js/lib/test/integrations/gpt/ad_init.test.ts
#	crates/trusted-server-js/lib/test/integrations/gpt_diagnostics/types.test.ts
#	crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts
#	docs/guide/integrations/gpt-diagnostics.md
Resolves conflicts from the squash-merges of #918 (APS OpenRTB), #966
(duplicate GPT slot requests), and #956 (opt-in creative sanitization)
against the rc/july copies of the same work plus rc-only follow-ups.

Resolution decisions:
- Adopt main's final versions wherever both sides carried the same PR
  content (markUsed lifecycle, load_config refactor, tiered slot-element
  resolver, sanitize-opt-in creative pipeline, canonical timeout tests).
- Keep rc-only work main does not have: APS PUC collapsed-shell resize
  and reusable server APS descriptors (re-answering PUC requests),
  render tracing (#922), DataDome cache privacy, publisher cache-control
  (#1007), decoupled-shim spec loader (#988), query-aware SPA route
  identity for page bids.
- Drop main's one-shot server-APS replay-guard test: rc's reusable
  descriptor behavior is asserted by the ported rc test instead.
- Add the divToSlotId registry tier to slot-frame resolution so the
  adInit-resolved div wins for ambiguous responsive prefixes.
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Fixed
Absorbs the #963 squash (APS renderer meta carrier). rc/july already
carried this work; keep the rc-only render-trace meta fields and adopt
main's core-bundle load in the APS renderer spec helper.
The textual merges double-inserted blocks that compiled silently:

- gpt_bootstrap.js carried two full copies of the slot-handoff helper
  section; JS shadowing made the stale rc copy dead code. The file now
  matches main exactly.
- types.ts declared GptSlotHandoff twice (TS declaration merging hid it).
- The #963 squash on main added its own copies of the APS registry tests
  that had been ported into prebid/index.test.ts and ad_init.test.ts,
  leaving seven tests duplicated under identical titles; the copies
  matching main are kept.
- Restore main's comment wording in core/render.ts.
Comment thread crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts Fixed
Comment thread crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts Fixed
The requestId-strip APS registry test and the hb_adid omission test
existed under rc names alongside main's renamed copies of the same
bodies; keep main's versions.
- prebid/index.test.ts: drop duplicated vi.hoisted destructure keys,
  duplicated mockPbjs properties, and a doubled fixture import.
- request.test.ts: type AddAdUnitsArg from the imported AdUnit instead
  of a Parameters<> lookup on a symbol that is only imported inside
  test bodies.
Absorbs the #998 squash (preserve APS renderer handshake behavior) and
aligns rc/july with its landed form:

- Adopt main's render bridge: slotIdForMessageSource source resolution,
  one-shot consumedServerApsBySlot guard, no renderer-path diagnostics,
  and the window-postMessage renderer handshake (dropping the rc-side
  MessagePort handshake, frame-based source resolution, and collapsed
  1x1 shell resize that the landed PR did not take).
- Keep rc-only work orthogonal to #998: render tracing (#922) in the
  slotRenderEnded and bridge inline/cache paths, the query-aware SPA
  route identity, and the renderer shell clipping fixes (overflow:hidden
  document styling and display:block on the renderer frame), re-ported
  onto main's handshake.
- Take main's ad_init and APS renderer tests wholesale.
The PUC dynamic-renderer resize spec asserted the collapsed 1x1 shell
resize that the landed #998 does not include; the spec, its
prebid-universal-creative devDependency, and the lockfile entry now
match main.
@aram356

aram356 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Replaced by #1019

@aram356 aram356 closed this Aug 12, 2026
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.

4 participants