Skip to content

List linked modules in each adapter - #1384

Open
jwrosewell wants to merge 58 commits into
feature/42-consent-decodersfrom
feature/43-no-modules-crate
Open

jwrosewell wants to merge 58 commits into
feature/42-consent-decodersfrom
feature/43-no-modules-crate

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Changes

Area Change
crates/trusted-server-adapter-axum/tests 3 files, 563 lines added, 52 removed
crates/trusted-server-core/src 8 files, 467 lines added, 12 removed
crates/trusted-server-cli/src 5 files, 203 lines added, 12 removed
crates/trusted-server-adapter-fastly/src 3 files, 174 lines added, 37 removed
crates/trusted-server-adapter-axum/src 1 file, 135 lines added, 4 removed
crates/trusted-server-adapter-cloudflare/src 1 file, 135 lines added, 4 removed
crates/trusted-server-adapter-spin/src 1 file, 135 lines added, 4 removed
Cargo.lock 1 file, 118 lines added, 61 removed
docs/guide 11 files, 116 lines added, 88 removed
docs/superpowers 1 file, 101 lines added, 0 removed
crates/ad-tag/google 2 files, 50 lines added, 0 removed
crates/testing/iabtl 4 files, 48 lines added, 26 removed
crates/ads-txt/iabtl 3 files, 40 lines added, 17 removed
crates/bot-protection/datadome 1 file, 29 lines added, 0 removed
crates/framework/nextjs 1 file, 28 lines added, 0 removed
crates/auction/prebid 1 file, 23 lines added, 0 removed
crates/audience/permutive 1 file, 23 lines added, 0 removed
crates/cmp/didomi 1 file, 23 lines added, 0 removed
crates/cmp/inmobi 1 file, 23 lines added, 0 removed
crates/cmp/sourcepoint 1 file, 23 lines added, 0 removed
crates/identity/lockr 1 file, 23 lines added, 0 removed
crates/tag/google-tag-manager 1 file, 23 lines added, 0 removed
crates/tag/google-tag 1 file, 23 lines added, 0 removed
crates/testing/testlight 1 file, 23 lines added, 0 removed
crates/trusted-server-adapter-axum/Cargo.toml 1 file, 20 lines added, 2 removed
crates/trusted-server-adapter-cloudflare/Cargo.toml 1 file, 20 lines added, 2 removed
crates/trusted-server-adapter-fastly/Cargo.toml 1 file, 20 lines added, 2 removed
crates/trusted-server-adapter-spin/Cargo.toml 1 file, 20 lines added, 2 removed
crates/headers/geo 1 file, 19 lines added, 1 removed
crates/trusted-server-cli/Cargo.toml 1 file, 18 lines added, 2 removed
AGENTS.md 1 file, 7 lines added, 8 removed
crates/trusted-server-cli/tests 2 files, 7 lines added, 7 removed
crates/trusted-server-integration-tests/src 1 file, 7 lines added, 5 removed
trusted-server.example.toml 1 file, 7 lines added, 7 removed
.cargo/config.toml 1 file, 6 lines added, 6 removed
Cargo.toml 1 file, 5 lines added, 7 removed
crates/ad-server/iabtl 2 files, 5 lines added, 5 removed
crates/trusted-server-adapter-cloudflare/tests 1 file, 5 lines added, 5 removed
crates/trusted-server-adapter-spin/tests 1 file, 5 lines added, 5 removed
crates/trusted-server-integration-tests/tests 1 file, 5 lines added, 3 removed
.github/workflows 1 file, 3 lines added, 3 removed
CHANGELOG.md 1 file, 3 lines added, 2 removed
crates/trusted-server-integration-tests/Cargo.toml 1 file, 3 lines added, 2 removed
TESTING.md 1 file, 2 lines added, 2 removed
crates/trusted-server-modules/Cargo.toml 1 file, 0 lines added, 50 removed
crates/trusted-server-modules/src 1 file, 0 lines added, 984 removed

Closes

Closes #1334

Spec

Spec: no-modules-crate

Test plan

CI on this pull request at c60a832 passed all 20 checks.

  • cargo test-fastly && cargo test-axum
  • cargo clippy-fastly && cargo clippy-axum
  • cargo fmt --all -- --check
  • 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 build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve
  • Other: the full workflow set of this repository, run on this pull request at c60a832

