Make the SSAT debug comment configurable - #943
Conversation
…edundant closures)
…nt-config # Conflicts: # crates/trusted-server-core/src/publisher.rs # crates/trusted-server-core/src/settings.rs
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Summary
🔧 Requesting changes because the new default configuration serialization breaks rollback and mixed-version deployment compatibility. One P1 inline finding is included.
aram356
left a comment
There was a problem hiding this comment.
Summary
Adds [debug.auction_html_comment_options] — section toggles, a metadata_keys subset selector, a redacted/upstream/full verbosity ladder, and compact/pretty formatting — replacing the old single hardcoded allowlist. The security design is sound: the redacted-mode schema validation matches exactly what orchestrator.rs and prebid.rs actually write, all six upstream keys have real writers, the dropped "status" allowlist key has no production writer, and terminator neutralization plus the 256 KiB cap are exercised across every verbosity × format combination. One blocking config-validation gap and three smaller items, all inline.
Blocking
🔧 wrench
- Unknown
metadata_keysentries are silently dead config: validate membership inAUCTION_DEBUG_METADATA_ALLOWLISTat config load (crates/trusted-server-core/src/settings.rs:2007)
Non-blocking
♻️ refactor
error_typeliterals duplicated fromorchestrator.rs: reuse theERROR_TYPE_*constants to prevent drift (crates/trusted-server-core/src/publisher.rs:1895)
⛏ nitpick
metadata_keysdocs omit its Upstream-mode behavior: it still gates the three base keys inupstreammode (crates/trusted-server-core/src/settings.rs:1966,docs/guide/auction-orchestration.md:863)- Guide recipe pairs
metadata_keyswithverbosity = "full", where the field has no effect (docs/guide/auction-orchestration.md:842)
CI Status
- GitHub checks: pending at review time (fresh push)
- fmt (local): PASS
- targeted rust tests, new settings + publisher tests via
cargo test-fastly(local): PASS (11/11)
Omit the default `[debug.auction_html_comment_options]` table from serialized config blobs so an older binary's `deny_unknown_fields` `DebugConfig` still accepts a pushed blob during a mixed-version deployment or rollback. A non-default table still serializes. Reject `metadata_keys` entries outside the fixed allowlist at config load instead of silently rendering an empty metadata object, keeping the render-time intersection as defense-in-depth. Validate and describe redacted error classifications through the orchestrator's `ERROR_TYPE_*` constants, with a test that fails when a new classification ships without safe wording. Document that `metadata_keys` also gates the three validated keys in upstream mode and is ignored in full mode, and drop it from the full-verbosity recipe where it has no effect.
* Fix dead links breaking the docs deploy The VitePress build on main has been failing since #943 landed, and PR #1013 added more breakage on top of it. Nineteen dead links across three files: - Twelve links in the SSAT debug comment design point into the source tree via `../../../crates/...`. Those targets sit outside the VitePress root, so they can never resolve. Rewrite them as inline code spans, matching the 172 source references already written that way under `docs/superpowers/`. - Seven links in the archived ESI spike documents kept a `./` prefix after the documents moved into `superpowers/archive/`. Every target exists one directory over, in `superpowers/plans/` or `superpowers/specs/`. `npm run build` in `docs` now completes instead of reporting dead links. * Gate the docs build in CI The VitePress build is the only check that catches dead links, and `deploy-docs.yml` runs it on push to main alone. Docs breakage therefore stays invisible until it has already landed, which is how nineteen dead links accumulated across two merges. Run the build in the existing `format-docs` job instead. That job already runs on pull requests, already installs the `docs` dependencies, and is already one of the required status checks, so dead links become a merge blocker with no ruleset change. Leaving `deploy-docs.yml` alone also keeps its `pages: write` permission off pull request events. Verified the gate fails closed: a deliberate dead link exits 1 with `[vitepress] 1 dead link(s) found`, and the build completes once removed.
Resolve ten conflicts from main's three commits after the #860 merge base. #943 and #1013 reached main as squashes after rc had already merged earlier revisions of the same branches, and #1066 is new to rc. Take main where its commit is the newer revision: - Fastly `apply_terminal_response_effects`: `must_remain_private` narrows back to the `TerminalPrivateResponse` marker, so an unmarked origin `private, max-age=600` keeps its own policy and validators instead of being overwritten. The terminal guard runs both `enforce_set_cookie_cache_privacy` and `enforce_uncacheable_cache_privacy`. Adds main's three review tests for page-bids preflight, active diagnostics, and the unmarked-origin case, while keeping rc's `resolve_and_sanitize_client_ip` block. - The three `docs/superpowers` documents: #1066's dead-link fixes, with no other difference between the two versions. Keep rc where it is the functional superset, after confirming no line main added is missing from it: - `response_privacy.rs` keeps #1008's inactive-ad-stack browser policy, the quoted-string-aware directive parser, and the public `is_private_or_no_store`; main's two new edge-cache-header tests are grafted on. - `publisher.rs` keeps `PageBidsFormat::parse`, which supersedes main's inline `format` rejection, and the assembled-response privacy condition that already covers main's narrower form. - `creative_opportunities.rs` and `scripts/template-cache-local-test.sh`. Two artifacts of the automatic merge needed correcting: `settings.rs` gained ten duplicate `#[test]` definitions from the #943 squash meeting rc's native merge, which `cargo check` cannot see because it does not build tests, and `configuration.md` had a duplicated shared-template heading. `Cache-Control` keeps rc's `private, no-store` ordering. #1013's final revision flipped the `enforce_private_no_store` path to `no-store, private`; directive order carries no meaning, rc asserts the current spelling in 34 places, and the CI shell harness greps the literal string. Main's grafted assertions were adapted instead. The JA4 debug endpoint keeps its own `no-store, private` literal.
Summary
[debug.auction_html_comment_options]for controlling SSAT<!-- ts-debug: ... -->auction comments: provider/mediator/bid section toggles, a fail-closed metadata subset, sensitivity modes, and compact or pretty outer JSON formatting.redacted(default, schema-validated server-owned diagnostics),upstream(six named provider-controlled diagnostics), andfull(raw response metadata and untruncated creatives for local investigation).Configuration
format = "pretty"indents the outer auction dump for easier navigation. Nested JSON-looking values such as PBSrequestbodyandresponsebodyremain strings exactly as captured.upstreamandfullcan expose request or identity data and must not be enabled in production.Security model
redacted,metadata_keyscan only narrow the fixed Rust allowlist; it cannot expose arbitrary keys such as PBSdebug.error_typeandhttp_statusare schema-validated, andmessageis generated from fixed server-owned wording rather than copied from a provider.upstreamorfull.debug.httpcallsandresolvedrequestrequirefull.Main changes
crates/trusted-server-core/src/settings.rsAuctionDebugCommentVerbosity, andAuctionDebugCommentFormatwith backward-compatible defaultscrates/trusted-server-core/src/publisher.rstrusted-server.example.tomldocs/guide/auction-orchestration.mddocs/superpowers/specs/docs/superpowers/plans/Closes
Closes #935
Test plan
cargo fmt --all -- --checkcargo test-fastlycargo test-axumcargo test-cloudflarecargo test-spincargo clippy-fastlycargo clippy-axumcargo clippy-cloudflarecargo clippy-cloudflare-wasmcargo clippy-spin-nativecargo clippy-spin-wasmChecklist
CLAUDE.mdconventions