Skip to content

**Spec**: Separate creative click rewrite switch - #1249

Closed
dhruv8sh wants to merge 5 commits into
mainfrom
spec/1234-creative-click-rewrite-switch
Closed

dhruv8sh wants to merge 5 commits into
mainfrom
spec/1234-creative-click-rewrite-switch

Conversation

@dhruv8sh

@dhruv8sh dhruv8sh commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds the design spec and implementation plan for Make creative click rewriting a separate feature with its own switch #1234. The issue asks for the spec to be approved in its own PR before any implementation PR is opened.
  • The spec makes click wrapping a separate feature. Today one switch, [auction] rewrite_creatives, controls both asset proxying and click wrapping, so an operator can't keep first-party click tracking while leaving assets direct, or the other way round.
  • It settles the open decisions in the issue:
    • Switch: [auction] rewrite_clicks is an Option<bool>. When unset, it follows rewrite_creatives, so no existing config changes behavior on upgrade.
    • HTML fetched through /first-party/proxy: an explicit value applies there too, while unset keeps today's always-wrap behavior.
    • <base> removal and TSJS injection: both run when either switch is on.
    • TsCreativeConfig.clickGuard: stays client-only.
    • Coordination with Add a host allowlist for creative asset rewriting #1231: both plans contain the same shared normalizer and policy step, so whichever implementation lands first introduces it and the other skips it.

Changes

File Change
docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Design spec: problem, goals, design, resolved open decisions, test plan, rollout and rollback
docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md Step-by-step TDD implementation plan, including the shared step with #1231

Closes

Part of #1234. This PR adds only the spec and plan. The implementation PR will link the approved spec and close the issue.

Test plan

  • 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: prettier --config docs/.prettierrc --check on both files. This PR changes no code, so no Rust or JS gates were run. The plan was checked by implementing it in a local branch, where fmt, all clippy aliases, test-fastly, test-fastly-reuse, test-axum, test-cloudflare, test-spin, the CLI tests and the parity tests passed. That code is not included here.

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

Spec and implementation plan for #1234: an [auction] rewrite_clicks switch that follows rewrite_creatives when unset, so click wrapping can be controlled independently of asset rewriting.

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
@dhruv8sh dhruv8sh self-assigned this Oct 7, 2026
@dhruv8sh dhruv8sh changed the title Add design spec for separate creative click rewrite switch **Spec**: Separate creative click rewrite switch Oct 7, 2026
Describe the review fixes: the extended shared-step CHANGELOG entry and the sign status change, rollback in both directions, the reworded Auction Rewrite Control docs and renderGuard note, the fuller body-less matrix fixture, the exact default-output pin, and the stronger proxied-HTML test.

Signed-off-by: dhruv8sh <dhruv8sh@proton.me>
@prk-Jr prk-Jr mentioned this pull request Oct 8, 2026
5 of 14 tasks

@prk-Jr prk-Jr 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

Spec and plan for #1234's [auction] rewrite_clicks. The design holds up well: the plan was applied verbatim to main (d8937e1) and every Rust block compiled, passed fmt, clippy-fastly and clippy-cli; every claimed pass count matched exactly (16 / 15 / 554 — also under Viceroy 0.17.0 — / 2 / 2); the red steps fail where predicted; both MATRIX_DEFAULT_*_OUTPUT constants match main byte for byte; and the normalizer leaves tsurl/tstoken identical for edge inputs (uppercase host, :443, spaces, é, IDN, tabs). Cited files are unchanged between 7a0ecb4c and main. Two blocking items are doc-accuracy problems that would flow into operator docs.

13 of the inline comments below carry a one-click GitHub suggestion — use Commit suggestion (or Add suggestion to batch) to apply them. The remaining comments describe the fix in prose because it spans several places. All suggestions were applied together and checked with the pinned docs prettier.

Blocking

🔧 wrench

  • Doc-update list misses text that becomes false — see inline at docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md:482
  • renderGuard caveat is wrong for the sandboxed renderer — see inline at docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md:344 and docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md:1712

Non-blocking

🤔 thinking

  • <base> removal in single-feature modes — see inline at spec :342
  • Public wrappers bypass both switches — see inline at spec :305

♻️ refactor

  • Task 1 red steps can't be observed — see inline at plan :637

