Skip to content

Add configuration-driven OpenRTB auction providers - #1016

Open
ChristianPavilonis wants to merge 6 commits into
mainfrom
docs/config-first-auction-provider-spec
Open

Add configuration-driven OpenRTB auction providers#1016
ChristianPavilonis wants to merge 6 commits into
mainfrom
docs/config-first-auction-provider-spec

Conversation

@ChristianPavilonis

@ChristianPavilonis ChristianPavilonis commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replaces the hard-coded Prebid Server and Amazon Publisher Services auction wiring with map-shaped provider and bidder configuration compiled into one immutable auction plan.
  • Adds a shared Open Real-Time Bidding (OpenRTB) 2.6 execution path with typed Standard, Prebid Server, and Amazon Publisher Services profiles, including bidder routing, request signing, notification policy, timeout handling, and response identity tracking.
  • Uses the same validated plan across adapters, runtime routing, browser demand generation, examples, and operator documentation so these paths cannot disagree about enabled providers or bidders.

The old design tied provider identity, routing, transport, and response handling to singleton implementations. Adding another standards-compliant endpoint required more provider-specific code, and each adapter could derive backend behavior independently. This implementation moves those decisions into validated configuration while preserving existing Prebid Server and Amazon Publisher Services behavior.

Changes

Changed files

Root configuration and guidance

File Change
Cargo.lock Refreshes the lockfile after removing an obsolete adapter dependency.
README.md Points operators to the new map-shaped auction provider configuration.
TESTING.md Updates auction test setup and verification guidance for the config-first implementation.
trusted-server.example.toml Replaces the legacy provider list with provider and bidder maps, typed profiles, routes, and notification settings.

Adapters and CLI

File Change
crates/trusted-server-adapter-axum/src/app.rs Compiles and reuses the validated auction plan in Axum request handling.
crates/trusted-server-adapter-axum/src/platform.rs Adds Axum target capability and backend-name validation for configured providers.
crates/trusted-server-adapter-axum/tests/routes.rs Covers startup and route behavior with config-defined auction providers.
crates/trusted-server-adapter-cloudflare/src/app.rs Builds the auction runtime from the validated plan for Cloudflare Workers.
crates/trusted-server-adapter-cloudflare/src/platform.rs Implements deterministic provider backend naming and target validation for Cloudflare Workers.
crates/trusted-server-adapter-fastly/Cargo.toml Removes the Fastly-only dependency no longer needed by backend construction.
crates/trusted-server-adapter-fastly/src/app.rs Compiles the auction plan at startup and passes it into Fastly request handling.
crates/trusted-server-adapter-fastly/src/backend.rs Reworks dynamic backend construction around canonical provider backend specifications.
crates/trusted-server-adapter-fastly/src/platform.rs Shares Fastly backend naming, timeout canonicalization, and target capability validation with the plan compiler.
crates/trusted-server-adapter-fastly/src/tinybird.rs Reports the separated provider, returned seat, and delivery bidder identities in auction telemetry.
crates/trusted-server-adapter-spin/src/app.rs Builds the auction runtime from the validated plan for Spin.
crates/trusted-server-adapter-spin/src/platform.rs Implements deterministic provider backend naming and target validation for Spin.
crates/trusted-server-cli/src/prebid_bundle.rs Removes the legacy provider-list conversion from generated Prebid configuration.
crates/trusted-server-cli/tests/config_env_overlay.rs Covers environment overlays against the new provider and bidder maps.

Auction core

