Skip to content

Run server-side identity collection on the Axum dev server - #1566

Open
dhruv8sh wants to merge 4 commits into
feat/s2s-eid-vendorsfrom
feat/axum-identity-providers
Open

dhruv8sh wants to merge 4 commits into
feat/s2s-eid-vendorsfrom
feat/axum-identity-providers

Conversation

@dhruv8sh

@dhruv8sh dhruv8sh commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Runs server-side identity collection on the Axum dev server. Until now it ran only on Fastly, and Axum refused to start with any provider enabled.
  • Covers the whole flow: cookie-only providers (SharedID, Criteo, ConnectID, ...), vendor lookups before the response through Axum's HTTP client, and lookups after the response with a follow-up conditional write. Consent gating and the single page-load write work as on Fastly.
  • Gives Axum an in-process EC record store with real compare-and-swap writes, so the identity graph's write guarantees hold without a platform store.

Changes

File Change
crates/trusted-server-adapter-axum/src/ec_kv.rs New. In-memory EcKvStore: one Mutex makes reads strongly consistent and gives a real generation compare-and-swap. Generations are never reused, and TTLs are honoured. Also adds an in-memory lookup rate limiter that rounds to a per-minute budget, as Fastly's does.
crates/trusted-server-adapter-axum/src/identity.rs New. Builds the partner registry and the coordinators for both phases at startup. Adds a lookup transport on Axum's HTTP client, navigation EC handling, finalize through KvIdentityGraph, and the after-response tokio task.
crates/trusted-server-adapter-axum/src/app.rs Drops reject_enabled_providers for Axum. Wires identity into the publisher fallback route. Gives /auction, /_ts/page-bids and the publisher auction the shared registry and graph. /_ts/admin/eids uses the shared registry.
crates/trusted-server-adapter-axum/src/identity_tests.rs New. End-to-end router tests against a local stub server.
crates/trusted-server-adapter-axum/src/lib.rs, Cargo.toml, Cargo.lock Register the modules and depend on trusted-server-identity-providers.
docs/guide/configuration.md Describes identity providers on the Axum dev server.

Differences from Fastly

  • Storage: records live in process memory and are lost on restart. This is a dev-server store, not a production backend.
  • Bot gate: Axum never sees a TLS fingerprint over plain HTTP, so it accepts any request whose User-Agent names a known platform.
  • After-response timing: collection starts when the handler returns, not after the last response byte is sent.
  • Not on Axum: partner pull sync, and EC finalization on named routes and integration proxies. Only the publisher fallback route finalizes.
  • Cloudflare and Spin still refuse enabled providers.

Closes

No linked issue. Follow-up into #1488. It includes the two SharedID commits from #1565, which the Axum tests depend on, rebased onto the current feat/s2s-eid-vendors.

Spec

Brings the existing Fastly identity flow to Axum, following the design in the #1487/#1488 stack.

Test plan

  • cargo test-fastly && cargo test-axum

  • cargo clippy-fastly && cargo clippy-axum (and cargo clippy-cli)

  • cargo fmt --all -- --check

  • JS tests: cd crates/trusted-server-js/lib && npx vitest run (no JS changes)

  • JS format: cd crates/trusted-server-js/lib && npm run format (no JS changes)

  • Docs format: prettier check on docs/guide/configuration.md

  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1

  • Manual testing via fastly compute serve

  • Other: Axum router tests against a stub server. Each test runs real navigations:

    • a _pubcid cookie is stored, and a later different cookie doesn't replace it;
    • _pubcid_optout=1 removes a stored ID and blocks a new one;
    • with TCF Purpose 4 denied, nothing is stored;
    • an ID5 lookup before the response stores its ID in exactly one page-load write;
    • an ID5 lookup after the response stores its ID through the follow-up write.

    All six identity tests passed five repeated runs.

Checklist

  • Feature PRs: spec linked above, ending in a review log of two or more agent review rounds
  • Changes follow AGENTS.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses log macros (not println!)
  • New code has tests
  • No secrets or credentials committed

@dhruv8sh dhruv8sh self-assigned this Nov 12, 2026
Read the cookie named by the Prebid sharedId module's storage.name, default the source to pubcid.org with atype 1, and keep a stored SharedID for as long as the row lives instead of letting a different cookie replace it after a day.

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
…provider

Core cannot see the provider crate's kinds, so its deploy validation refused any enabled identity provider. ts config already builds every enabled provider, which refuses an unregistered kind; core now leaves that check to it.

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
Axum now builds the partner registry and both provider coordinators at startup, reads and mints ts-ec on publisher navigations, runs page-phase lookups through Axum's HTTP client, and finalizes through KvIdentityGraph with a single page-load write. After-response providers run on a spawned blocking task with their follow-up compare-and-swap write. The identity graph is a process-local store with generation-based CAS, enabled when ec.ec_store is set.

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
@dhruv8sh
dhruv8sh force-pushed the feat/axum-identity-providers branch from 53edc2f to 117a58e Compare November 12, 2026 14:43
@dhruv8sh
dhruv8sh changed the base branch from fix/1488-sharedid-prebid-alignment to feat/s2s-eid-vendors November 12, 2026 14:43

@jevansnyc jevansnyc 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.

Reviewed the Axum identity lifecycle, process-local KV/CAS behavior, auction wiring, and included SharedID changes. No blocking runtime issues found. One non-blocking documentation correction below. All reported CI checks pass. Local verification: cargo test-axum passed all 73 tests (including all six new identity tests); one documentation example is ignored.

