Skip to content

About

No description, website, or topics provided.

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Auctioneer

Important

Auctioneer is under heavy development and is not yet stable. We are not accepting outside contributions or pull requests at this time. This notice will be updated when the project is ready for external contributions.

IAB Tech Lab repository. This is a fresh-history import. Historical plans and evidence are retained; see repository import for their status.

An OpenRTB 2.6 auction engine written in Rust, usable as a standalone server or a library for in-binary integration. Built on the EdgeZero framework, its standalone adapters target Axum (native), Cloudflare Workers, Fastly Compute@Edge, and Spin (Fermyon). Target support is not deployment qualification. Direct Trusted Server integration is a product goal; see the vision for the distinction from the existing library.

Product vision: vision.md Architecture overview: docs/architecture.md Design spec: Master design Approved roadmap: docs/roadmap.md Foundations plan: docs/superpowers/plans/2026-05-25-foundations.md Upstream credit: Prebid and other acknowledgements

Workspace

Crate Purpose
crates/auctioneer-core EdgeZero app, HTTP routes and handlers, host integration, and response serialization
crates/auctioneer-runtime Host-environment seams: Clock + Rng traits with deterministic test impls (FakeClock, SeededRng), Fisher-Yates shuffle, Lemire gen_range
crates/auctioneer-openrtb OpenRTB 2.6 typed model + prepare(req, headers) — the sole construction gate for a NormalizedBidRequest
crates/auctioneer-config Host / account / bidder configuration. Build-time codegen reads bidder-owned bidder.toml manifests, auctioneer.toml, and shared reference data, then emits typed accessors
crates/auctioneer-adapter-axum Axum (native) entry point
crates/auctioneer-adapter-cloudflare Cloudflare Workers (wasm32-unknown-unknown) entry point
crates/auctioneer-adapter-fastly Fastly Compute@Edge (wasm32-wasip1) entry point
crates/auctioneer-adapter-spin Spin / Fermyon (wasm32-wasip2) entry point

Status

  • Foundations and auction core: runtime primitives, typed OpenRTB preparation, generated configuration, and the auction, status, and bidder-info routes are implemented with unit and integration tests.
  • GDPR fanout: TCF v2 parsing and legal-basis enforcement, GVL/GCL authenticity and freshness, GDPR scrubs, config overlays (bidder kill switches, sample_rate, aliases, and accounts), and golden fixtures are implemented.
  • Bounded fanout and privacy enforcement: strict config resolution, GPP source normalization, independent CCPA/LMT/COPPA and activity decisions, bidder-local projection/scrubs, bounded outbound construction, and measured per-auction reservations are integrated. The verification record records native tests, conformance, linting, and WASM compilation checks, not a physical-OOM guarantee or hosted qualification.
  • Signed user sync: /cookie_sync, /setuid, /getuids, and the preflight use the generated App; issued UID state requires a MAC envelope. Recorded native and Chromium loopback checks do not establish third-party-cookie acceptance or hosted-provider readiness.
  • Bounded diagnostics: permission-gated capture and sanitized projection into auction ext.debug are implemented. Local diagnostic and qualification evidence retains explicit provider, resource, and publisher-readiness limitations.
  • Controlled-native bidder delivery: source registration is generated, and all 14 priority selected flows, including Sharethrough, Rubicon, and APS, are implemented under the approved native contract. Recorded local acceptance is not full-catalog completion or complete worst-case resource certification. New priority publications are native-only and inactive by default; existing guest publications remain unchanged.

Complete resource certification is outstanding; affected guest production readiness remains blocked. Hosted execution, Trusted Server embedding, and live publisher acceptance remain separate work. Production deployment uses EdgeZero's production-deploy tooling; commands in edgezero.toml are dev/staging-only.

Roadmap

The approved roadmap separates delivered diagnostic hardening and controlled-native priority flows from planned integration and qualification. The next priorities are direct Trusted Server embedding and a selected-bidder publisher pilot, then demand-led bidder expansion. Stored requests/accounts, currency/multibid/auction identity, creative caching, and full video delivery follow. Other shared parity work covers first-party data, floors/adjustments, AMP/native, privacy/transparency, compressed ingress, hooks/modules, metrics/analytics, and browser privacy compatibility. Residual full-catalog migration remains distinct from priority-flow delivery and bidder expansion. These plans do not claim implementation or production readiness.

Diagnostic qualification is a local/staging checkpoint, not a live publisher pilot. Trusted Server embedding owns in-binary integration; publisher-pilot acceptance owns hosted execution and live limited-bidder rollout. Selected banner/display flows need not wait for the full catalog or video, but publisher-specific dependencies and deployment checks still apply; see the pilot requirements.

Build