File Change
crates/trusted-server-core/src/auction/README.md Documents the plan-driven auction architecture and request flow.
crates/trusted-server-core/src/auction/endpoints.rs Adds canonical endpoint validation used by provider-plan compilation.
crates/trusted-server-core/src/auction/formats.rs Carries returned upstream seat identity separately from the browser delivery bidder.
crates/trusted-server-core/src/auction/mod.rs Admits requests into the compiled-plan flow and handles disabled or empty auctions without provider I/O.
crates/trusted-server-core/src/auction/openrtb.rs Implements the shared OpenRTB 2.6 request, signing, transport, response, and notification driver.
crates/trusted-server-core/src/auction/openrtb/test_executor.rs Provides deterministic transport support for OpenRTB driver tests.
crates/trusted-server-core/src/auction/openrtb/tests.rs Adds golden and error-path coverage for Standard, Prebid Server, and Amazon Publisher Services profiles.
crates/trusted-server-core/src/auction/orchestrator.rs Replaces singleton dispatch with plan-driven fanout, routing, logical budgets, bid collection, and mediation.
crates/trusted-server-core/src/auction/plan.rs Compiles raw configuration into a sorted, immutable plan and validates target capabilities and collisions.
crates/trusted-server-core/src/auction/profile.rs Defines the typed profile registry and compiled Standard, Prebid Server, and Amazon Publisher Services profile variants.
crates/trusted-server-core/src/auction/provider.rs Adds the generic planned provider that dispatches through the shared OpenRTB driver.
crates/trusted-server-core/src/auction/routing.rs Validates bidder ownership and builds explicit and all-eligible provider routes.
crates/trusted-server-core/src/auction/telemetry.rs Keeps provider ID, returned seat, and delivery bidder distinct in telemetry.
crates/trusted-server-core/src/auction/test_support.rs Adds reusable plan, provider, and backend fixtures for auction tests.
crates/trusted-server-core/src/auction/types.rs Adds plan-driven auction input types and the returned-seat field.

Configuration, platform, and request handling

File Change
crates/trusted-server-core/src/auction_config_types.rs Defines map-shaped provider and bidder configuration with typed profile, routing, and notification options.
crates/trusted-server-core/src/config.rs Validates the new auction schema and rejects the retired list-shaped provider configuration.
crates/trusted-server-core/src/config_payload.rs Updates configuration payload parsing and validation for provider and bidder maps.
crates/trusted-server-core/src/creative_opportunities.rs Derives browser auction opportunities from authoritative configured bidder routes.
crates/trusted-server-core/src/html_processor.rs Passes plan-derived bidder data into injected browser configuration.
crates/trusted-server-core/src/platform/backend_naming.rs Adds the shared pure backend-name codec used by startup validation and adapters.
crates/trusted-server-core/src/platform/http.rs Adds HTTP fields needed by canonical provider transport.
crates/trusted-server-core/src/platform/mod.rs Exports the shared backend naming and target validation support.
crates/trusted-server-core/src/platform/test_support.rs Extends platform fixtures for provider backend prediction and transport tests.
crates/trusted-server-core/src/platform/traits.rs Updates platform contracts for canonical backend specifications and timeout handling.
crates/trusted-server-core/src/publisher.rs Generates publisher JavaScript and auction responses from the compiled provider plan.
crates/trusted-server-core/src/settings.rs Aligns runtime settings with compiled auction configuration ownership.
crates/trusted-server-core/src/test_support.rs Makes shared test settings construct the new auction configuration.

Integrations

File Change
crates/trusted-server-core/src/integrations/adserver_mock.rs Keeps mock mediation separate from bidder-provider plans while preserving mediation behavior.
crates/trusted-server-core/src/integrations/aps.rs Converts Amazon Publisher Services into a typed OpenRTB profile while preserving request, response, renderer, and diagnostics behavior.
crates/trusted-server-core/src/integrations/didomi.rs Reads auction state through the plan-backed settings API.
crates/trusted-server-core/src/integrations/google_tag_manager.rs Reads configured browser bidders from the compiled plan.
crates/trusted-server-core/src/integrations/gpt_diagnostics.rs Updates diagnostics to use plan-backed auction state.
crates/trusted-server-core/src/integrations/mod.rs Removes the former static Prebid Server and Amazon Publisher Services provider registration path.
crates/trusted-server-core/src/integrations/nextjs/mod.rs Uses plan-derived bidder configuration when generating Next.js integration data.
crates/trusted-server-core/src/integrations/prebid.rs Converts Prebid Server into a typed OpenRTB profile and derives browser demand from validated bidder routes.
crates/trusted-server-core/src/integrations/registry.rs Stops treating auction providers as singleton integration registrations.
crates/trusted-server-core/src/integrations/sourcepoint.rs Reads auction state through the plan-backed settings API.

Browser and integration tests

File Change
crates/trusted-server-integration-tests/fixtures/configs/trusted-server.integration.toml Migrates the integration fixture to provider and bidder maps.
crates/trusted-server-js/lib/src/integrations/prebid/index.ts Builds browser demand only for bidders authorized by the server plan.
crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts Covers authoritative bidder filtering and mixed browser/server demand.
crates/trusted-server-js/lib/test/prebid-artifact-integration.test.mjs Updates built-artifact expectations for plan-derived Prebid configuration.