Comment on lines +926 to +929
Identity providers run on Fastly and on the Axum dev server. This release
registers no provider kind, so `ts config validate`, `push` and `diff` reject an
enabled provider; keep `enabled = false` until a kind ships. The Cloudflare and
Spin adapters refuse to start when an enabled provider is configured. On Fastly

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.

P3: Remove the obsolete instruction to disable all providers. This PR removes the blanket deployment rejection, and the provider crate already registers supported kinds, so this guidance would prevent readers from enabling the Axum feature described here.

Suggested change
Identity providers run on Fastly and on the Axum dev server. This release
registers no provider kind, so `ts config validate`, `push` and `diff` reject an
enabled provider; keep `enabled = false` until a kind ships. The Cloudflare and
Spin adapters refuse to start when an enabled provider is configured. On Fastly
Identity providers run on Fastly and on the Axum dev server. The Cloudflare and
Spin adapters refuse to start when an enabled provider is configured. On Fastly

@ChristianPavilonis ChristianPavilonis 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

Adds server-side identity collection to the Axum dev server with process-local generation-based CAS storage, and updates SharedID defaults and retention. Approved with one non-blocking documentation correction.

Non-blocking

🏕 camp site

  • Update contradictory provider documentation — see inline at docs/guide/configuration.md:926–929.

The inline comment is prose-only because the complete correction spans multiple files and lines outside the diff.

Verification

  • Focused configuration-validation scratch probe: PASS.
  • git diff --check: PASS.
  • Passing remote CI results reused; full local suites and deployed-runtime testing were not rerun.

CI Status

  • integration tests (Fastly EC lifecycle): PASS
  • integration tests: PASS
  • browser integration tests: PASS
  • trace runtime and browser acceptance: PASS
  • cargo test (ts CLI, native) (macos-latest): PASS
  • cargo test (ts CLI, native) (ubuntu-latest): PASS
  • cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo test (cross-adapter parity): PASS
  • worker-deadlines (cloudflare): PASS
  • cargo test (axum native): PASS
  • ts dev lint domains (changed lines): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • HTML EOF runtime (Fastly): PASS
  • CI Node pin guard: PASS
  • format-typescript: PASS
  • prepare integration artifacts: PASS
  • cargo test: PASS
  • vitest: PASS
  • cargo fmt: PASS
  • release scripts: PASS
  • CLAUDE.md symlink guard: PASS
  • docs-proposal scripts: PASS
  • format-docs: PASS
  • worker-deadlines (spin): PASS

GitHub reports no required checks for this branch.

Comment on lines +926 to +929
Identity providers run on Fastly and on the Axum dev server. This release
registers no provider kind, so `ts config validate`, `push` and `diff` reject an
enabled provider; keep `enabled = false` until a kind ships. The Cloudflare and
Spin adapters refuse to start when an enabled provider is configured. On Fastly

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.

🏕 camp site — Update the remaining contradictory provider documentation

This paragraph still says the release registers no provider kinds and rejects every enabled provider, but this build includes registered kinds and this PR removes that blanket rejection. Related contradictions remain at lines 981–982, 999–1000, 1016–1017 and 1033–1034; trusted-server.example.toml:124 also still says “Fastly only.”

Proposed wording:

Identity providers run on Fastly and on the Axum dev server. `ts config validate`,
`push` and `diff` reject unregistered kinds and invalid provider-specific
settings. Cloudflare and Spin refuse to start with enabled providers.
Invalid enabled provider configuration also fails startup on Fastly and Axum.

Retain the process-local storage and TLS explanation, and align the other references above with this behavior.

Apply manually — the complete correction spans multiple files and lines outside the diff.

aram356 added a commit that referenced this pull request Nov 12, 2026


Per the user, every feature is built once and works on every adapter in
platform order, with platform gaps sent to EdgeZero (DEC-16, SH-5). T21
moves the identity routes, EC lifecycle, providers and write-back into one
router in core that each adapter mounts; A2, A10, T8, T9, T17 and T18
shrink to turning it on per adapter and passing the conformance suite, and
T7, T14 and A11 fold into A2 and A10. EZI-2a adds EdgeZero's local store
for Axum development and EZI-4 binds Axum's geo provider from the manifest.

Restack the Axum RC units on #1506: #1531 carries A1 in place of #1528,
#1533 and #1534 close as copies of #1525 and #1526, and the image and
Terraform units sit directly on #1532 so A6 and A7 stop waiting on A2.
Record #1566, refresh the provider stack's fixes at their current heads,
and flag #1535 as unplanned.
@aram356

aram356 commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator

CREATOR: From the server-side identity plan (#1559, c7dc9de77): Move 0a2a00aaf (SharedID name, source and retention) and 0c13d4272 (drops the blanket provider rejection) into #1488. Rebuild the Axum part on T21's shared app and EdgeZero capabilities: no Axum-only EcKvStore (ec_kv.rs:87; ID-2, DEC-3), no Trusted Server rate limiter (none on Axum, DEC-11), no User-Agent-only gate (EZI-3, ID-7), and no detached block_on task (EZI-1). Local development uses EdgeZero's local store (EZI-2a). It then serves A2 and A10.

Part of #1574

This branch has not been deployed

No deployments
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