⛏ nitpick

  • Step 5 grep can never pass — plan :651
  • "Unchanged output" vs the shared step's Fixed items — spec :26, plan :22
  • Task 0 has no one-match case — plan :310
  • Suffix-spoof case dropped from the policy test — plan :352
  • Private intra-doc link warning — plan :92
  • Step 8 wording replaces the wrong span — plan :1363
  • Click guard isn't fully inert — spec :357
  • "Without allocating" — spec :176
  • Commit instructions vs CONTRIBUTING.md — plan :35

Cross-cutting / body-level findings

  • ⛏ Smaller precision items
    • Citations off by one or two: spec :38 (proxy.rs:1898-1906), :229 (1672-1703, matching the plan), :486 (endpoints.rs:84-90), :487 (formats.rs:375-378).
    • The shared CHANGELOG Fixed entry (plan :290) leaves out that unparseable quoted URLs in <style>/style= are no longer re-quoted via cssparser::serialize_string, and that /first-party/sign error text changes (invalid url / unsupported scheme → unsupported url). "Re-quoted" also understates the old fallback: // input was emitted https:-prefixed (src=" //exa mple.example/x " → https://exa mple.example/x).
    • Because settings serialize normalized, the first ts config push after upgrading shows a blob diff for configs with mixed-case/whitespace/""/* exclude entries — worth one line in Rollout.
    • Expected files (spec :491) omits auction/orchestrator.rs and auction/endpoints.rs.
    • Spec :372's provenance sentence reads as if #1231's text lacks the four tests; #1248's plan already has them.
    • Spec :107-115 vs plan :886-896 doc comments differ (plan adds the "rejected by binaries that predate this field" clause); spec :122 vs plan :902 likewise.
    • Plan :39: Viceroy 0.21.1 vs pinned 0.17.0 (re-run under 0.17.0 gives the same counts).
    • PR checklist: the tracing box should read log.
  • 🌱 Staged / multi-service rollback — spec :467: a blob pushed with --staging that carries rewrite_clicks also has to be re-pushed without it before rolling back a staged binary, once per service.
  • 📌 Trailing-dot hosts bypass exclude_domains (pre-existing) — https://excluded.example.com./x is still proxied and wrapped in both old and new code (reproduced). Not for this PR; same follow-up as noted on #1248.
  • 👍 Praise
    • The plan is executable as written, with exact counts and byte-exact pins.
    • Gating is complete: the anchor handler is the only producer of click URLs, apart from rebuild of already-signed input.
    • Keeping rewrite_clicks commented out in the example TOML is the right call, since ts config init copies it.
    • Option<bool> with per-path resolution keeps both existing operator groups unchanged.

CI Status

  • All 22 checks PASS: Analyze (actions / javascript-typescript / python / rust), CodeQL, CLAUDE.md symlink guard, browser integration tests, integration tests, integration tests (Fastly EC lifecycle), prepare integration artifacts, cargo fmt, cargo test, cargo test (axum native), cargo test (cross-adapter parity), cargo check (cloudflare native + wasm32-unknown-unknown), cargo check/build/test (spin native + wasm32-wasip1), cargo test (ts CLI, native) (macos-latest / ubuntu-latest), vitest, format-typescript, format-docs

Comment thread docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Outdated
Comment thread docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md Outdated
Comment thread docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md Outdated
Comment thread docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md Outdated
Comment thread docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Outdated
Comment thread docs/superpowers/plans/2026-10-07-1234-creative-click-rewrite-switch.md Outdated
Comment thread docs/superpowers/specs/2026-10-07-1234-creative-click-rewrite-switch-design.md Outdated
@aram356
aram356 marked this pull request as draft October 9, 2026 05:27
@aram356

aram356 commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

@dhruv8sh please merge into implementation PR #1252

Correct the renderGuard caveat for the sandboxed /auction renderer, list the
operator docs that become false, keep a bidder <base target> while dropping
its href, and warn on the public rewrite wrappers.

Also fix citations, the shared CHANGELOG Fixed wording, red-step ordering,
the Step 5 grep, rollout and staged rollback notes, and other precision items.

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

Copy link
Copy Markdown
Collaborator Author

Closing in favor of #1252

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

3 participants