Operator and architecture documentation

File Change
docs/guide/api-reference.md Documents the updated auction request and response behavior.
docs/guide/architecture.md Describes the compiled auction plan in the system architecture.
docs/guide/auction-orchestration.md Rewrites auction orchestration guidance around providers, profiles, bidder routes, and mediation.
docs/guide/configuration.md Documents the map-shaped auction schema and validation rules.
docs/guide/ec-setup-guide.md Updates examples that reference auction configuration.
docs/guide/error-reference.md Adds startup and request errors for invalid provider plans and routes.
docs/guide/fastly.md Explains Fastly backend handling for configured providers.
docs/guide/first-party-proxy.md Updates configuration references to the new schema.
docs/guide/getting-started.md Uses provider and bidder maps in setup instructions.
docs/guide/integration-guide.md Explains how integrations consume plan-backed auction state.
docs/guide/integrations-overview.md Updates the relationship between integrations and auction profiles.
docs/guide/integrations/aps.md Documents the Amazon Publisher Services profile and bidder routing configuration.
docs/guide/integrations/prebid.md Documents the Prebid Server profile and authoritative browser bidder behavior.
docs/guide/proxy-signing.md Updates signing references for the shared OpenRTB driver.
docs/superpowers/plans/2026-08-11-config-first-auction-provider-architecture-implementation-plan.md Records the implementation sequence, parity requirements, and verification gates.
docs/superpowers/specs/2026-08-10-config-first-auction-provider-architecture-design.md Records the configuration-first provider architecture and its runtime contracts.

Scope

This is a large change because provider configuration is now the single source of truth for startup validation, adapter backend registration, runtime dispatch, browser bidder exposure, telemetry, and operator documentation. Shipping only part of that path would leave the old and new models active at the same time and allow them to disagree. The pull request keeps the work focused on auction-provider configuration and execution; it does not replace the existing static mock mediator or add runtime-loadable provider plugins.

Target-aware validation before ts config push remote I/O remains blocked on publishing and pinning the required EdgeZero callback dependency. The shared target-independent compiler and adapter startup validation are included here.

Closes

Closes #1026

Test plan

Full verification still needs to run on the rebased implementation head. The current remote head has completed only the JavaScript and TypeScript CodeQL check.

  • cargo test-fastly && cargo test-axum && cargo test-cloudflare && cargo test-spin
  • ./scripts/test-cli.sh
  • cargo test --manifest-path crates/trusted-server-integration-tests/Cargo.toml --test parity
  • cargo fmt --all -- --check
  • cargo clippy-fastly && cargo clippy-axum && cargo clippy-cloudflare && cargo clippy-cloudflare-wasm && cargo clippy-spin-native && cargo clippy-spin-wasm
  • JS tests: cd crates/trusted-server-js/lib && npx vitest run
  • JS format: cd crates/trusted-server-js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM builds for Fastly, Cloudflare, and Spin
  • CodeQL: JavaScript and TypeScript analysis

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code; use expect("should ...")
  • Uses log macros, not println!
  • New Rust and JavaScript behavior has test coverage in this pull request
  • No secrets or credentials are intentionally included

@ChristianPavilonis ChristianPavilonis changed the title Define how auction providers are configured and routed Spec: auction provider refactor Aug 11, 2026
@ChristianPavilonis
ChristianPavilonis force-pushed the docs/config-first-auction-provider-spec branch from 8de9eab to 0c98095 Compare August 11, 2026 23:42
@ChristianPavilonis
ChristianPavilonis marked this pull request as draft August 13, 2026 15:53
@aram356 aram356 added this to the 202608 milestone Aug 17, 2026
@aram356 aram356 assigned aram356 and ChristianPavilonis and unassigned aram356 Aug 18, 2026
@aram356

aram356 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

@ChristianPavilonis to test in staging

@ChristianPavilonis
ChristianPavilonis marked this pull request as ready for review August 25, 2026 18:12
@ChristianPavilonis ChristianPavilonis changed the title Spec: auction provider refactor Add configuration-driven OpenRTB auction providers Aug 25, 2026
Make auction behavior derive from one validated provider plan so startup, runtime routing, browser demand, and platform backend handling cannot drift across adapters.\n\nPreserve existing Prebid and APS behavior while allowing multiple typed OpenRTB providers and rejecting the retired list-shaped configuration.

