From 25a4c24b48f5364f000ea127b2a4c9e85b4b4367 Mon Sep 17 00:00:00 2001 From: jevansnyc Date: Wed, 1 Apr 2026 12:57:55 -0500 Subject: [PATCH] Add JS Asset Proxy and Auditor engineering specs Product specs for the JS Asset Proxy feature (IABTechLab/trusted-server#603). Includes the original PRD and two engineering design documents covering: - JS Asset Proxy: config schema, KV data model, fetch/cache pipeline, HTML head injection, security hardening, and Fastly provisioning steps - JS Asset Auditor: Claude Code slash command that sweeps a publisher page via Chrome DevTools MCP and generates/diffs js-assets.toml Co-Authored-By: Claude Sonnet 4.6 --- docs/js-asset-proxy-prd.md | 356 ++++++++++++++++++ .../2026-04-01-js-asset-auditor-design.md | 216 +++++++++++ .../specs/2026-04-01-js-asset-proxy-design.md | 302 +++++++++++++++ 3 files changed, 874 insertions(+) create mode 100644 docs/js-asset-proxy-prd.md create mode 100644 docs/superpowers/specs/2026-04-01-js-asset-auditor-design.md create mode 100644 docs/superpowers/specs/2026-04-01-js-asset-proxy-design.md diff --git a/docs/js-asset-proxy-prd.md b/docs/js-asset-proxy-prd.md new file mode 100644 index 00000000..c5a01d54 --- /dev/null +++ b/docs/js-asset-proxy-prd.md @@ -0,0 +1,356 @@ +# Product Requirements: First-Party JS Asset Proxy + +**Status:** Draft +**Author:** Trusted Server Product +**Last updated:** 2026-03-26 + +--- + +## Table of Contents + +1. [Overview](#1-overview) +2. [Problem Statement](#2-problem-statement) +3. [Goals and Non-Goals](#3-goals-and-non-goals) +4. [Target Customers](#4-target-customers) +5. [Opaque URL Routing](#5-opaque-url-routing) +6. [KV Asset Cache](#6-kv-asset-cache) +7. [HTML Script Tag Injection](#7-html-script-tag-injection) +8. [Cache Lifecycle](#8-cache-lifecycle) +9. [Configuration](#9-configuration) +10. [Routes](#10-routes) +11. [Security](#11-security) +12. [Open Questions](#12-open-questions) +13. [Success Metrics](#13-success-metrics) + +--- + +## 1. Overview + +The JS Asset Proxy allows Trusted Server to fetch third-party JavaScript files from configured origin URLs, cache them in Fastly or similar KV Store under opaque first-party paths, and serve them from the publisher's own domain. When running in full HTML proxy mode, TS also injects the corresponding ` + + +``` + +### 7.2 TS Lite mode (HTML proxy disabled) + +TS does not modify HTML responses. The publisher hardcodes the opaque ` +``` + +### 7.3 Tag attributes + +The injected or hardcoded tag has no `async` or `defer` attributes by default. Ad tech bootstrapper scripts (Prebid loaders, vendor loaders) are render-blocking by design — they must execute before GPT slot definitions and auction calls. The ad tech partner controls whether their subsequently loaded scripts are async/defer. + +--- + +## 8. Cache Lifecycle + +### 8.1 Initial TTL + +**1 hour (3600 seconds)** for v1. This matches the most common `Cache-Control: max-age=3600` from ad tech CDN origins. The TTL is configurable per asset entry in `trusted-server.toml` to accommodate partners with different cache policies. + +### 8.2 ETag-based conditional refresh + +On TTL expiry, TS issues a conditional `GET` with `If-None-Match: {stored_etag}` to the origin. A `304 Not Modified` response costs only a TCP roundtrip — no body is transferred. The KV body is reused as-is, and only the metadata `expires_at` is updated. This is the expected common case: vendor files are typically updated daily, not hourly. + +### 8.3 Cache warming + +On first request after deployment (cold KV), the origin fetch adds latency to that one request. This is acceptable for v1. A pre-warm step (fetching and populating KV at service deploy time) is a follow-on improvement. + +### 8.4 Manual invalidation + +TS operators can force a cache bust by deleting the KV entry via the KV management API. The next request will treat it as a cold miss and fetch from origin. No binary redeploy required. + +--- + +## 9. Configuration + +New section in `trusted-server.toml`: + +```toml +[kv_stores] +js_asset_store = "golf-js-asset-store" # new, alongside ec_store and partner_store + +# One [[js_assets]] entry per proxied asset +[[js_assets]] +slug = "golf-WnLmpLyEjL:prebid-load" +path = "/sdk/gWnLmpLy.js" +origin_url = "https://web.prebidwrapper.com/golf-WnLmpLyEjL/default-v2/prebid-load.js" +ttl_sec = 3600 +inject_in_head = true # inject