Skip to content

Add TS admin endpoint to look up EC by id#928

Open
prk-Jr wants to merge 4 commits into
mainfrom
feat/admin-ec-lookup-endpoint
Open

Add TS admin endpoint to look up EC by id#928
prk-Jr wants to merge 4 commits into
mainfrom
feat/admin-ec-lookup-endpoint

Conversation

@prk-Jr

@prk-Jr prk-Jr commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds GET /_ts/admin/ec/{id} (explicit EC ID) and GET /_ts/admin/ec (EC ID from the caller's ts-ec cookie) so operators can inspect EC identity graph entries without KV console access.
  • The EC response includes a derived auction view: the exact EIDs the auction would attach for the entry, plus the reason each stored partner ID was skipped (empty_uid, not_in_registry, bidstream_disabled) — making KV-to-auction EID propagation debuggable in one call. Corrupt or legacy-schema entries stay inspectable via a new raw lookup that reports entry_error + raw_body instead of failing closed.
  • Adds GET /_ts/admin/eids, the client-side half of the picture: it echoes the request's ts-eids and sharedId cookies and previews what cookie ingestion would write into the EC entry's ids map (matched partner UIDs, deduplicated exactly like the ingestion path, plus dropped sources). Pure request inspection with no KV access, so every adapter serves the real handler; always responds 200.

Changes

File Change
crates/trusted-server-core/src/ec/admin.rs New handle_admin_ec_lookup + handle_admin_eids_lookup handlers, response payload types, 14 unit tests
crates/trusted-server-core/src/ec/kv.rs New KvIdentityGraph::lookup_raw returning raw body/metadata/generation without validation
crates/trusted-server-core/src/ec/prebid_eids.rs Expose cookie-ingestion collectors pub(crate) so the EIDs preview reuses them instead of reimplementing
crates/trusted-server-core/src/ec/mod.rs Register admin module
crates/trusted-server-core/src/settings.rs Add all three routes to Settings::ADMIN_ENDPOINTS; update coverage tests
crates/trusted-server-adapter-fastly/src/app.rs Route EC + EIDs paths to the real handlers; route-table tests. The EC arm deliberately builds its own identity graph instead of reusing the bot-gated ec.kv_graph, so operator curl requests work
crates/trusted-server-adapter-axum/src/app.rs EC routes → local 501 (AdminEcNotSupported); EIDs route → real handler
crates/trusted-server-adapter-axum/tests/routes.rs Route-registration, authenticated-501 (EC) and authenticated-200 (EIDs) tests
crates/trusted-server-adapter-cloudflare/src/app.rs EC routes → local 501; EIDs route → real handler
crates/trusted-server-adapter-cloudflare/tests/routes.rs Route-registration, authenticated-501 (EC) and authenticated-200 (EIDs) tests
crates/trusted-server-adapter-spin/src/app.rs EC routes → local 501; EIDs route → real handler; extend fallback-methods table
crates/trusted-server-adapter-spin/tests/routes.rs Authenticated-501 (EC) and authenticated-200 (EIDs) tests

Closes

Closes #921

Test plan

  • cargo test-fastly && cargo test-axum (also cargo test-cloudflare && cargo test-spin)
  • cargo clippy-fastly && cargo clippy-axum (also clippy-cloudflare, clippy-cloudflare-wasm, clippy-spin-native, clippy-spin-wasm)
  • cargo fmt --all -- --check
  • JS tests: cd crates/trusted-server-js/lib && npx vitest run (JS untouched — left to CI)
  • JS format: cd crates/trusted-server-js/lib && npm run format (JS untouched — left to CI)
  • Docs format: cd docs && npm run format (docs untouched — left to CI)
  • WASM build: cargo check -p trusted-server-adapter-fastly --target wasm32-wasip1
  • Manual testing via fastly compute serve: verified auth gating, the EC lookup against the seeded Viceroy entry, and the EIDs echo against real browser cookies; this surfaced (and the branch fixes) an initial bug where the bot-gated KV graph made curl requests return 501
  • Other: integration parity suite (cargo test --manifest-path crates/trusted-server-integration-tests/Cargo.toml --test parity)

Hardening note

All three paths were added to Settings::ADMIN_ENDPOINTS, so startup validation fails closed (a Configuration error via Report, no panic!/unwrap()/expect()) for any config whose basic-auth handler regex does not cover them; prefix-style regexes like the example config's ^/_ts/admin remain valid. Covered by the updated uncovered_admin_endpoints_* and admin_endpoints_match_fastly_router tests. Routes are registered explicitly on every adapter so they never fall through to the publisher fallback, which would forward the caller's Authorization header to the origin.

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses log macros (not println!)
  • New code has tests
  • No secrets or credentials committed

Adds GET /_ts/admin/ec/{id} (explicit EC ID) and GET /_ts/admin/ec
(EC ID from the caller's ts-ec cookie) so operators can inspect EC
identity graph entries and debug KV-to-auction EID propagation.

The core handler returns the stored KvEntry verbatim (including raw
consent strings and partner UIDs), the KV metadata mirror, the store
generation marker, and a derived auction view showing exactly which
EIDs the auction would attach and why each stored partner ID was
skipped (empty_uid, not_in_registry, bidstream_disabled). Corrupt
entries are returned with the parse error and raw body via the new
KvIdentityGraph::lookup_raw instead of failing closed.

The routes join Settings::ADMIN_ENDPOINTS so startup validation
rejects configs whose basic-auth handler regex does not cover them.
The EC identity graph is Fastly KV backed, so the Axum, Cloudflare,
and Spin adapters register the routes to local 501 responses, keeping
them off the publisher fallback that would forward the Authorization
header to the origin.

Closes #921
@prk-Jr prk-Jr self-assigned this Jul 17, 2026
prk-Jr added 3 commits July 17, 2026 18:46
The dispatch arm reused EcRequestState::kv_graph, which is deliberately
None for clients that fail the browser gate. Operators hit this
auth-gated endpoint with curl, so every lookup returned 501 as if no
EC store were configured. Build the identity graph directly from
settings instead, and document why the bot-gated copy must not be used.

Also point the bare-route no-cookie 404 at the explicit-id route, since
the ts-ec cookie (Domain-scoped, Secure) cannot exist on localhost.
Adds GET /_ts/admin/eids, complementing the EC lookup endpoint with the
client-side half of EID propagation: it decodes the request's ts-eids
and sharedId cookies and previews what cookie ingestion would write
into the EC entry's ids map — matched partner UIDs (deduplicated
exactly like the ingestion path) and unmatched sources that would be
dropped.

The endpoint always responds 200; missing or malformed cookies are
reported in the payload rather than as errors. It is pure request
inspection with no KV access, so every adapter serves the real handler.
The path joins Settings::ADMIN_ENDPOINTS for basic-auth coverage
validation.
Review feedback on the admin EC lookup asked for readable dates. The
echoed entry now carries derived created_iso and consent.updated_iso
fields (yyyy-MM-ddTHH:mm:ss.SSSZ) next to the stored unix-seconds
values, which stay untouched so the echo remains faithful to KV.
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.

Add TS admin endpoint to look up EC by id

1 participant