Install the versions declared in .tool-versions using your tool manager. The file pins Rust, Node.js, Fastly CLI, Spin, Viceroy, and Wasmtime to the reviewed EdgeZero toolset. A version declaration does not install a missing tool or its version-manager plugin.

Rust builds every target; Node.js serves the browser and Worker tooling. Fastly CLI and Spin package their adapters, and Viceroy runs the local Fastly guest controls. The pinned Wasmtime is required for selected-source WASIp1/P2 schema execution tests, including the workspace test run. CI installs its checksum-pinned release before those consumers. Compile/package-only WASM jobs still do not establish runtime execution. Relevant CI setup reads .tool-versions instead of maintaining separate Rust, Node.js, Fastly, Spin, or Viceroy version literals.

For the normal edit loop, start with the affected package rather than the workspace. See development loops and test ownership for focused commands, required-feature checks and isolation rules. Retain Cargo's incremental cache; do not routinely clean targets between edits.

cargo check --locked -p auctioneer-bidder --lib
cargo test --locked -p auctioneer-bidder --lib endpoint_builder::tests::

Broad native checks (not the complete CI/guest/qualification matrix):

cargo build --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings

The insecure-bidders cargo feature on auctioneer-config enables deterministic loopback test bidders:

cargo test --workspace --features auctioneer-config/insecure-bidders

Axum's default cargo test -p auctioneer-adapter-axum --all-targets also runs the handler-to-socket privacy test. Its test-only dependency enables the loopback bidder; normal production builds retain the secure defaults. The test sweeps CCPA and all three disclosure activities independently.

Auction privacy configuration

The executable examples in auctioneer.toml cover baked defaults and pushed runtime overrides. CCPA and LMT enforcement default off; activity controls default to allow. GDPR enablement does not bypass independent CCPA, LMT, COPPA, or activity decisions. COPPA has no disable override. Activity configuration accepts at most 128 rules per activity, 128 combined name/type entries per rule, and 128 UTF-8 bytes per component name. Runtime rule arrays replace inherited arrays; rules = [] clears them.

The internal GPP envelope parser supports TCF section 2 and USP section 6 through separate policy modules. Other sections remain opaque; this does not implement US-state policy enforcement. Parser ceilings are:

Input or work Ceiling
Raw GPP UTF-8 value 256 KiB
Encoded header 4 KiB
Total sections, including unknown/empty sections 64
Numeric section ID 1..=65535
Charged decoding operations 524288

Limit violations and invalid ext.prebid.nosale names return 400 before bidder construction, even when enforcement is disabled. Within-limit format errors instead use fixed warnings and the documented source-selection rules; an empty or invalid active TCF section never retries granting legacy consent. See the privacy enforcement design for precedence, scrubs, and the remaining acceptance requirements.

[baked.host.resource_limits] defines independent max_outbound_raw_bytes and max_outbound_request_bytes ceilings for raw and transport-encoded bidder bodies. Set the same fields under [runtime.auction] for pushed overrides. Both default to 256 KiB, accept 1 KiB through 16 MiB, and are clamped to the installed boot envelope. An oversized bidder request is a bidder-local code-5 refusal; exceeding an auction's prepaid resource allowance instead returns fixed 503 overloaded\n. The latter never changes consent selection.

User sync operator setup

Provision usersync_cookie_keyring in the default EdgeZero secret store before serving UID routes. See key provisioning and rotation. Unsigned/tampered cookies are rejected; unavailable keys return 503 without cookie writes. A valid signature protects issued state, not ownership of the public callback's supplied UID or an authorization/consent grant.

The example auctioneer.toml uses https://sync.example.test only as a demonstration callback base. Set baked.host.user_sync.external_url (or its runtime.user_sync override) to the public HTTPS origin and optional base path that actually reaches this deployment, for example https://sync.publisher.example/auctioneer. The default redirect template then builds callbacks under that base path. Do not derive the callback from request Host, Origin, or forwarded headers. Baked changes require a rebuild; runtime changes require a config push and take effect on a subsequent request. Invalid effective sync config is rejected rather than replaced by permissive defaults.

host_cookie.cookie_name and family identify a separate host cookie to import; Auctioneer's writable UID cookie is always named uids. Configure an optional cookie domain, positive ttl_days (default 90), and optional opt-out cookie name and value together. max_cookie_size_bytes = 0 disables only the logical eviction threshold, not the hard Set-Cookie cap. Account cookie_sync settings select default/cooperative limits and can replace host priority groups, including with an empty list. A missing or empty account selects baked/default policy; a supplied account ID selects its named override when present. runtime.bidders.<name>.usersync_enabled can disable sync independently of auction participation, but cannot create a syncer absent from the baked bidder metadata.