@prk-Jr prk-Jr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Summary

Large, coherent rework: provider identity, routing, transport, and response handling all move out of singleton integrations into one immutable, validated AuctionPlan shared by every adapter. The plan compiler, profile registry, and pure backend-naming policy are well factored, and the new validation (endpoint canonicalization, backend-name collision prediction, notification seat limits, static-extension bounds) is thorough.

Two blocking issues: the required cargo test check is failing because of this PR, and the config schema break ships with no operator-facing migration note.

1 of the inline comments below carries a one-click GitHub suggestion — use Commit suggestion to apply it as a commit on the PR branch. The remaining comments describe the fix in prose because the change spans multiple files, touches lines outside the diff, or is a design question rather than a patch.

Blocking

wrench

  • Required cargo test job fails: template-cache harness configures no auction provider — see Cross-cutting below
  • Breaking config cutover with no CHANGELOG entry and no safe deploy ordering — see Cross-cutting below
  • Dead tautological assertion in the moved registration loop — see inline at crates/trusted-server-core/src/integrations/registry.rs:827

Non-blocking

thinking / refactor

  • One malformed envelope entry silently zeroes a slot's server-side demand — see inline at crates/trusted-server-core/src/auction/routing.rs:434
  • HTTPS-only endpoint canonicalization blocks loopback stub endpoints — see inline at crates/trusted-server-core/src/auction/plan.rs:570
  • #[cfg(test)] orchestrator harness re-implements the production dispatch path — see inline at crates/trusted-server-core/src/auction/orchestrator.rs:318
  • run_auction carries the same body twice under opposite cfg gates — see inline at crates/trusted-server-core/src/auction/orchestrator.rs:849
  • apply_prebid pairs imps to slots positionally — see inline at crates/trusted-server-core/src/auction/openrtb.rs:280
  • Browser shim ownership inverted: unowned bidders now fail open to client-side — see Cross-cutting below

praise

  • Response currency is finally checked — see inline at crates/trusted-server-core/src/auction/openrtb.rs:552

Cross-cutting / body-level findings

  • wrench — Required cargo test job fails: the template-cache harness no longer configures any auction provider. scripts/template-cache-local-test.sh is not touched by this PR, but the cargo test job runs it, and it patches the example config by literal string replacement:

    s = s.replace('[integrations.prebid]\nenabled = false\nserver_url = "https://prebid.example.com/openrtb2/auction"', ...)
    s = s.replace('providers = []', 'providers = ["prebid"]', 1)

    Both target strings were deleted from trusted-server.example.toml by this PR (grep -c 'providers = \[\]' and grep -c server_url both return 0), so both replacements are silent no-ops. The stub then runs with [auction] enabled = true and zero providers, so no bids are produced and 6 assertions fail in the cargo test job:

    FAIL a bids script is present — got '0', want '1'
    FAIL the seam carries slot definitions, not just bids — got '0', want '1'
    FAIL the slot definitions reach the guarded scheduler — got '0', want '1'
    FAIL the winning bid's bucketed price reaches the reader — got '0', want '1'
    FAIL the served seam failed the real GPT module contract: Error: served document has no executable seam payload
    FAIL cache hit streams: the article is delivered before the auction resolves — got 'no', want 'yes'
      15 passed, 6 failed
    

    Rewriting the replacements to the new map shape is not sufficient on its own: canonicalize_endpoint requires scheme == "https" (crates/trusted-server-core/src/auction/plan.rs:570) and the harness stub endpoint is http://127.0.0.1:{port}/bid. The previous path accepted any scheme, since server_url carried only #[validate(url)]. The harness needs either an HTTPS stub backend or an explicit loopback exemption in endpoint validation.

  • wrench — Breaking config cutover ships with no CHANGELOG entry and no safe deploy ordering. Two schema breaks land together: [auction].providers changes from a list to a map (the list shape is explicitly rejected), and PrebidIntegrationConfig is rebuilt as a browser-only config with #[serde(deny_unknown_fields)], dropping server_url, bidders, and the server-side override fields.

    IntegrationRegistry::with_plan calls prebid::register_for_plan, which does settings.integration_config::<PrebidIntegrationConfig>(PREBID_INTEGRATION_ID)?. A live config blob still carrying server_url therefore fails to parse, the error propagates out of build_state_from_settings, and the adapter comes up on the startup-error router. The reverse ordering fails too: a map-shaped blob does not parse on a binary that predates this PR. There is no deploy ordering that avoids an outage window — binary and config have to cut over together.

    CHANGELOG.md is untouched by this PR. The repo documents exactly this class of change under [Unreleased] / Changed with a Breaking marker and explicit upgrade/rollback ordering (see the sanitize_creatives and APS OpenRTB entries, both of which spell out "upgrade the binary first, then push the config" and the rollback constraint). This change needs the same treatment, including the fact that ts config push now rejects the old shape and that the previous log-and-strip tolerance for unknown bidders / client_side_bidders entries is now a hard startup error.

  • thinking — Browser shim ownership inverted: unowned bidders now fail open to client-side. In crates/trusted-server-js/lib/src/integrations/prebid/index.ts, installPrebidNpm previously folded every bidder not listed in clientSideBidders into the trustedServer envelope and stripped it from unit.bids. It now folds only codes present in serverSideBidders (that is, [auction.bidders]) and leaves everything else in browser demand:

    unit.bids = unit.bids.filter(
      (bid) => bid?.bidder === ADAPTER_CODE || !serverSideBidders.has(bid?.bidder ?? '')
    );

    An operator who upgrades the binary and pushes a config without populating [auction.bidders] silently moves all demand from the server-side auction to direct browser SSP calls. There is no error and no warning; validate_browser_bidder_ownership only rejects codes claimed by both sides at once. Worth calling out explicitly in the migration note above, since it is a first-party-proxying regression that will not show up as a failure anywhere.

