Verify content rewriting pipeline is platform-agnostic (PR 8)#600
Conversation
…zero-pr8-content-rewriting
aram356
left a comment
There was a problem hiding this comment.
Summary
Documentation-only PR (plus one intra-doc link fix) that verifies the content rewriting pipeline is platform-agnostic. Core claims are accurate — html_processor, streaming_processor, streaming_replacer, and rsc_flight have zero fastly imports. Good separation of concerns that saves future adapter authors from implementing unnecessary abstractions.
Non-blocking
🤔 thinking
- Broken intra-doc link syntax in
html_processor.rs:12—`impl `[`StreamProcessor`]has an awkward space between backtick-wrappedimpland the link. Consider`impl` [`StreamProcessor`]or plain`impl StreamProcessor`. - Missing blank line before
useinhtml_processor.rs:17-18— The original file had a blank line between the doc block and imports. Lost in the edit; inconsistent withstreaming_processor.rswhich has the blank line.
♻️ refactor
publisher.rscaveat inplatform/mod.rs:31-37— The handler-coupling detail feels like it belongs inpublisher.rsitself rather than the platform module doc. Consider moving it there and keepingplatform/mod.rsfocused on what adapters need to know.
🌱 seedling
- PR number references in doc comments may age poorly — "PR 8", "PR 11", "PR 16/17" will be opaque without EdgeZero migration context. Consider more descriptive labels (e.g., "the HTTP-type migration" instead of "PR 11").
⛏ nitpick
StreamingPipeline::process<R: Read, W: Write>inplatform/mod.rs:27— Angle brackets are plain text, not a link or code. Should be wrapped in backticks or use an intra-doc link.
👍 praise
- Good call not introducing a
PlatformContentRewritertrait — the pipeline is already generic. - Nice catch fixing the unresolved
EdgeRequestdoc link.
CI Status
- integration tests: PASS
- browser integration tests: PASS
- prepare integration artifacts: PASS
- Fix intra-doc link syntax and restore missing blank line in `html_processor` - Replace opaque PR number references with descriptive context labels - Move HTTP-type coupling caveat from `platform` module down to `publisher.rs` - Convert `StreamingPipeline::process` plain-text generics to an intra-doc link
aram356
left a comment
There was a problem hiding this comment.
Summary
Documentation-only PR that verifies the content rewriting pipeline is platform-agnostic and documents this for future adapter authors. The doc comments are well-structured and the separation of concerns (platform-agnostic pipeline vs platform-coupled handler layer) is correctly captured.
Blocking
🔧 wrench
-
Unresolved intra-doc link:
StreamingPipeline::processinplatform/mod.rs:26does not resolve —StreamingPipelineis not in scope from theplatformmodule. This is a newcargo docwarning not present on the base branch. Needs the full path. -
Inconsistent PR number references:
streaming_processor.rsstill uses opaque "PR 8" (line 11) and "PR 16/17" (line 17) whilehtml_processor.rsandplatform/mod.rswere updated to descriptive labels in commit2333227. This file was missed.
Non-blocking
🤔 thinking
- 350-line plan document:
docs/superpowers/plans/2026-03-31-pr8-content-rewriting-verification.mdis an agentic implementation plan with task checkboxes and bash commands — 350 lines of process artifact for ~55 lines of doc comment changes. It also still contains opaque "PR 8"/"PR 11"/"PR 16/17" references. Is this pattern intended to be kept long-term, or should plans be cleaned up after the PR ships?
CI Status
- integration tests: PASS
- browser integration tests: PASS
- prepare integration artifacts: PASS
aram356
left a comment
There was a problem hiding this comment.
Summary
Verified the core claim: grep confirms zero fastly imports in html_processor.rs, streaming_processor.rs, streaming_replacer.rs, and rsc_flight.rs. cargo doc --no-deps --all-features produced no new warnings (15 pre-existing, all unrelated to this PR). CI is green across all three checks. The audit table in the plan doc is a useful artifact to leave behind for future adapter authors.
Non-blocking
🤔 thinking
- Self-referential module doc —
crates/trusted-server-core/src/publisher.rs:1-7speaks about "publisher.rs" from insidepublisher.rs. Rust module docs should speak in first person ("this module"). Also worth noting:publisher.rsisn't in the plan's File Map — it appeared in the "Address PR review feedback" commit. Consider rewording to "Publisher response handler. Platform coupling: this module is currently coupled tofastly::Body/Request/Responseat its handler boundaries..."
♻️ refactor
- Tautological verification label — Three sites (
platform/mod.rs,html_processor.rs,streaming_processor.rs) say "(verified in the content rewriting verification)". An earlier draft said "PR 8" and got genericized into a circular phrase. Prefer a durable pointer like(Verified 2026-03-31; see docs/superpowers/plans/2026-03-31-pr8-content-rewriting-verification.md.)or drop the parenthetical entirely — the surrounding paragraph already conveys the reasoning.
⛏ nitpick
- Awkward
implcode span —html_processor.rs:12renders as two separate code spans:`impl`then a linkedStreamProcessor. Prefer`impl `[`StreamProcessor`](single styled run) or`impl StreamProcessor`(no link). - Vague forward reference — "future adapters (subsequent adapter migrations)" appears in all three modified module docs. The original plan named Cloudflare / Axum / Spin explicitly; either name the targets or drop the parenthetical.
- PR body
Changestable is incomplete — The table lists 5 files but the diff touches 6;publisher.rsis only alluded to in Summary bullet 3. - Stale checklist template — PR checklist says "Uses
tracingmacros (notprintln!)" but this project standardizes onlog(withlog-fastly). Template drift only.
🌱 seedling
- Silent sibling modules — The plan intentionally skips
streaming_replacer.rsandrsc_flight.rsas internal. Fine, but a one-line//! See [\crate::platform`] module doc for platform notes.` at the top of each would make them self-documenting for anyone grepping "platform" directly in the file.
🏕 camp site
- Pre-existing
cargo docwarnings — 15 unresolved/private intra-doc links acrosslib.rs,auction/provider.rs,consent/types.rs,redacted.rs,tsjs.rs, and a few integration modules. Out of scope here, but since this is a documentation-quality PR, a follow-up sweep would noticeably liftcargo dochygiene.
👍 praise
- Clean separation of concerns —
crates/trusted-server-core/src/platform/mod.rs:15-30: the publisher-layer coupling was correctly reclassified as an HTTP-type concern rather than conflated with content-rewriting, and the publisher note was relocated fromplatform/mod.rs(plan draft) intopublisher.rsitself (final version) in response to earlier review feedback. Good response to review, good taxonomy.
CI Status
- browser integration tests: PASS
- integration tests: PASS
- prepare integration artifacts: PASS
* Add PR7 design spec for geo lookup + client info extract-once
Documents the call site migration plan: five Fastly SDK extraction
points in trusted-server-core replaced by RuntimeServices::client_info
reads, following Phase 1 injection pattern from the EdgeZero migration design.
* Fix spec review issues in PR7 design doc
- Correct erroneous claim about generate_synthetic_id being called twice
via DeviceInfo; it is called once (line 91 for fresh_id), DeviceInfo.ip
is a separate req.get_client_ip_addr() call fixed independently
- Add before/after snippet for handle_publisher_request call site in main.rs
- Add noop_services import instruction for http_util.rs test module
- Clarify _services rename (drop underscore, not add new param) in didomi.rs
- Clarify nextjs #[allow(deprecated)] annotations are out of scope (different function)
* Update PR7 spec to address all five agent review findings
- Change RequestInfo::from_request signature to &ClientInfo (not
&RuntimeServices) so prebid can call it with context.client_info
- Scope SDK-call acceptance criteria to active non-deprecated code only
- List all six AuctionContext construction sites including two production
sites in orchestrator.rs and three test helpers in orchestrator/prebid
- Add explicit warn-and-continue pattern for publisher.rs geo lookup
- Correct testing table: formats.rs and endpoints.rs have no test modules;
add orchestrator.rs and prebid.rs test helper update rows
* Add PR7 implementation plan and address plan review findings
Plan covers 6 tasks in compilation-safe order: AuctionContext struct change
first, then from_request signature, then synthetic.rs cascade, then publisher
geo, then didomi. Includes two new copy_headers unit tests (Some/None).
Spec fixes: clarify injection pattern exceptions for &ClientInfo and
Option<IpAddr>; reword acceptance criterion to reflect that provider-layer
reads flow through AuctionContext.client_info.
* Fix three plan review findings and two open questions
- Finding 1 (High): Add missing publisher.rs test call site at line ~695
for get_or_generate_synthetic_id — was omitted from Task 3 Step 6
- Finding 2 (Medium): Remove crate::geo::GeoInfo import from endpoints.rs
rather than replacing it — type is not used by name after the change,
keeping any import fails clippy -D warnings
- Finding 3 (Low): Replace interactive git add -p in Task 6 with explicit
file staging instruction
- Open Q1: Add Task 2 step to update stale handle_publisher_request
signature in auction/README.md
- Open Q2: Add Task 2 step to update from_request doc comment to reflect
ClientInfo-based TLS detection instead of Fastly SDK calls
* Broaden two low-severity doc cleanup steps in PR7 plan
- Step 7: cover all four stale Fastly-SDK-specific locations in
http_util.rs (SPOOFABLE_FORWARDED_HEADERS doc, RequestInfo struct doc,
from_request doc, detect_request_scheme doc)
- Step 8: replace the whole routing snippet in auction/README.md, not
just the one handle_publisher_request line — handle_auction and
integration_registry.handle_proxy are also stale in that snippet
* Fix two remaining low findings in PR7 plan
- Add missing Location 2 (RequestInfo.scheme field doc, line ~67) to
Step 7; renumber subsequent locations 3-5
- Replace &runtime_services with runtime_services in Step 5 and README
snippet — runtime_services is already &RuntimeServices in route_request
* Fix count drift in Step 7: four → five locations
* Add client_info field to AuctionContext and fix all construction sites
* Change RequestInfo::from_request to take &ClientInfo, thread services into handle_publisher_request
* Add Task 2 follow-up coverage and README route fixes
* Add services param to generate_synthetic_id, remove Fastly IP/geo calls in formats and endpoints
* Revert premature publisher geo change from Task 3
* Replace deprecated GeoInfo::from_request in publisher.rs with services.geo().lookup()
* Remove Fastly IP extraction from Didomi copy_headers, use ClientInfo instead
* Move IpAddr import to test module level in didomi.rs
* Apply rustfmt formatting to didomi.rs, publisher.rs, and synthetic.rs
Fix multi-line function call style in didomi.rs, line-break wrapping in
publisher.rs test, and import ordering in synthetic.rs test module.
* Add test coverage for generate_synthetic_id with concrete client IP
Adds noop_services_with_client_ip helper to test_support and a new
test that verifies the client_ip path through generate_synthetic_id
by asserting the HMAC differs when the IP changes.
* Align geo lookup warn log format with codebase convention ({e} not {e:?})
* Apply Prettier formatting to PR7 plan and spec docs
* Verify content rewriting pipeline is platform-agnostic (PR 8) (#600)
* Document content rewriting as platform-agnostic in platform module
* Document html_processor as platform-agnostic
* Document streaming_processor as platform-agnostic
* Fix unresolved doc link: replace EdgeRequest with edgezero_core::http::Request
- Fix intra-doc link syntax and restore missing blank line in `html_processor`
- Replace opaque PR number references with descriptive context labels
- Move HTTP-type coupling caveat from `platform` module down to `publisher.rs`
- Convert `StreamingPipeline::process` plain-text generics to an intra-doc link
* Rename crates to trusted-server-core and trusted-server-adapter-fastly Rename crates/common → crates/trusted-server-core and crates/fastly → crates/trusted-server-adapter-fastly following the EdgeZero naming convention. Add EdgeZero workspace dependencies pinned to rev 170b74b. Update all references across docs, CI workflows, scripts, agent files, and configuration. * Add platform abstraction layer with traits and RuntimeServices Introduces trusted-server-core::platform with PlatformConfigStore, PlatformSecretStore, PlatformKvStore, PlatformBackend, PlatformHttpClient, and PlatformGeo traits alongside ClientInfo, PlatformError, and RuntimeServices. Wires the Fastly adapter implementations and threads RuntimeServices into route_request. Moves GeoInfo to platform/types as platform-neutral data and adds geo_from_fastly for field mapping. * Address platform layer review feedback - Defer KV store opening: replace early error return with a local UnavailableKvStore fallback so routes that do not need synthetic ID access succeed when the KV store is missing or temporarily unavailable - Use ConfigStore::try_open + try_get and SecretStore::try_get throughout FastlyPlatformConfigStore and FastlyPlatformSecretStore to honour the Result contract instead of panicking on open/lookup failure - Encapsulate RuntimeServices service fields as pub(crate) with public getter methods (config_store, secret_store, backend, http_client, geo) and a pub new() constructor; adapter updated to use new() - Reference #487 in FastlyPlatformHttpClient stub (PR 6 implements it) - Remove unused KvPage re-export from platform/mod.rs - Use super::KvHandle shorthand in RuntimeServices::kv_handle() * Reject host strings containing control characters in BackendConfig * Fix clippy error * Validate scheme and host for control characters in BackendConfig * Address review findings on platform abstraction layer * Address review findings on platform abstraction layer * Add config store read path and storage module split - Split fastly_storage.rs into storage/{config_store,secret_store,api_client,mod}.rs - Add PlatformConfigStore read path via FastlyPlatformConfigStore::get using ConfigStore::try_open/try_get - Add PlatformError::NotImplemented variant; stub write methods on FastlyPlatformConfigStore and FastlyPlatformSecretStore - Add StoreName/StoreId newtypes with From<String>, From<&str>, AsRef<str> - Add UnavailableKvStore to core platform module - Add RuntimeServicesBuilder replacing 7-arg constructor - Migrate get_active_jwks and handle_trusted_server_discovery to use &RuntimeServices - Update call sites in signing.rs, rotation.rs, main.rs - Add success-path test for handle_trusted_server_discovery using StubJwksConfigStore - Fix test_parse_cookies_to_jar_empty typo (was emtpy) * Harden legacy config-store reads and align Fastly adapter stubs * Address storage review feedback * Resolved github-advanced-security bot problems * Address PR review feedback on platform abstraction layer - Make StoreName and StoreId inner fields private; From/AsRef provide all needed construction and access - Add #[deprecated] to GeoInfo::from_request with #[allow(deprecated)] at the three legacy call sites to track migration progress - Enumerate the six platform traits in the platform module doc comment - Extract backend_config_from_spec helper to remove duplicate BackendConfig construction in predict_name and ensure - Replace .into_iter().collect() with .to_vec() on secret plaintext bytes - Remove unused bytes dependency from trusted-server-adapter-fastly - Add comment on SecretStore::open clarifying it already returns Result (unlike ConfigStore::open which panics) * Add PR 4 design spec for secret store trait (read-only) * Clarify test scope and deferred branches in PR 4 spec * Add implementation plan for PR 4 secret store trait * Add test for get_secret_bytes open-failure path * Add NotImplemented tests for FastlyPlatformSecretStore write stubs * Inline StoreId binding and add section comment in write-stub tests * Remove plan * Add PR 6 design spec for backend and HTTP client traits * Address spec review findings on PR 6 design * Implement PlatformHttpClient and thread RuntimeServices through proxy layer - Add PlatformHttpClient trait with send(), send_async(), and select() methods - Add PlatformBackend trait with predict_name() and ensure() methods - Add PlatformResponse wrapper around EdgeZero HTTP responses - Add PlatformPendingRequest and PlatformSelectResult for auction fan-out - Thread RuntimeServices through IntegrationProxy::handle(), IntegrationRegistry::handle_proxy(), and all first-party proxy endpoints so handlers can reach the HTTP client - Add StubHttpClient and StubBackend test stubs with build_services_with_http_client helper - Add proxy_request_calls_platform_http_client_send integration test - Fix proxy_with_redirects to stay within 7-arg clippy limit via ProxyRequestHeaders struct - Document Body::Stream limitation in edge_request_to_fastly with warning log - Document intentional duplication of platform_response_to_fastly across proxy and orchestrator - Remove spec file (promoted to plan + implementation) * Address pr review findings * Resolve pr review findings * Fix ci test and format failure * Address review findings * Address PR review findings * Address review findings * Extract client IP and TLS info once at adapter boundary (PR7) (#599) * Add PR7 design spec for geo lookup + client info extract-once Documents the call site migration plan: five Fastly SDK extraction points in trusted-server-core replaced by RuntimeServices::client_info reads, following Phase 1 injection pattern from the EdgeZero migration design. * Fix spec review issues in PR7 design doc - Correct erroneous claim about generate_synthetic_id being called twice via DeviceInfo; it is called once (line 91 for fresh_id), DeviceInfo.ip is a separate req.get_client_ip_addr() call fixed independently - Add before/after snippet for handle_publisher_request call site in main.rs - Add noop_services import instruction for http_util.rs test module - Clarify _services rename (drop underscore, not add new param) in didomi.rs - Clarify nextjs #[allow(deprecated)] annotations are out of scope (different function) * Update PR7 spec to address all five agent review findings - Change RequestInfo::from_request signature to &ClientInfo (not &RuntimeServices) so prebid can call it with context.client_info - Scope SDK-call acceptance criteria to active non-deprecated code only - List all six AuctionContext construction sites including two production sites in orchestrator.rs and three test helpers in orchestrator/prebid - Add explicit warn-and-continue pattern for publisher.rs geo lookup - Correct testing table: formats.rs and endpoints.rs have no test modules; add orchestrator.rs and prebid.rs test helper update rows * Add PR7 implementation plan and address plan review findings Plan covers 6 tasks in compilation-safe order: AuctionContext struct change first, then from_request signature, then synthetic.rs cascade, then publisher geo, then didomi. Includes two new copy_headers unit tests (Some/None). Spec fixes: clarify injection pattern exceptions for &ClientInfo and Option<IpAddr>; reword acceptance criterion to reflect that provider-layer reads flow through AuctionContext.client_info. * Fix three plan review findings and two open questions - Finding 1 (High): Add missing publisher.rs test call site at line ~695 for get_or_generate_synthetic_id — was omitted from Task 3 Step 6 - Finding 2 (Medium): Remove crate::geo::GeoInfo import from endpoints.rs rather than replacing it — type is not used by name after the change, keeping any import fails clippy -D warnings - Finding 3 (Low): Replace interactive git add -p in Task 6 with explicit file staging instruction - Open Q1: Add Task 2 step to update stale handle_publisher_request signature in auction/README.md - Open Q2: Add Task 2 step to update from_request doc comment to reflect ClientInfo-based TLS detection instead of Fastly SDK calls * Broaden two low-severity doc cleanup steps in PR7 plan - Step 7: cover all four stale Fastly-SDK-specific locations in http_util.rs (SPOOFABLE_FORWARDED_HEADERS doc, RequestInfo struct doc, from_request doc, detect_request_scheme doc) - Step 8: replace the whole routing snippet in auction/README.md, not just the one handle_publisher_request line — handle_auction and integration_registry.handle_proxy are also stale in that snippet * Fix two remaining low findings in PR7 plan - Add missing Location 2 (RequestInfo.scheme field doc, line ~67) to Step 7; renumber subsequent locations 3-5 - Replace &runtime_services with runtime_services in Step 5 and README snippet — runtime_services is already &RuntimeServices in route_request * Fix count drift in Step 7: four → five locations * Add client_info field to AuctionContext and fix all construction sites * Change RequestInfo::from_request to take &ClientInfo, thread services into handle_publisher_request * Add Task 2 follow-up coverage and README route fixes * Add services param to generate_synthetic_id, remove Fastly IP/geo calls in formats and endpoints * Revert premature publisher geo change from Task 3 * Replace deprecated GeoInfo::from_request in publisher.rs with services.geo().lookup() * Remove Fastly IP extraction from Didomi copy_headers, use ClientInfo instead * Move IpAddr import to test module level in didomi.rs * Apply rustfmt formatting to didomi.rs, publisher.rs, and synthetic.rs Fix multi-line function call style in didomi.rs, line-break wrapping in publisher.rs test, and import ordering in synthetic.rs test module. * Add test coverage for generate_synthetic_id with concrete client IP Adds noop_services_with_client_ip helper to test_support and a new test that verifies the client_ip path through generate_synthetic_id by asserting the HMAC differs when the IP changes. * Align geo lookup warn log format with codebase convention ({e} not {e:?}) * Apply Prettier formatting to PR7 plan and spec docs * Verify content rewriting pipeline is platform-agnostic (PR 8) (#600) * Document content rewriting as platform-agnostic in platform module * Document html_processor as platform-agnostic * Document streaming_processor as platform-agnostic * Fix unresolved doc link: replace EdgeRequest with edgezero_core::http::Request - Fix intra-doc link syntax and restore missing blank line in `html_processor` - Replace opaque PR number references with descriptive context labels - Move HTTP-type coupling caveat from `platform` module down to `publisher.rs` - Convert `StreamingPipeline::process` plain-text generics to an intra-doc link
Summary
html_processor,streaming_processor,streaming_replacer,rsc_flight) has zero Fastly imports and requires noPlatformContentRewritertrait — future adapters (PR 16/17) need not implement any content-rewriting interface.platform/mod.rs,html_processor.rs, andstreaming_processor.rsso it is discoverable for Cloudflare, Axum, and Spin adapter authors.publisher.rshandler layer usesfastly::Body/Request/Responseat its function boundaries, but this is an HTTP-type coupling addressed in Phase 2 (PR 11), not a content-rewriting concern.Changes
crates/trusted-server-core/src/platform/mod.rsPlatformContentRewritertrait is neededcrates/trusted-server-core/src/html_processor.rs# Platform notessection confirming zero Fastly importscrates/trusted-server-core/src/streaming_processor.rs# Platform notessection confirmingStreamingPipeline::processis generic overR: Read + W: Writecrates/trusted-server-adapter-fastly/src/platform.rsEdgeRequest→edgezero_core::http::Request) caught bycargo doccrates/trusted-server-core/src/publisher.rsfastly::Body/Request/Responseusage is an HTTP-type concern, not content-rewritingdocs/superpowers/plans/2026-03-31-pr8-content-rewriting-verification.mdCloses
Closes #489
Test plan
cargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warningscargo fmt --all -- --checkcd crates/js/lib && npx vitest runcd crates/js/lib && npm run formatcd docs && npm run formatcargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1fastly compute serveChecklist
unwrap()in production code — useexpect("should ...")logmacros (notprintln!)