Cross-origin JavaScript access is off by default. Add exact scheme/host/port origins to user_sync.allowed_origins, without paths or wildcards, and send browser requests with credentials when cookies are needed. Allowed application responses use credentialed CORS and Vary: Origin; OPTIONS /cookie_sync permits POST with Content-Type. Pre-config/admission/framework failures cannot promise CORS headers. Auctioneer-owned sync responses use Cache-Control: no-store. The uids cookie uses Path=/ and an expiry; Domain is optional. The current Chrome/CriOS 67+ user-agent rule adds Secure and SameSite=None. Browser acceptance, especially in third-party contexts, is not guaranteed by a successful server response and needs real-browser validation.

Sync surface Current hard limit
POST /cookie_sync 32 KiB body and 4,096 JSON nodes; compressed bodies rejected
GET /setuid, GET /getuids 32 KiB encoded query, at most 32 parameters; adapter request-target profiles allow 33 KiB, subject to provider limits
Cookie decode Current profiles admit 16 KiB of request headers; codec ceilings are 64 header fields, 32 KiB header/encoded value, 24 KiB decoded value, and 4,096 JSON nodes
Selection/config 256 requested or catalog names, 128 UTF-8 bytes per name, 32 priority groups, 256 priority entries
Output 32 KiB per sync URL, 256 KiB response body, 4 KiB complete signed Set-Cookie field value

These are resource ceilings, not a promise that every legal browser or provider request is admitted. User sync does not migrate the full upstream bidder catalog and does not feed stored buyeruid values into auction bidder requests; /getuids exposes the stored map to clients only. See the user sync design for endpoint ordering and intentional reference differences.

Per-adapter dev commands

Routes are wired in auctioneer-core; the commands below are the Cargo/framework entry points for the adapter shells. Run them from the workspace root.

Adapter Local dev
Axum cargo run -p auctioneer-adapter-axum
Cloudflare Workers wrangler dev --cwd crates/auctioneer-adapter-cloudflare
Fastly Compute@Edge fastly compute serve
Spin spin up --from crates/auctioneer-adapter-spin

Operational endpoints (/_auctioneer/*)

GET /_auctioneer/health/gvl reports GVL archive health (archive age, bundled vendor-list versions, and the rolling unavailable-lookup counter). The handler is fail-closed: it answers 401 unless the adapter boot installed an explicit access policy — either a bearer token (AUCTIONEER__RUNTIME__HEALTH_GVL_TOKEN on Axum / Cloudflare; the platform secret store on Fastly / Spin) or the machine-checkable allow_unauthenticated_health = true opt-in.

Deployments that opt in to serving /_auctioneer/* without a token MUST restrict the /_auctioneer/* path prefix at the ingress layer. That restriction is an L7 (HTTP-path) rule — an L3/L4 network policy such as Kubernetes NetworkPolicy cannot match an HTTP path and does NOT satisfy it. Per-platform recipes (Cloudflare Access, Fastly VCL, Kubernetes ingress HTTPRoute + AuthorizationPolicy, nginx auth_request for standalone Axum) live in docs/deployment/restrict-operational-endpoints.md.

License

Copyright 2026 IAB Technology Laboratory, Inc.

Auctioneer is licensed under the Apache License 2.0, matching IAB Tech Lab Trusted Server's license. Third-party copyrights and attribution remain in NOTICE and the source-specific notices; the project copyright does not replace them.

Acknowledgements

Auctioneer builds on EdgeZero and the IAB Tech Lab OpenRTB specification.

Auctioneer credits Prebid.org and the Prebid Server contributors for the selected bidder implementations ported and adapted to Rust, bidder metadata, parameter schemas, auction/privacy/user-sync reference behavior, and captured test fixtures. Additional bidder reference material comes from the Stackpop fork of Prebid Server. GPP reference fixtures also use Prebid's go-gpp; this fixture reference is not a Go runtime dependency.

Auctioneer's Rust adaptations, policy decisions and extensions differ from these upstream projects. Attribution does not imply complete behavioral parity, certification, affiliation or endorsement.

The NOTICE records upstream credit and the retained Prebid Server copyright notice. The unchanged shared reference license remains with the bidder source witnesses. The patched schema compiler retains its MIT license. The patched regex-automata retains its MIT or Apache-2.0 license alternatives. Other third-party materials retain their own licenses and notices.

Reference-derived bidders' bidder.toml files record their immutable source revisions and intentional differences. Attribution and shared license notices belong here, not in a new license file in every bidder folder. Existing byte-pinned reference captures are consolidated with their integrity readers under the asset migration plan; their duplication is not the convention for new bidders.

About

No description, website, or topics provided.

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages