Skip to content

Make creative click rewriting a separate switch - #1252

Draft
dhruv8sh wants to merge 6 commits into
spec/1234-creative-click-rewrite-switchfrom
feat/1234-creative-click-rewrite-switch
Draft

dhruv8sh wants to merge 6 commits into
spec/1234-creative-click-rewrite-switchfrom
feat/1234-creative-click-rewrite-switch

Conversation

@dhruv8sh

@dhruv8sh dhruv8sh commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Makes creative click wrapping its own feature. [auction] rewrite_clicks controls <a href> and <area href> wrapping into signed /first-party/click redirects, and rewrite_creatives now controls asset URLs only. Operators can keep first-party click tracking with assets left direct, or proxy assets with landing links left alone.
  • rewrite_clicks is an Option<bool>, and unset is the default:
    • Auction creatives follow rewrite_creatives, so no existing config changes behavior on upgrade.
    • HTML fetched through /first-party/proxy keeps wrapping links as it does today.
    • An explicit value applies to every path.
    • <base> removal and TSJS injection run when either switch is on.
  • Introduces the normalizer and host-policy split that Add a host allowlist for creative asset rewriting #1231 builds on:
    • to_abs is replaced by normalize_creative_url plus Rewrite::should_proxy_asset and Rewrite::should_wrap_click.
    • exclude_domains matching is now case-insensitive and trimmed.

Implements the approved design in #1249: docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md.

Stacked PR. The base is spec/1234-creative-click-rewrite-switch (#1249), so this diff shows only the implementation. Merge #1249 first; GitHub then retargets this PR to main. Use git diff -w when reading creative.rs, because gating the handlers re-indents a large block.

Changes

File Change
crates/trusted-server-core/src/auction_config_types.rs rewrite_clicks: Option<bool> (left out of the blob when unset), rewrites_auction_clicks(), rewrites_proxied_clicks(), tests
crates/trusted-server-core/src/creative.rs normalize_creative_url, asset_target/click_target, CreativeFeatures. Asset and anchor handlers are registered only when their switch is on. Caller wiring, module docs, the four-combination matrix tests, and a byte-for-byte pin against main's output
crates/trusted-server-core/src/settings.rs Rewrite::should_proxy_asset, should_wrap_click and normalize (trim, lowercase, drop inert entries); removes is_excluded; tests
crates/trusted-server-core/src/proxy.rs /first-party/sign uses the normalizer and policy; proxied-HTML click tests
crates/trusted-server-core/src/config_payload.rs Blob round-trip and legacy-blob tests
crates/trusted-server-core/src/auction/formats.rs, publisher.rs End-to-end /auction and inline tests; doc and log updates
crates/trusted-server-core/src/auction/orchestrator.rs New field in the full AuctionConfig literal
crates/trusted-server-core/src/auction/endpoints.rs, auction/README.md Doc updates
crates/trusted-server-cli/tests/config_env_overlay.rs Pins the TRUSTED_SERVER__AUCTION__REWRITE_CLICKS override behavior, with and without the TOML leaf
trusted-server.example.toml rewrite_creatives comment narrowed to assets; commented-out rewrite_clicks line with rollout notes
docs/guide/configuration.md, creative-processing.md, auction-orchestration.md, api-reference.md Operator docs: switch matrix, proxied-HTML rule, clickGuard vs rewrite_clicks, rollout and rollback
CHANGELOG.md Added rewrite_clicks; Fixed case-insensitive exclude_domains and the related edge cases

Closes

Closes #1234

Test plan

  • cargo test-fastly && cargo test-axum. Also cargo test-fastly-reuse, cargo test-cloudflare, cargo test-spin, ./scripts/test-cli.sh and the parity tests.
  • cargo clippy-fastly && cargo clippy-axum. All 8 clippy aliases pass, and every intermediate commit passes clippy-fastly.
  • 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: cd docs && npm run format, plus the markdown prettier check outside docs/
  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve
  • Other: every new behavior test was seen failing before it was implemented. A table mapping each spec completion criterion to its test is in the plan.

Rollout: deploy the binary first; behavior is unchanged while rewrite_clicks is unset. Then push a config that sets it. Rollback: remove any explicit rewrite_clicks and push first, then roll back the binary.

Checklist

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

Replace to_abs with normalize_creative_url and move exclusion policy to Rewrite::should_proxy_asset and Rewrite::should_wrap_click, sharing the case-insensitive proxy host matcher. Normalize exclude_domains at load. This is the shared step for #1231 and #1234.

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

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
The rewrite pass registers asset handlers only when rewrite_creatives is on and the anchor handler only when click rewriting resolves on. Base removal and TSJS injection run whenever either is on.

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

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

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
@dhruv8sh dhruv8sh self-assigned this Oct 7, 2026
@dhruv8sh dhruv8sh linked an issue Oct 7, 2026 that may be closed by this pull request
8 tasks
@aram356
aram356 marked this pull request as draft October 8, 2026 15:50

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.

Make creative click rewriting a separate feature with its own switch

1 participant