Checklist

  • Feature PRs: spec linked above, ending in a review log of two or more review rounds
  • Changes follow AGENTS.md conventions
  • No unwrap() in production code (clippy denies unwrap_used in CI)
  • Uses log macros as AGENTS.md asks (not println!)
  • New code has tests
  • No secrets or credentials committed

On top of the consent decoders series (#1383). Issue: #1334.

What changed after the 51Degrees PR review

Agreed at the review on 23 October, point 2. The 51Degrees loading cache is pluggable through modules, and the publisher asset feature becomes a module.

  • Neither an adapter nor the ts tool links the loading cache module. Each adapter's list and the tool's list drop the 51Degrees loading cache module, so no stock build compiles it or fiftyone-caching, and a test beside each list fails if a module on it offers a loading cache.
  • This pull request's copy of the no modules crate design takes its final text from Add the integration seam design specs #1342, which says that the Axum adapter's linked builders include no loading cache module.

Agreed at the review on 23 October, point 4. Attestation leaves the stack, with no attestation interface in core.

Fixes found in review

  • The design copy names the order test of the ts list, where it said the list had none.
  • A CLI test shows ts config validate refusing a loading cache module it does not link. It takes the place of the test that went with the stock lists' loading cache.

Kept current

What this adds

What changes.

crates/trusted-server-modules is gone. Each adapter lists the modules it links in its own app.rs, each module describes the middleware it supplies, the ts command asks the builders it links, and the three modules this repository ships under names that said nothing about their maintainer are named for it: crates/ad-server/iabtl, crates/testing/iabtl and crates/ads-txt/iabtl.

How it works.

  • Each adapter lists what it links. shipped_module_builders() in each adapter's app.rs is the same twenty builders in the same order the crate listed them, and module_builders_with(extra) puts a deployment's own after them. None of them offers a loading cache, so no stock build links the loading cache module, and a deployment that wants copies kept hands a loading cache module's builder to its adapter with its own. The integration test crate takes the Axum adapter's list, because its fixtures are validated against what the adapters have.
  • Each module describes its middleware. IntegrationBuilder::with_middleware takes the middleware a module supplies with their phases and media types, supplied_middleware(builders) gives them in the registry's order with core's own rows (the script proxy, robots.txt, the service version), and the registry refuses a registration whose description contradicts what it registers. A description is optional, because the registry's own tests register middleware in many places and a registration can be conditional, and each stock module proves its description against its registration in a test of its own.
  • The ts command asks the builders. The audit's entries come from supplied_middleware over the builders the command links, and a module's selection comes from the builder's own section and name, so the command holds no table.
  • The renames. [ad-server] module = "iabtl" with [ad-server.iabtl], [ads-txt] modules = ["iabtl"], and the seam probe's [shared.iabtl], loading-cache.iabtl and iabtl-answers cache follow the folders. Type names, log labels, the probe's integration id, routes and page markers stay, because they say what the thing does rather than where it lives.

Why

Nothing is shared by being listed. Every piece of functionality is its own crate under crates/<type>/<vendor>/, with iabtl as the vendor where this repository's own initial version has no vendor, and each adapter and each deployment names the crates it links itself. A module that describes its own middleware is the only place that description cannot drift from the code.

What breaks

A deployment that selected mock or sellers writes iabtl, and one whose settings named the seam probe's shared table or cache follows the rename, each listed with its old and new form in the changelog. A crate outside core that depended on trusted-server-modules names the crates it links instead.

The commits

  1. The ad server this repository ships is named for its maintainer.
  2. The seam probe is named for its maintainer.
  3. The ads.txt module this repository ships is named for its maintainer.
  4. Each module describes the middleware it supplies.
  5. The ts command asks the builders it links.
  6. Each adapter lists the modules it links.
  7. The Fastly adapter's test module imports the composition functions its tests call, and the Axum shipped-modules test is formatted as cargo fmt wants.
  8. A merge of the series below, which carries the fixes made lower in the stack.
  9. A merge of the series below, which carries the page origin change.
  10. The no modules crate design names the adapters, the startup refusal and the rollout of the renames, and takes its round 2 corrections.
  11. The config push tests read a pushed document back with the modules the ts command links, in place of the removed modules crate's list.
  12. The DataDome description test passes the module's id as a constant, because code scanning took the id, read from a builder that declares secret settings, for a secret in the test's assertion message.
  13. Neither an adapter nor the ts command links the loading cache module or depends on its crate, so a stock build compiles neither the module nor fiftyone-caching, and a test beside each list fails if a module on it offers a loading cache.
  14. This row's copy of the no modules crate design takes its final text from Add the integration seam design specs #1342.
  15. The endpoint proof's tests select the probe by its new name, iabtl.
  16. Later merges of the series below carry Tech Lab main at 7aa5c99.

The mock ad server moves from crates/ad-server/mock to
crates/ad-server/iabtl, the stack's own, under the package name
trusted-server-ad-server-iabtl. The module name is ad-server.iabtl,
so a deployment that selected it writes [ad-server] module = "iabtl"
and [ad-server.iabtl], and an implementation line names
ad-server.iabtl. The workspace, the cargo aliases, the stock module
list, the guide, the template and the changelog follow.

The crate's types and log labels keep the word mock because they
describe what the ad server does, which is to ask mocktioneer's
decision endpoint.
The test fixture that proves the integration seam from outside core
moves from crates/testing/seam-probe to crates/testing/iabtl, under
the package name trusted-server-testing-iabtl. Its module name
follows its folder, so the settings that select it and each of the
modules it supplies write testing.iabtl, its shared table is
[shared.iabtl], its loading cache is loading-cache.iabtl and the
cache it declares is iabtl-answers. The two adapters' round-trip
tests, the workflow that runs the crate's own tests, the guide and
the changelog follow.

The probe's integration id, its routes, the markers it writes into a
page and the identities its modules answer with keep the words seam
probe, because they say what the fixture is rather than where it
lives.
The module that adds a publisher's sellers to ads.txt moves from
crates/ads-txt/sellers to crates/ads-txt/iabtl, the stack's own
initial version, under the package name trusted-server-ads-txt-iabtl.
Its module name follows its folder, so a deployment that selected it
writes [ads-txt] modules = ["iabtl"] and [ads-txt.iabtl], and the
[[fetch]] entry on /ads.txt names the middleware ads-txt.iabtl. The
workspace, the cargo aliases, the stock module list, the guide, the
template and the changelog follow.

The crate's types keep the word sellers because they describe what
the module adds.
IntegrationBuilder gains with_middleware, which takes the page changes
a module's registration supplies as SuppliedMiddleware values naming
the middleware, the phase an entry names it in and the media type the
entry covers. A middleware that runs in either phase is described in
the one a generated configuration places it in. The registry refuses
a registration whose middleware contradicts the description, in a
phase it does not run in or for a media type it does not work on, and
leaves a described middleware the registration does not supply alone,
because a module may supply one only where its settings call for it.

Core lists what a build supplies with supplied_middleware, in the order
the registry registers them: what registers from the auction plan,
then the built-in modules, then the linked builders in their order,
then core's robots.txt and service version middleware, which no
builder supplies. A tool that writes a configuration asks this of the
builders it links and holds no table of its own.

Every module in this repository that supplies middleware describes it,
the script proxy and the seam probe included, and each proves under its
own fixture settings that the description is exactly what it registers,
through the helper in core's test support.
The ts tool lists the module builders it links in its own composition,
in the order their request hooks run, and registers that list for
deploy validation where it registered the stock crate's. The audit's
generator writes the [[fetch]] and [[serve]] entries from what those
builders describe of their middleware, through core's
supplied_middleware, and finds the section a detected module is
selected in and the name it is written under from the builder itself,
so the command holds no table of modules.

The tool depends on each module crate it links, and the list is
public so the command's own integration tests register the same
modules the command does.
crates/trusted-server-modules is removed. Each adapter lists the
module builders it links in its own app.rs, as shipped_module_builders,
in the order their request hooks run, which is the order the crate
listed them, and composes a deployment's builders after them with
module_builders_with. The adapters build their state and load their
settings from that list where they took the crate's, and the Fastly
adapter re-exports both so a deployment composing a binary of its own
can take the list. The integration tests validate their fixture
configurations against the Axum adapter's list.

The tests the crate held move to where the thing they test now lives.
Each adapter proves its own list's order and composition. The Axum
adapter proves what the linked builders give a deployment, being the
stock loading cache, each module's own deploy rules and secret
settings, the diagnostics module's request preparer, the middleware
the template and the guide document, the ad server's decision between
planned bids and the maintainers every crate outside core names.

The workspace, the cargo aliases, the guide, the onboarding page and
the layout in AGENTS.md follow, with a design page for the change.
# Conflicts:
#	CHANGELOG.md
#	crates/trusted-server-modules/src/lib.rs
The Fastly adapter's tests call shipped_module_builders and
module_builders_with and name IntegrationBuilder, so the test module
imports them. The Axum shipped-modules test is formatted as cargo fmt
wants.
…nd the rollout of the renames

Review round 1 approved the design with no blocking issues and found
gaps in what it covered. The design now names the four adapters, the
integration tests crate and the three list functions with where each is
exported, says what a deployment that keeps the stock set sees, and says
that deploy validation never builds the registry, so a wrong description
is refused only at startup and then stops the whole service. It gives
the rollout of the renamed selectors, the renamed packages and the seam
probe's names, what ts audit reads and writes, and the two things with
no test. It defines iabtl and the stack, puts the renames in the title,
and records the pull requests now raised and the review round.
Review round 2 found no blocking issues. The design no longer claims a
test for ts audit leaving out a middleware described for another media
type and lists that as a third untested item, records the three small
changes left for a later change, and carries the round 2 entry in its
review log and revision record. The changelog entries for the module
list and the middleware list no longer say the removed crate holds
them.
@jwrosewell
jwrosewell added this pull request to stack #1401 October 15, 2026 17:56
Comment thread crates/trusted-server-core/src/test_support.rs Fixed
@jwrosewell
jwrosewell removed this pull request from stack #1401 October 15, 2026 20:51
The config push tests from the config by host change read a pushed
document back with the stock module list from trusted-server-modules,
which this branch removes. They now use trusted_server_cli::linked_builders,
the list the ts command registers, as the audit diagnostics tests do.
… iabtl crate

The configuration rules guide's table of old names to new had no row for
the ads.txt module this branch renames from `ads-txt.sellers` to
`ads-txt.iabtl`. The table now has that row, covering `[ads-txt] modules`,
the module's table and the `[[fetch]]` entry that names its middleware.

The table also holds the `[tinybird]` row that the branch making auction
telemetry an analytics module adds, set in this branch's column widths, so
that merging the branch below into this one resolves to this table.

The APS guide's checks run the ad server's tests from
`trusted-server-ad-server-iabtl`, the package this branch renames from
`trusted-server-ad-server-mock`, and the APS crate's tests as the branches
below run them.
@jwrosewell
jwrosewell added this pull request to stack #1418 October 19, 2026 12:18
@jwrosewell
jwrosewell removed this pull request from stack #1418 October 19, 2026 16:30
@jwrosewell jwrosewell closed this Oct 19, 2026
@jwrosewell jwrosewell reopened this Oct 19, 2026
@jwrosewell
jwrosewell added this pull request to stack #1421 October 19, 2026 17:38
Code scanning reported the test's assertion message as cleartext logging of sensitive information (alert 218), because the test read the module id from a builder that declares secret settings, and code scanning treats any value read from such a builder as a secret. The test now passes DATADOME_INTEGRATION_ID, as the 51Degrees middleware test passes its BUILDER_ID, so the message holds no value read from that builder.
@jwrosewell
jwrosewell removed this pull request from stack #1421 October 19, 2026 18:29
@jwrosewell
jwrosewell added this pull request to stack #1422 October 19, 2026 19:20
@jwrosewell jwrosewell changed the title Each adapter lists the modules it links List linked modules in each adapter Oct 19, 2026
@jwrosewell
jwrosewell marked this pull request as ready for review October 19, 2026 20:24
Each adapter's shipped_module_builders() and the tool's
linked_builders() no longer carry
trusted_server_loading_cache_51degrees::builder(), and the four adapters
and the tool no longer depend on the module crate, so none of them
compiles fiftyone-caching. the_stock_build_links_no_loading_cache sits
beside each adapter's order test and fails if the list offers a loading
cache, and the order tests stop naming loading-cache.51degrees. Nothing
pinned the tool's list, so the tool gains the same guard and an order
test of its own.

The three tests in the Axum adapter's shipped_modules.rs that pinned the
stock loading cache give way to the Axum adapter's guard, and the module
crate's builder documentation says that no stock build links it.
@jwrosewell
jwrosewell removed this pull request from stack #1422 October 28, 2026 11:47
@jwrosewell
jwrosewell added this pull request to stack #1465 October 28, 2026 18:28

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.

A crate holds the list of modules on every adapter's behalf

2 participants