Remove legacy entry point, canary routing, and flag plumbing#744
Remove legacy entry point, canary routing, and flag plumbing#744prk-Jr wants to merge 463 commits into
Conversation
…feature/edgezero-pr12-handler-layer-types
…/edgezero-pr13-integration-provider-type-migration
Blocking fixes: - Remove debug_assert! in compat::to_fastly_response that contradicted the documented silent-drop fallback and caused to_fastly_response_with_streaming_body_produces_empty_body to panic in debug builds - Restore streaming dispatch for PublisherResponse::Stream, which was regressed by the PR 11 compat shim. Introduce HandlerOutcome enum so route_request can signal streaming intent back to the adapter. main() handles HandlerOutcome::Streaming via to_fastly_response_skeleton + stream_to_client + stream_publisher_body directly, avoiding the Vec<u8> buffer that delayed TTFB and scaled WASM memory with body size. Non-blocking fixes: - Add to_fastly_response_skeleton for headers-only fastly response conversion - Add geo-401 comment: skip geo lookup for unauthenticated callers - Add audited-callers comment on EdgeBody::Stream arms in compat - Add O(N) / PR 15 comment on bytes.to_vec() calls - Deduplicate auction/publisher status extraction in route_tests via outcome_status helper
Resolve conflicts in main.rs, compat.rs, auction/endpoints.rs, cookies.rs, edge_cookie.rs, migration_guards.rs, publisher.rs, and request_signing/endpoints.rs. Includes main's JA4 debug endpoint, Sourcepoint integration, and Prebid bid param override rules. Removed unused try_build_ec_cookie_value and get_ec_id_from_http_request stubs surfaced by clippy after merge.
StreamingBody in fastly 0.11.12 has no Drop impl — dropping it without calling finish() leaves the chunked HTTP stream with no terminal chunk, causing clients to receive "unexpected EOF during chunk size line". Match on stream_publisher_body result and call finish() in both the success and error paths so the response is always properly terminated.
Blocking fixes: - Fix doc_markdown clippy errors in integrations/mod.rs (BAD_GATEWAY, max_bytes, one_chunk wrapped in backticks) - Drop change_context() on collect_body_bounded() calls in auction, datadome, didomi, lockr, permutive — RequestTooLarge (413) was being rewritten to Integration/Auction (502); now propagates unchanged via ? so oversized bodies correctly surface as PAYLOAD_TOO_LARGE - Remove debug_assert! in compat::to_fastly_response (already fixed in PR 12, missed in PR 13 merge) Non-blocking fixes: - Migrate testlight upstream response read from unbounded collect_body to collect_response_bounded(UPSTREAM_RTB_MAX_RESPONSE_BYTES) matching all other RTB integrations; remove now-unused collect_body function - Upgrade orchestrator predicted-backend-name fallback log from debug to warn so operators see silent bid-loss fallback in production
Conflict resolution: keep PR13 http-native integration dispatch (no compat round-trip) and add HandlerOutcome::Buffered wrapping from PR12. Migrate sourcepoint.rs from fastly SDK types to edgezero http types, completing the integration layer HTTP type migration started in PR13. All sourcepoint helper methods and tests updated to use http::Request, http::Response, and HeaderValue instead of fastly::Request/Response.
Blocking fixes:
- Fix cargo fmt failure in auction handler Ok() block (app.rs)
- Extract SpawnedRequestResult type alias to fix clippy::type_complexity (platform.rs)
- Rename TRUSTED_SERVER__SYNTHETIC__SECRET_KEY to TRUSTED_SERVER__EDGE_COOKIE__SECRET_KEY
in scripts/integration-tests.sh and setup-integration-test-env/action.yml (PR15 rename miss)
- Update CLAUDE.md CI Gates to reference cargo test-fastly && cargo test-axum
- Add clippy-fastly/clippy-axum cargo aliases; split format.yml clippy into two target-matched
steps so wasm32-wasip1 paths are linted in CI
Non-blocking:
- Refactor startup_error_router: rename make closure to make_handler (one indirection level)
- Remove redundant rotate_handler/deactivate_handler aliases; pass admin_not_supported directly
- Log warn on invalid PORT env var value instead of silently falling back
- Log debug when buffering Body::Stream to Vec<u8> for outbound requests
- Move simple_logger to workspace dependencies
- Update agent docs (pr-reviewer, verify-app, pr-creator) to use cargo test-fastly/clippy-fastly
- Emit "Listening on http://{addr}" at startup for both PORT and run_app paths
- Format docs markdown tables with Prettier
Resolved conflicts across 22 files. Key decisions: - Core files: took PR15's renames (get_or_generate_ec_id_from_http_request, ec_cookie_value_is_safe, collect_response_bounded, ec_cookie_attributes) and all new tests PR15 added - Fastly adapter: kept PR15's HandlerOutcome, edgezero_main, OwnedProcessResponseParams, HEADER_X_TS_FINALIZED sentinel, and named route table pattern - fastly.toml: took PR15's edgezero_enabled = "false" (EdgeZero not yet at parity) - docs/guide/testing.md: took PR15's version - Cargo.lock: regenerated post-resolution - Removed stale DEFAULT_FIRST_BYTE_TIMEOUT import from proxy.rs (superseded by platform)
P1: Cap EdgeZero publisher fallback buffering via configurable publisher.max_buffered_body_bytes setting. When unset (default), buffering is unbounded, restoring pre-PR14 parity. When set, a BoundedWriter enforces the limit and returns a 500 on overflow instead of growing the Wasm heap without bound. P2: Extract resolve_geo_for_response helper to middleware.rs so the 401-skip rule is defined once and shared by both FinalizeResponseMiddleware and apply_entry_point_finalize. P2: Update get_settings doc to reflect OnceLock caching — first call loads and validates, subsequent calls clone the cached value. P2: Narrow startup-error module doc — responses may still receive entry-point finalization when settings reload succeeds after build_state fails. P3: Expand legacy_main doc to list all safe-fallback cases: disabled flag, config-store open failure, key-read error, and non-truthy values.
…dy in platform/mod.rs
Blocking: - Fix cargo fmt failure in integration-tests cloudflare.rs (long import, struct init) - Replace `use worker::*` with explicit imports in adapter lib.rs - Return generic 500 body from top-level dispatch error; log detail server-side - Fix workerd process-group leak: spawn wrangler as group leader, killpg on drop - Use find_available_port() for wrangler dev instead of hardcoded 8787 - Reject multi-provider fan-out in select() with PlatformError::HttpClient instead of a noisy warn; per-provider timeout is now enforced by failing loudly rather than silently degrading to sum(latencies) - Fix clippy::type_complexity in axum platform.rs with ResponseTriplet alias - Fix docs prettier formatting Non-blocking: - Return Err from execute() on Body::Stream outbound instead of silent empty body - Assert unreachable! on Body::Stream in send_async (execute always returns Once) - Extract shared dispatch() helper from get_fallback/post_fallback duplicates - Rename auth test to auth_middleware_runs_in_chain_for_protected_routes - Update stale #[ignore] reasons for Cloudflare integration tests
- Merge latest PR16 base (bff1adc, 314575b): removes unused backend.rs and fixes .gitignore comment - Use SpawnedRequestResult type alias from PR16 (includes Result wrapper) - Add check-cloudflare alias for wasm32-unknown-unknown target check - Add clippy-cloudflare alias to complete the per-adapter clippy pattern
…ezero-pr17-cloudflare-adapter
Resolve PR19 conflicts against the latest PR18 base. Keep PR18's renamed crate layout/toolchain updates while preserving PR19's Spin workspace member, CI checks, route parity, and worker 0.8 compatibility. Combine Fastly TLS header hardening with PR18's client-info extraction helper, and update Spin/integration-test paths for the trusted-server-js rename.
…ezero-pr18-phase5-verification # Conflicts: # .github/workflows/integration-tests.yml
…ezero-pr18-phase5-verification # Conflicts: # crates/trusted-server-integration-tests/Cargo.lock
…/edgezero-pr19-spin-adapter # Conflicts: # crates/trusted-server-integration-tests/Cargo.lock
…ro-pr19-cutover-canary
…zero-pr20-legacy-cleanup # Conflicts: # .github/workflows/integration-tests.yml # scripts/check-integration-dependency-versions.sh
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Automated review: I reviewed PR #744 against feature/edgezero-pr19-cutover-canary, focusing on the Fastly post-cutover path, config/test changes, and compatibility risks. Current GitHub checks are green, and I did not find a blocking security, data-loss, authorization, or CI-breaking issue. I did find two compatibility concerns worth addressing or explicitly accepting; details are inline.
| } else { | ||
| legacy_main(req); | ||
| } | ||
| edgezero_main(req); |
There was a problem hiding this comment.
Automated review: P1 compatibility — removing the fallback makes the known streaming gap apply to all Fastly traffic. This line now sends every non-health request through EdgeZero, but the EdgeZero fallback still materializes publisher responses via buffer_publisher_response (app.rs:719) and asset-route responses via buffer_asset_body (app.rs:781). The code comments acknowledge that legacy streamed asset bodies uncapped, while the EdgeZero path buffers them until the streaming cutover (app.rs:757-763), and the Fastly platform client rejects non-streamed origin responses over 10 MiB before publisher processing. That means large publisher pages/assets that legacy could stream can now fail once rollback/canary is removed. Suggested fix: either land the EdgeZero streaming seam before deleting the legacy fallback, or make this an explicit accepted compatibility break with targeted tests/docs covering the new size limits for publisher and asset responses.
|
|
||
| [local_server.backends] | ||
|
|
||
| [local_server.kv_stores] |
There was a problem hiding this comment.
Automated review: P2 compatibility — local Fastly config dropped stores that the default app config still uses. The root fastly.toml now defines only creative_store and consent_store, but trusted-server.toml still sets ec.ec_store = "ec_identity_store", and the Fastly batch-sync limiter still opens counter_store via RATE_COUNTER_NAME. The integration fixtures keep these stores, so CI stays green, but fastly compute serve with the repo defaults can fail EC identity or batch-sync operations because the local Viceroy config no longer provisions the referenced stores. Suggested fix: restore placeholder [[local_server.kv_stores.ec_identity_store]] and [[local_server.kv_stores.counter_store]] entries in root fastly.toml (remove only the canary config-store keys intended by this PR).
aram356
left a comment
There was a problem hiding this comment.
Summary
Re-review of the updated head (1e93245). All three blocking findings from the previous pass are resolved and CI is fully green — I verified each fix against the code, not just the check status. One new blocking issue was introduced by this update: fastly.toml no longer declares KV stores the runtime still opens, which breaks local fastly compute serve for EC. Details below.
Resolved since last review
- ✅
cargo test/admin_endpoints_match_fastly_router— test repointed frommain.rstoapp.rsand the parser updated to theNamedRoutepath:format;ADMIN_ENDPOINTS(/_ts/admin/keys/{rotate,deactivate}) now matches the routes inapp.rs. Verified passing. - ✅
integration tests+browser integration tests— root cause was the defaultviceroy-template.tomlnot declaring thetrusted_server_configstore that the EdgeZero entry point opens at startup. Now declared, with a guard test (default_fastly_viceroy_template_defines_trusted_server_config_store). - ✅
middleware.rsdoc — no longer references "the legacy entry point".
Cross-cutting / body-level findings
-
🔧
fastly.tomldropped KV stores the EdgeZero runtime still opens — localfastly compute servewill fail for EC. This update's net diff removesec_identity_store,counter_store, andopid_storefrom[local_server.kv_stores](leaving onlycreative_storeplus a newly-addedconsent_store). This is the PR's change, not base drift — both the merge-base and the current base tip still declare all three.The concrete breakage is
ec_identity_store:trusted-server.tomlstill setsec_store = "ec_identity_store"(active; not in this PR's diff).- The EdgeZero path opens it via
open_kv_store(platform.rs, called fromapp.rs). [local_server.kv_stores]is the only store config Viceroy /fastly compute servereads.
So
fastly compute serve+ any EC identify/batch-sync request →open_kv_store("ec_identity_store")→ store-not-found error. The pre-seeded test EC entry used bytest-prebid-eids.shis also gone.Why CI stays green: the integration suites use
viceroy-template.toml, which still declarescounter_store,opid_store,ec_identity_store(with seeds), andec_partner_store.fastly.tomlis never exercised by CI, so the divergence is invisible to the checks. Production is unaffected ([local_server]is Viceroy-only; production stores are provisioned out-of-band).This looks unintended (it surfaced through merge mechanics, not an explicit
fastly.tomledit in any commit). Suggested fix: restoreec_identity_store(with its test seed) andcounter_storetofastly.tomlso it matchestrusted-server.tomlandviceroy-template.toml; or, if a store rename was intended, update all three consistently. Proposed[local_server.kv_stores]shape:[local_server.kv_stores] [[local_server.kv_stores.counter_store]] key = "placeholder" data = "placeholder" [[local_server.kv_stores.creative_store]] key = "placeholder" data = "placeholder" [[local_server.kv_stores.ec_identity_store]] key = "placeholder" data = "placeholder" # Pre-seeded test EC entry for local script testing (test-prebid-eids.sh). [[local_server.kv_stores.ec_identity_store]] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test01" data = '{"v":1,"created":1700000000,"last_seen":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US"}}' [[local_server.kv_stores.consent_store]] key = "placeholder" data = "placeholder"
(
opid_storehas no runtime or config reference, so dropping it appears safe to leave out.)
CI Status
- cargo fmt: PASS
- cargo test: PASS
- cargo test (axum native): PASS
- cargo test (cross-adapter parity): PASS
- cargo check (cloudflare native + wasm32-unknown-unknown): PASS
- cargo check/build/test (spin native + wasm32-wasip1): PASS
- vitest: PASS
- format-typescript: PASS
- format-docs: PASS
- prepare integration artifacts: PASS
- integration tests: PASS
- integration tests (EdgeZero entry point): PASS
- browser integration tests: PASS
No checks are marked required under branch protection; per CLAUDE.md these are still PR gates. The new finding is config-only and not exercised by any check.
aram356
left a comment
There was a problem hiding this comment.
Summary
Re-review of head 1e93245 (unchanged since my previous review). The three original blocking findings remain resolved. The one blocking issue from the last pass — fastly.toml dropping KV stores the runtime still opens — is still unaddressed at this head, so the verdict stays REQUEST_CHANGES. This pass also went deeper on the large deletions and the entry point; those results are recorded below as confirmation (no new blocking issues).
Still blocking (unchanged from previous review)
- 🔧
fastly.tomldroppedec_identity_store/counter_store/opid_storefrom[local_server.kv_stores].trusted-server.tomlstill setsec_store = "ec_identity_store"and the EdgeZero path opens it viaopen_kv_store, sofastly compute serve+ any EC identify/batch-sync request fails with a store-not-found error; the pre-seeded test EC entry used bytest-prebid-eids.shis also gone. This is the PR's change (both merge-base and base tip still declare all three stores). CI stays green only because the integration suites useviceroy-template.toml(which still declares them), notfastly.toml. Production is unaffected ([local_server]is Viceroy-only). Restoreec_identity_store(with its seed) andcounter_storetofastly.toml, or if a rename was intended, updatetrusted-server.tomlandviceroy-template.tomlto match. (opid_storehas no runtime/config reference and can stay removed.)
Deep-pass verification (no action needed — recorded for confidence)
- 📝
route_tests.rsdeletion (1867 lines) loses no coverage. All 43 deleted tests importroute_request/HandlerOutcome(the removed legacy router). The scenarios are re-covered by the EdgeZeroapp.rstest module (asset-route fallthrough, tester-cookie enable/disable,legacy_admin_aliases_denied_locally_not_proxied_to_publisher,dispatch_unregistered_method_returns_405_at_router_level, consent-store fail-closed) plus behavior-level tests in core. - 📝
compat.rsremoval of theBody::Streamdebug_assertis benign.app.rsbuffers streaming publisher/asset bodies toBody::Once(buffer_publisher_response/buffer_asset_body, bounded bypublisher.max_buffered_body_bytes) before the response leaves the router, so theStreamarm into_fastly_responseis unreachable by design; thewarn!log remains as a safety net. - 📝
main.rsentry point is correct — config-store open, forwarded-header sanitization, TLS-scheme re-injection, EC finalize, and geo application are all sound; streaming responses are buffered before the Fastly conversion.
Resolved (confirmed still fixed)
- ✅
admin_endpoints_match_fastly_router— repointed toapp.rs+NamedRouteparser; passes. - ✅ integration/browser suites — default
viceroy-template.tomlnow declarestrusted_server_config, with a guard test. - ✅
middleware.rsdoc — no longer references "the legacy entry point".
CI Status
All 13 checks PASS (cargo fmt, cargo test, cargo test axum native, cross-adapter parity, cloudflare check, spin check/build/test, vitest, format-typescript, format-docs, prepare integration artifacts, integration tests, integration tests (EdgeZero entry point), browser integration tests). The open finding is config-only and not exercised by any check.
aram356
left a comment
There was a problem hiding this comment.
Summary
Re-review of head 1e93245 (unchanged) — findings now anchored as inline comments. Verdict stays REQUEST_CHANGES for the one open blocking issue (fastly.toml KV stores). The three original findings remain resolved, and the deep-pass items are confirmations, not action items.
Blocking
🔧 wrench
fastly.tomldropped KV stores the runtime still opens — see inline atfastly.toml:30(carries a one-clicksuggestion).
Non-blocking
📝 note
compat.rsBody::Streamdebug_assertremoval is benign — see inline atcrates/trusted-server-adapter-fastly/src/compat.rs:20.
Deep-pass confirmations (no inline anchor — whole-file / deleted-file)
route_tests.rsdeletion (−1867) loses no coverage — all 43 tests were legacyroute_request/HandlerOutcome; scenarios re-covered byapp.rsEdgeZero tests + core behavior tests.main.rsentry point verified correct — config-store open, header sanitization, TLS-scheme re-injection, EC finalize, geo application all sound.
Resolved (confirmed still fixed)
- ✅
admin_endpoints_match_fastly_router— repointed toapp.rs+NamedRouteparser; passes. - ✅ integration/browser suites —
viceroy-template.tomlnow declarestrusted_server_config, with a guard test. - ✅
middleware.rsdoc — no longer references "the legacy entry point".
CI Status
All 13 checks PASS. The open finding is config-only and not exercised by any check.
| [[local_server.kv_stores.consent_store]] | ||
| key = "placeholder" | ||
| data = "placeholder" |
There was a problem hiding this comment.
🔧 wrench — This PR drops ec_identity_store, counter_store, and opid_store from [local_server.kv_stores], leaving only creative_store + the new consent_store. But trusted-server.toml still sets ec_store = "ec_identity_store" and the EdgeZero path opens it via open_kv_store, so fastly compute serve + any EC identify/batch-sync request fails with a store-not-found error (the pre-seeded test-prebid-eids.sh EC entry is gone too). Both the merge-base and current base tip still declare these stores; CI stays green only because the integration suites use viceroy-template.toml (which keeps them), not fastly.toml. Restore the stores the runtime opens (opid_store has no runtime/config reference, so it's left out here):
| [[local_server.kv_stores.consent_store]] | |
| key = "placeholder" | |
| data = "placeholder" | |
| [[local_server.kv_stores.ec_identity_store]] | |
| key = "placeholder" | |
| data = "placeholder" | |
| # Pre-seeded test EC entry for local script testing (test-prebid-eids.sh). | |
| # Matches the TEST_EC_ID used in that script. | |
| [[local_server.kv_stores.ec_identity_store]] | |
| key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test01" | |
| data = '{"v":1,"created":1700000000,"last_seen":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US"}}' | |
| [[local_server.kv_stores.counter_store]] | |
| key = "placeholder" | |
| data = "placeholder" | |
| [[local_server.kv_stores.consent_store]] | |
| key = "placeholder" | |
| data = "placeholder" |
(Apply manually if you instead intend a store rename — then also update trusted-server.toml and viceroy-template.toml to match. Config-only change; not compile-verifiable, but the resulting TOML was validated to parse.)
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Review Summary
Approved. I reviewed PR #744 against main with senior-review focus on correctness, compatibility, CI coverage, and adapter behavior. The current GitHub checks are green; I left non-blocking CREG notes inline for follow-up.
📝 CI / existing-review context: GitHub currently reports the branch as conflicting with current main, so it still needs a rebase/merge conflict resolution before it can land. Existing reviews already cover the fastly.toml local KV-store drift and the Fastly streaming-size compatibility concern; I did not duplicate those inline.
Resubmitting this review as a non-blocking comment instead of approval.
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Review Summary
Resubmitting the previous review as a non-blocking COMMENT rather than an approval. I reviewed PR #744 against main with senior-review focus on correctness, compatibility, CI coverage, and adapter behavior. The current GitHub checks are green.
📝 CI / existing-review context: GitHub currently reports the branch as conflicting with current main, so it still needs a rebase/merge conflict resolution before it can land. Existing reviews already cover the fastly.toml local KV-store drift and the Fastly streaming-size compatibility concern; I did not duplicate those inline.
🌱 Non-blocking findings noted in the dismissed review's inline comments:
.github/workflows/format.yml:41— Cloudflare wasm production code is not clippy-gated; the missing wasm clippy command currently fails with-D warnings.crates/trusted-server-adapter-cloudflare/src/app.rs:342— Cloudflare exposes authenticated admin key-management routes even though platform store writes/deletes are unsupported.crates/trusted-server-adapter-spin/src/app.rs:647— Spin exposes authenticated admin key-management routes even though platform store writes/deletes are unsupported.
Resolve the stacked-history conflicts against current main while preserving PR20's post-cutover cleanup and main's newer asset streaming, config generation, CLI, and adapter changes.
Restore the local runtime KV stores, stream Fastly publisher responses, add Cloudflare WASM clippy coverage, and return explicit 501 responses for unsupported Cloudflare and Spin key management.
Summary
legacy_main,route_request,HandlerOutcome, and all canary flag-reading machinery (edgezero_enabled/edgezero_rollout_pct) now that EdgeZero has reached full functional parity and the cutover canary (PR19) is merged.errormodule, the legacyroute_testsfile, and unused compat functions that only existed to support the old code path.mainto a direct trampoline intoedgezero_main, removing ~710 lines of dead code and the two config-store keys fromfastly.toml.Changes
crates/trusted-server-adapter-fastly/src/main.rslegacy_main,route_request,HandlerOutcome, flag constants, and all associated imports (~710 lines removed)crates/trusted-server-adapter-fastly/src/error.rscrates/trusted-server-adapter-fastly/src/route_tests.rscrates/trusted-server-adapter-fastly/src/compat.rscrates/trusted-server-adapter-fastly/src/platform.rsbuild_runtime_services(legacy-only)crates/trusted-server-adapter-fastly/src/app.rsruntime_services_for_consent_routeandbuild_state(legacy-only); update importscrates/trusted-server-adapter-fastly/src/middleware.rsfastly.tomledgezero_enabledandedgezero_rollout_pctconfig-store entriesdocs/superpowers/plans/2026-05-27-pr20-legacy-cleanup.mdCloses
Closes #501
Test plan
cargo fmt --all -- --checkcargo clippy-fastlycargo clippy-axumcargo test-fastly— 48 tests passed, 0 failedcargo test-axum— 20 tests passed, 0 failedcd crates/js/lib && npx vitest run— 291 tests passedcd crates/js/lib && npm run formatcd docs && npm run formatChecklist
unwrap()in production code — useexpect("should ...")logmacros (notprintln!)