Skip to content

Add cache-header audit design spec for ts origin audit-headers - #930

Merged
aram356 merged 13 commits into
IABTechLab:mainfrom
vasujain00:spec/834-audit-headers
Oct 8, 2026
Merged

aram356 merged 13 commits into
IABTechLab:mainfrom
vasujain00:spec/834-audit-headers

Conversation

@vasujain00

@vasujain00 vasujain00 commented Jul 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Changes

File Change
docs/superpowers/specs/2026-07-14-cache-header-audit-design.md Design spec: command surface and exit codes, per-URL response model, effective browser and shared-cache policy with TS overrides, discovery and origin routing, rules, output contract, CLI integration, tasks

Closes

Closes #835

Test plan

  • Docs format: cd docs && npm run format (prettier 3.8.1, the lockfile version, on the spec)
  • Other: compiled the §9.1 OriginCommand shape against the workspace's clap 4.6.1
  • Other: checked each cited API (asset_route_for_path, origin_host_header, asset_cache_policy_for_path, enforce_set_cookie_cache_privacy, match_slots, tls::install_crypto_provider, the template-cache gate) against main

Checklist

  • Changes follow CLAUDE.md conventions
  • No secrets or credentials committed

@aram356 aram356 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

The spec is a solid starting shape for ts dev audit headers (clear taxonomy, verdict rollup, task breakdown), but several load-bearing claims about the codebase are stale or incorrect — ts dev is already a subcommand tree, there is no CliError enum, reqwest is not a CLI dependency, and the discovery section probes edge-only /_ts/ routes against the publisher origin. Two cacheability rules also fail the strictest correct configuration, and the doc itself is what's breaking the format-docs CI check.

Details are in the inline comments (8 blocking 🔧, 5 🤔, 1 ♻️, 2 🌱, 2 ⛏). Cross-cutting items below.

Blocking