CI Status

  • cargo test: FAIL (required)
  • cargo fmt: PASS (required)
  • format-typescript: PASS (required)
  • format-docs: PASS (required)
  • cargo test (axum native): PASS
  • cargo test (cloudflare native): not reported separately; cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • cargo test (cross-adapter parity): PASS
  • cargo test (ts CLI, native): PASS
  • vitest: PASS
  • integration tests: PASS
  • integration tests (Fastly EC lifecycle): PASS
  • browser integration tests: PASS
  • prepare integration artifacts: PASS
  • CodeQL: PASS
  • Analyze (rust): PASS
  • Analyze (javascript-typescript): PASS (reported twice, from two workflow runs)
  • Analyze (actions): PASS

The suggestion in this review was applied in an isolated worktree at ba2eea6 and verified against the full gate: cargo fmt --all -- --check, all six clippy aliases, cargo test-fastly / test-axum / test-cloudflare / test-spin, and the cross-adapter parity suite — all pass, with no drift between the approved bytes and the post-verification tree.

Comment thread crates/trusted-server-core/src/integrations/registry.rs Outdated
Comment thread crates/trusted-server-core/src/auction/routing.rs
Comment thread crates/trusted-server-core/src/auction/plan.rs
Comment thread crates/trusted-server-core/src/auction/orchestrator.rs
Comment thread crates/trusted-server-core/src/auction/orchestrator.rs
Comment thread crates/trusted-server-core/src/auction/openrtb.rs
Comment thread crates/trusted-server-core/src/auction/openrtb.rs
@ChristianPavilonis

Copy link
Copy Markdown
Collaborator Author

Addressed the requested changes in 35e1897:

  • migrated the template-cache harness to the provider-map schema and a trusted local HTTPS bidder;
  • made harness config rewrites strict, bounded network waits, and added a CI job timeout;
  • documented the breaking, atomic binary/config migration and rollback requirements;
  • removed the tautological registry assertion;
  • deduplicated plan-backed run_auction handling;
  • asserted and tested Prebid impression-to-slot parameter pairing.

I deliberately retained fail-closed malformed-envelope handling, HTTPS-only provider endpoints, and configured browser/server bidder ownership. The broader AuctionOrchestratorHarness migration remains follow-up work.

Validation passed across Fastly, Axum, Cloudflare, Spin, CLI, parity, clippy, JS, formatting, and both template-cache harness modes. All inline threads have replies and are resolved.

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.

Implement config-first generic OpenRTB auction providers

3 participants