🔧 wrench

  • format-docs CI failure: prettier rejects this file's tables — cd docs && npm run format:write (line 30)
  • Dependency graph must be mermaid: docs use vitepress-plugin-mermaid; ASCII art won't render (line 391)
  • Stale ts dev premise: DevCommand subcommand tree already exists on main; no Serve to default to (lines 254, 289)
  • CliError doesn't exist: CLI errors are CliResult<T> = Result<T, String> (line 271)
  • reqwest is not a CLI dep + target scoping unaddressed: workspace default target is wasm32-wasip1; spec must say where deps are scoped and that audit is cross-platform, unlike the macOS-only proxy (line 323)
  • Discovery probes edge routes against origin: /_ts/* paths 404 on publisher.origin_url (line 131)
  • Wrong issue link: #293 text links to /issues/834 (line 7)
  • HTML/RTB rules fail no-store alone: RFC 9111's strongest posture would FAIL the audit (lines 75, 106)

Non-blocking

📌 out of scope

  • Plan document and epic breakdown still pending: issue #835 asks for a spec and a plan under docs/superpowers/plans/ plus a task breakdown in epic #834; this PR delivers the spec only (Section 10 is a partial plan). Also, the PR body retains the unfilled template (empty Summary/Changes tables, dangling Closes #).

CI Status

  • format-docs: FAIL (caused by this file)
  • All other checks (fmt, clippy targets, Rust/JS tests, integration, parity, CodeQL): PASS

ChristianPavilonis

This comment was marked as low quality.

@ChristianPavilonis
ChristianPavilonis requested review from ChristianPavilonis and removed request for ChristianPavilonis August 14, 2026 18:52
Vasu Jain added 2 commits August 21, 2026 11:38
Technical spec for epic IABTechLab#834: origin cache-header audit with
per-content-type cacheability diagnostics. Covers content-type
taxonomy, cacheability rules for all five directives (Cache-Control,
Surrogate-Control, Surrogate-Key, Vary, ETag), per-type verdict
rollup, CLI integration into the ts dev group, and a 7-task
implementation breakdown.

Closes IABTechLab#835
Resolves all 8 blocking 🔧 items from @aram356's review:

1. format-docs CI: ran prettier (tables now padded correctly)
2. Dependency graph: replaced ASCII art with mermaid flowchart
3. Stale ts dev premise: rewrote §8.1 to add Audit variant to existing
   DevCommand enum (no Serve default, no DevArgs invention)
4. CliError: corrected §8.2 to use existing CliResult<T>/cli_error() pattern
5. reqwest scoping: added §8.3 explaining cfg(not(wasm32)) dep scoping
   and cross-platform requirement for audit (unlike macOS-only proxy)
6. Discovery probes: rewrote §5 to HTML-parse origin root page instead
   of probing edge-only /_ts/ routes against origin
7. Issue link: fixed [IABTechLab#293] to link to IABTechLab/issues/293 (was linking IABTechLab/issues/834)
8. HTML/RTB no-store rules: no-store alone now passes per RFC 9111 §5.2.2.5

Non-blocking items also addressed:
- Verdict: changed to unit enum (messages on HeaderVerdict)
- Author: corrected @Vasujai to @vasujain00
- s-maxage: added to audited headers with explanation
- Vary: now evaluated on all cacheable groups (not just HTML)
- application/woff*: removed (redundant with font/*)
- Content-Type param stripping: documented in §3
- Module path: corrected to commands/dev/audit/headers/
@vasujain00
vasujain00 force-pushed the spec/834-audit-headers branch from cf69725 to e268913 Compare August 21, 2026 18:53
@aram356

aram356 commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

@vasujain00 Thank you for addressing Please implement it per spec. You can use this pr for the implementation as well.

@aram356 aram356 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

The round-1 blockers on the mermaid graph, the DevCommand premise, CliResult, bare no-store, and the #293 link are resolved. Since that round, main has changed under the spec: TS now sets HTML cache privacy itself, has an opt-in template cache and operator asset rules, and documents the CLI's exit codes and --json conventions. Several rules now contradict shipped behavior, and three design gaps (redirects, edge-vs-browser policy, per-URL results) would have the tool grade responses TS never serves. Most of the fixes land in §4, §5 and §7.2.

9 of the inline comments below carry a one-click GitHub suggestion. Use Commit suggestion (or Add suggestion to batch for several at once) to apply them as commits on the PR branch. The remaining comments describe the fix in prose because it spans several sections of the spec.

Blocking

🔧 wrench

  • HTML rule fails correct configs and disables the template cache: see inline at 2026-07-14-cache-header-audit-design.md:77-80
  • Rules grade Cache-Control as the edge policy (Surrogate-Control, CDN-Cache-Control, Age, Expires ignored): see inline at 2026-07-14-cache-header-audit-design.md:71
  • immutable recommended for unfingerprinted JS/CSS/fonts: see inline at 2026-07-14-cache-header-audit-design.md:86
  • Exit code 2 collides with the CLI's tool-failure code: see inline at 2026-07-14-cache-header-audit-design.md:40-48
  • Audit requests don't match what TS sends to origin: see inline at 2026-07-14-cache-header-audit-design.md:142-143
  • Following redirects grades a different response than TS receives: see inline at 2026-07-14-cache-header-audit-design.md:457
  • No per-URL record: verdicts can't name the URL; errors and status codes unmodeled: see inline at 2026-07-14-cache-header-audit-design.md:228-243
  • Set-Cookie isn't audited, and it overrides every other cache header: see inline at 2026-07-14-cache-header-audit-design.md:67
  • RTB bullet still routes discovery to an edge-only route: see inline at 2026-07-14-cache-header-audit-design.md:141-145
  • §4.6 still conflates request-side If-None-Match (#428); Last-Modified missing: see inline at 2026-07-14-cache-header-audit-design.md:117-122
  • §8.3's reqwest = { workspace = true } makes ts dev proxy panic: see inline at 2026-07-14-cache-header-audit-design.md:296

Non-blocking

  • 🤔 All application/json graded as RTB: see inline at 2026-07-14-cache-header-audit-design.md:62
  • 🤔 Placement: ts audit is now the audit group: see inline at 2026-07-14-cache-header-audit-design.md:314
  • ♻️ Reuse AppConfigArgs instead of a new --config: see inline at 2026-07-14-cache-header-audit-design.md:38
  • 🤔 Bare no-store: citation doesn't say "sufficient"; advise adding private: see inline at 2026-07-14-cache-header-audit-design.md:115
  • 🤔 Missing Surrogate-Key WARNs every non-Fastly deployment; message is inaccurate: see inline at 2026-07-14-cache-header-audit-design.md:88
  • 🤔 Discovery can't reach parts of the taxonomy: see inline at 2026-07-14-cache-header-audit-design.md:138-140
  • 🤔 Fetcher has no host allowlist, limits, or output escaping: see inline at 2026-07-14-cache-header-audit-design.md:363
  • ⛏ §8.1 snippet needs #[command(subcommand)]: see inline at 2026-07-14-cache-header-audit-design.md:277-278
  • ⛏ Cross-platform rationale misstates the dependency facts: see inline at 2026-07-14-cache-header-audit-design.md:288
  • ⛏ s-maxage is a directive, not a header: see inline at 2026-07-14-cache-header-audit-design.md:69
  • ⛏ Real domain in examples (human output): see inline at 2026-07-14-cache-header-audit-design.md:156
  • ⛏ Real domain in examples (JSON): see inline at 2026-07-14-cache-header-audit-design.md:175-179
  • ⛏ Task wiring details (args location, cfg cleanup, output writer): see inline at 2026-07-14-cache-header-audit-design.md:215
  • 🌱 Test fixture reuse, acceptance cases, docs sidebar: see inline at 2026-07-14-cache-header-audit-design.md:412

Cross-cutting / body-level findings

  • 📝 PR description is still the unfilled template: the Summary and Changes table are empty, and there's a dangling Closes # below the real Closes #835. Worth filling in, especially if this PR will also carry the implementation.

CI Status

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

prk-Jr
prk-Jr previously requested changes Oct 1, 2026

@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

The design document is unchanged since the September 24 review. Material specification issues remain in asset caching recommendations, HTML policy, effective cacheability, origin routing, dependency features, exit statuses, and result attribution. These need correction before this specification guides implementation.

This review contains seven blocking findings and one non-blocking documentation correction, all expressed as prose comments.

Blocking

  • Avoid enabling a second rustls crypto provider — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:301
  • Gate immutable caching on verified versioned URLs — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:86
  • Separate HTML privacy from origin-template eligibility — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:77
  • Evaluate effective browser and shared-cache policies — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:71
  • Preserve configured origin routing and Host overrides — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:142
  • Reserve a distinct exit status for incomplete audits — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:48
  • Keep verdicts associated with individual sampled URLs — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:228

Non-blocking

  • Mark the nested clap subcommand — see inline at docs/superpowers/specs/2026-07-14-cache-header-audit-design.md:278

Validation

  • All 19 reported GitHub checks pass.
  • The changed document passes local Prettier checking.
  • Isolated dependency-feature and rustls builder reproductions confirm the crypto-provider conflict; the single-provider reproduction succeeds.
  • The corrected nested clap derive compiles.
  • The full runtime suite was not rerun locally for this documentation-only PR.

CI Status

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

Address the September 24 and October 1 review feedback, and rebase the
design on what main now ships.

- Move the command to `ts origin audit-headers`, next to
  `probe-shareability`, and defer the HTML shareability verdict to the probe.
- Evaluate browser and shared-cache policy separately, with per-runtime
  precedence (Surrogate-Control, CDN-Cache-Control, Expires, Age), and apply
  TS overrides: asset rules, cookie privacy, and ad-serving and readthrough
  paths.
- Recommend `immutable` only for fingerprinted URLs, audit Set-Cookie and
  validators (ETag or Last-Modified), and drop the request-side IABTechLab#428 framing.
- Map URLs through asset routes and the Host override, never follow
  redirects across hosts, grade 3xx and error responses, and bound fetches.
- Model per-URL results with status and errors, align JSON with
  `ts audit ad-templates verify`, and use exit codes 0/1/2 with --strict.
- Reuse the CLI's existing reqwest client and rustls provider install
  instead of the workspace reqwest dependency.
- Replace real domains with example domains, and rework tasks, tests, and
  open questions accordingly.
@aram356 aram356 changed the title Add cache-header audit design spec for ts dev audit headers Add cache-header audit design spec for ts origin audit-headers Oct 8, 2026
@aram356
aram356 requested review from aram356 and prk-Jr and removed request for ChristianPavilonis October 8, 2026 05:02
@aram356
aram356 dismissed stale reviews from prk-Jr, ChristianPavilonis, and themself October 8, 2026 05:03

Merging since implementation started

@aram356 aram356 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.

Merge

@aram356
aram356 merged commit d8937e1 into IABTechLab:main Oct 8, 2026
27 of 28 checks passed
vasujain00 pushed a commit to vasujain00/trusted-server that referenced this pull request Oct 25, 2026
…BTechLab#930)

Addresses round-3 blockers IABTechLab#4, IABTechLab#5, IABTechLab#6 and splits IABTechLab#7.

IABTechLab#4 placement: the merged design spec (IABTechLab#930, docs/superpowers/specs/
2026-07-14-cache-header-audit-design.md §34) places this command at
`ts origin audit-headers`, beside `ts origin probe-shareability`. Moved the
module from commands/dev/audit/headers to commands/origin/audit_headers,
removed the DevAuditCommand group, and added an AuditHeaders variant to
OriginCommand. URLs now arrive through a repeatable --url (probe convention),
not positional args.

IABTechLab#5 exit codes: dropped the bespoke exit-code 3 and the process::exit call.
The report now maps to RunOutcome (AssertionFailed on a FAIL, or a WARN under
the new --strict flag; Success otherwise), returned through dispatch like every
other command. main exits 2 for transport/config errors (Err), so a warn-only
audit is never confused with one that could not run. Matches spec §59-69.

IABTechLab#6 transport safety: explicit --url, the resolved origin root, and discovered
assets all pass through the shared crate::url_guard::require_credential_safe_
transport used by probe-shareability -- HTTPS required except on loopback, no
URL-embedded credentials. Discovery is additionally restricted to http/https
assets, so file:/javascript:/data: links pulled from fetched HTML are dropped.

IABTechLab#7 core-aware grading (Spec Task 1) is deliberately NOT in this change -- it
spans trusted-server-core and is tracked as a follow-up (noted in the PR
description). This command ships the generic ruleset.

Docs: cli.md updated to the new command surface, --strict, and the 0/1/2
exit-code table. 776 CLI tests pass, clippy -D warnings clean, fmt + prettier
clean.
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.

Create spec and plan to audit publsher origin headers

4 participants