Repository navigation
Consolidate request timing and GPT diagnostics - #1261
ChristianPavilonis wants to merge 74 commits into
Conversation
* Add request phase timing design spec (Server-Timing subtimings + access telemetry) * Address review round 1: freeze point, template-cache naming, snapshot semantics, KV scope, geo carry, route template, sink confirmation, sampling and query model, config rollback * Address review round 2: auction-wait placement modes, conservative private-only header emission, non-null sorting key with service identity, coarse publisher route template, telemetry snapshot and outage behavior, tinybird flag decoupling, adapter phase semantics * Add request phase timing implementation plan * Address engineer review: KV timing decorator, try_lock sampling, route metadata extension, adapter-derived env, typed template-cache state, adapter-owned emission context, per-mode delivery semantics, Axum outer wrapper
…ite-back in middleware Three final-review fixes for access telemetry correctness: - Normalize the HTTP method to an allowlist (GET/HEAD/POST/PUT/DELETE/ PATCH/OPTIONS, else "other") inside access_event_row, so a client- controlled extension-method token can never inflate the LowCardinality method column, regardless of which adapter builds the row. - Guard emit_access_telemetry_after_send against snapshots carrying a degraded sample_rate of 0.0 (captured on the app-state-build-failure fallback path), which could otherwise be sampled in by freshly reloaded settings and corrupt the sum(1.0/sample_rate) volume estimator. - Mirror the geo lookup write-back from apply_entry_point_finalize_headers into FinalizeResponseMiddleware::handle, so a middleware-finalized response that resolved geo via fallback carries the resolved GeoLookupState for the access-telemetry snapshot instead of showing country "unknown".
std::time::Instant::now() panics on wasm32-unknown-unknown, so every publisher request on the Cloudflare adapter trapped when the timing collector was constructed, and the two auction-wait sites would trap once an auction dispatched. web_time re-exports std's Instant on every other target, so Fastly, Axum, and Spin behavior is unchanged. The publisher.rs sites are qualified locally because that module's std Instant import still serves the pre-existing template-cache sites, which are out of scope here.
The character allowlist alone does not bound identity: [a-z0-9_-] is exactly the alphabet UUIDs, hex ids, reset tokens, and article slugs are built from, and truncating to 32 characters still leaves a globally unique prefix. A first segment now rejects whole to /other/* when it exceeds 32 characters or carries more than 7 ASCII digits, alongside the existing charset rejection. Year archives and hyphenated section names still pass. Extends the adversarial tests to the publisher-fallback path with UUID, hex-id, token, and slug shapes, and fixes the stale event_date reference in the row-builder doc.
- Gate building the access snapshot on tinybird.enabled and access_enabled, threaded through SendContext: a disabled deployment (the default) no longer pays env reads and String allocations on the pre-send path. DeliveryOutcome.snapshot becomes Option and the emitter treats None as nothing to send. - Classify asset-fallback responses as route_class asset with the operator-configured route prefix as the template, instead of landing in the other/unknown bucket alongside 404s. - Pin Phase::index() to PHASE_COUNT with a uniqueness-and-bounds test so a future variant fails the suite instead of panicking at runtime. - Drop the tautological sampled-out emission test; the 0.0-rate behavior is covered by sampled_in_boundary_rates_are_unconditional. - Clarify that the local dev config env var name genuinely triples trusted_server_config (prefix, store, key) rather than reading as a find/replace mistake.
Adds section 18 to the request phase timing spec: three first-call-wins T0 offsets (auction dispatched, resolved, committed) on RequestTimings, emitted as additive nullable columns on access_logs_raw with auction_id as the join key to the per-bidder auction dataset. Answers the overlap-proof questions the two existing clocks cannot: when the auction started relative to request entry, when the final bid landed, and when targeting was committed toward GAM.
Implements spec section 18: three first-call-wins marks on RequestTimings (dispatched at the DispatchAuctionOutcome::Dispatched arm, resolved after collect at both sites, committed after write_bids_to_state at both sites), carried through TimingSnapshot into four additive access_logs_raw columns: auction_dispatched_ms, auction_resolved_ms, auction_committed_ms, and auction_id as the join key to the per-bidder auction dataset. Null offsets mean no auction ran; a failed dispatch records nothing. FORWARD_QUERY fills the new columns with typed defaults for pre-existing rows. No header emission, no config surface, no adapter changes: the values ride the existing snapshot and the tinybird.access_enabled gate.
The Cloudflare integration harness writes wrangler.integration.generated.toml at test time; it was swept into the previous commit by accident. Ignore it so local CI=1 runs cannot commit it again.
The first path segment is only a section name when the path has depth: under a /%postname%/ permalink structure every article is a single-segment path, so keeping those segments verbatim put full article slugs into the 30-day dataset, against spec section 9. Depth is now required for a named template; single-segment paths, root landing pages included, bucket to /other/*. Route slicing keeps route_class and multi-segment templates like /news/*.
The bucket-quantized sampler truncated rates below one in a million to a zero threshold (silently emitting nothing) and quantized other low rates downward while rows still carried the configured rate, biasing the sum(1.0 / sample_rate) volume estimator. Its no-rand premise was also wrong: rand::thread_rng() is WASI-backed on this target and the EC generation path already relies on it. The sampler is now a direct uniform-roll comparison, and the roll gates on the rate stored in the snapshot itself, so emission probability and the row's sample_rate column cannot diverge; the divergence guard and its tests are removed. Also per review: the settings-reload fallback in the post-send path could never emit (no snapshot exists when settings were absent) and is removed; the dead_code allow on DeliveryOutcome narrows to the one collected-but-unemitted field; and the post-send ordering test is narrowed to the leg it actually proves, that request_elapsed is stamped when send returns.
On origin failure with a dispatched auction, the origin span guard stayed alive through the emit_abandoned_auction await, so ts-origin and origin_ms absorbed Tinybird emission time. The span now closes when the send resolves, before either branch, with an error-path regression test.
- Pin HEADER_PHASES against Phase::header_name() in the phase-index test, closing the second hand-synced list. - Add RouteClass::Asset to the snake_case rendering test; rename the lowercasing test to say what it does. - Give the Axum adapter a named, fully configured construction path (TrustedServerApp::dev_server_service) so server_timing_enabled is never silently discarded; the tuple API is private now. - Document that Server-Timing is client-visible when enabled, in the configuration guide's observability section. - Replace stale event_date references in the spec, plan, and dashboard guidance with the toDate(event_ts) sorting-key expression, and state the single-segment rejection rule in spec section 9.
…ming # Conflicts: # crates/trusted-server-adapter-fastly/src/app.rs # crates/trusted-server-adapter-fastly/src/main.rs # crates/trusted-server-adapter-fastly/src/middleware.rs # crates/trusted-server-core/src/publisher.rs # crates/trusted-server-core/src/settings.rs # docs/guide/configuration.md # trusted-server.example.toml
The access emitter carried the configured body limit without enforcing it, allowing oversized rows to bypass the intended transport safeguard.
Gate duration and placement on the actual launch flag in both collectors, without skipping collection, bid-state updates or terminal summaries. Preserve measured zero waits. Cover empty tokens in both placements, buffered and streamed routing-only navigation, and zero-duration recording. Document null and zero semantics.
Preserve the timing-aware Axum terminal wrapper alongside main's logging defaults, retain both Fastly health contracts, and keep portable publisher clocks. Align access version rustdoc with the new header split and handle fallible normalization in route-section tests. Validated merged JS, adapter/parity and target-matched lint gates. Fastly passes only against the disclosed local lifecycle-plus-timing candidate; the public pin remains blocked. Native core passes without Cargo's build-version environment injection, whose legacy test-loader failure is reproduced on unmodified main.
|
Merged current main with a normal merge commit, 686826e. Conflicts are resolved and GitHub reports MERGEABLE. The dependency manifest and lockfile are unchanged. Posted dispositions on 90 review threads and resolved 89: 58 on this PR and 31 on the related source PRs. The current EdgeZero dependency thread, r4240834032, remains open. Deferral replies explicitly describe unchanged behavior; they supersede earlier disposition entries that overstated optional cleanup as implemented. The approved correctness, test and versioned-schema fixes, the four follow-up fixes and the launch-gated wait correction remain in the branch. Local checks on the merged tree passed JS build/lint/format and all 1,236 Vitest tests; Axum 56, Cloudflare 55, Spin 89, cross-adapter parity 17, CLI 890, native filesystem tests, native and WASM lint including the portable-clock gate, and docs/Markdown checks. Fastly adapter 268 and core 3,002 tests, reuse, build and lint pass only against the disclosed local lifecycle-plus-timing candidate, not the committed pin. Native core has an inherited test-environment failure from main: Cargo injects the build-only TRUSTED_SERVER__GIT_VERSION into the legacy test-only environment loader, which rejects git_version. The same failure was reproduced on an unmodified archive of main. The rebuilt merged core binary passes all 3,008 tests with only that build-only variable removed. Normal cargo test is not claimed green. Rustdoc builds but retains warnings, including the deferred Axum link correction. Deferred work remains visible in the thread replies: timing contract/transport-completion semantics, fallback route identity and adapter wiring/health coverage, synchronous ingestion/target caching, raw-TOML secret preflight, delivery-result cleanup, diagnostics bundle/UX/privacy hardening, and documentation/refactor cleanup. No follow-up issues or deployments were created. Current CI is still blocked by the committed EdgeZero pin's missing lifecycle API. The misleadingly named cargo fmt job fails in Fastly clippy, and the Axum job fails in its Fastly release-build verification, not the Axum tests. Integration and browser jobs remain skipped. We will wait for a stable EdgeZero release, repin with a scoped lockfile update, then get committed-dependency CI and browser integration green before re-requesting review. No review request has been sent. |
aram356
left a comment
There was a problem hiding this comment.
Summary
Round 2 at 686826eaf. The fixes in 06e13366c, 3d39b1ef6 and 51aff4334 hold up. I re-ran the round-1 probes and mutations: core, JS and Fastly now catch all but one of them, the bare-private gate passes a 25-case probe, and the main-merge resolutions keep everything main added. Against the local EdgeZero combination, Fastly (268), Axum (56), wasm clippy, the 3,008 core tests (run directly; see the note below), 1,236 vitest tests and the docs build all pass. What still blocks: the EdgeZero pin (CI red), one surviving mutation on the page-bids diagnostics gate, and roughly twenty deferrals that live only in resolved threads.
6 of the inline comments carry a one-click
suggestion, each verified alone against the head (rustfmt, native core clippy with-D warningsand the core suite for Rust; prettier for docs; JSON and key-order checks for the fixture). The rest are prose because they span hunks or files.
Round-1 status
Verified fixed at this head: the FORWARD_QUERY (now a versioned access_logs_v2 with no forward query, and access_logs_raw untouched), the planned-Immediate launch accounting, the disabled-auction join key (null on all three routes), the field-qualified private gate, the core timeline/placement tests (6 of 7 round-1 mutations now killed), the JS classification tests (all 5 killed), the Fastly freeze-point / geo write-back / body-boundary tests, the TimedKvStore per-method tests, the first-impression fallback facts, the poll_ready swap, the operator telemetry and Tinybird docs, the env-override and Cloudflare/Spin docs, and the ts_version rustdoc. Partial or open items are below.
Blocking
🔧 wrench
- Page-bids diagnostics gate still survives deletion: see inline at
crates/trusted-server-core/src/publisher.rs:25149 - EdgeZero pin / CI, and deferred work with no tracking issues: see below
Non-blocking
🤔 thinking / 📝 note / ⛏ nitpick / 🌱 seedling
ts_versionvs main'sx-ts-version: see inline atcrates/trusted-server-adapter-fastly/src/main.rs:1174auction_resolved_msrename window: see inline attinybird/datasources/access_logs_v2.datasource:32- Mediator-only collection is untimed: see inline at
crates/trusted-server-core/src/publisher.rs:4361 set_auction_idrustdoc after the disabled-auction change: see inline atcrates/trusted-server-core/src/request_timing.rs:194- Comment made false by the
Immediatefix: see inline atcrates/trusted-server-core/src/publisher.rs:7458 - Legacy test loop still counts
Immediateas a launch: see inline atcrates/trusted-server-core/src/auction/orchestrator.rs:2067 - Fixture rows the producer can't emit: see inline at
tinybird/fixtures/access_logs_v2.ndjson:1 - Telemetry doc gaps (wait on
/auctionand page-bids, route templates): see inline atdocs/guide/telemetry.md:58 - Badge doc vs
badges.ts: see inline atdocs/guide/integrations/gpt-diagnostics.md:382 - CHANGELOG gaps: see inline at
CHANGELOG.md:46 - README cutover steps: see inline at
tinybird/README.md:57 - No guard against the legacy dataset name: see inline at
crates/trusted-server-core/src/settings.rs:2037 bidWonflag set before registration: see inline atcrates/trusted-server-js/lib/src/integrations/prebid/index.ts:1124service_fnnever polls readiness: see inline atcrates/trusted-server-adapter-axum/src/main.rs:94
Cross-cutting / body-level findings
- 🔧 The EdgeZero pin still cannot build Fastly, so CI is red (open thread r4240834032).
cargo fmt(required, failing in its Fastly clippy step),cargo test(required),cargo test (axum native)(failing only in its Fastly release-build step) andprepare integration artifactsfail withcannot find 'lifecycle' in 'edgezero_adapter_fastly'; the integration, Fastly EC lifecycle and browser jobs are skipped, sogpt-diagnostics.spec.tshas still never run. One thing changed upstream: EdgeZero #389's head878be472now contains both APIs, but it is v0.0.9 plus the two timing commits, and v0.0.9 is the logical-ID store-binding migration (#381) that #1175 is working through on this side. Repinning to it here means taking that migration in this PR; landing #1175 first and repinning to a release that includes #389 keeps the two changes separable. The lock still rewrites three unrelated edges (windows-sys 0.61.2 -> 0.48.0forcoloredandwinapi-util,hashbrown 0.17.1 -> 0.16.1forgix-imara-diff), andrandis still out of order in the FastlyCargo.toml. The PR is still not a draft. - 🔧 About twenty deferrals exist only in resolved threads. Resolving a thread with "deferred" removes it from view without a tracker; please file issues (one tracking issue is fine) and link them from the PR before merge. Grouped:
- Timing contract:
R - D/ transport-completion capture (r4240834077), early-sendts-origin(r4240834074), warm vs coldappbuild(r4240834071, r4249515006), origin timing for asset and proxy fetches (r4249515141). - Route identity and adapter coverage: Fastly fallback early returns without route metadata (r4240834063), Cloudflare/Spin
build_routercollector and/healthtests (r4249515067), the duplicated middleware test (r4249515076), Cloudflare/Spin startup warning for no-op flags (r4249515086, r4240834098; partly #1148). - Ingestion: synchronous
block_onsend, per-request target rebuild, post-sendexpect(r4240834069, r4249515006, r4249515122). - Secret preflight: inactive token references validated from raw TOML at push and carried in every blob (r4249514996, 1074 r4186272326); needs an EdgeZero CLI issue.
- Diagnostics: Prebid shim size (273 bytes of headroom under 43 KB; r4240834080, r4249515093),
prepare_requestbefore the CSRF gate (r4249515032), badge history (r4240834119), re-entered slot labelling (r4249515107). - Refactors: dispatch/collect mapping x3 (r4249515036), page-bids snapshot assembly (r4249515043),
SendContextx3 (r4249515130), single recorder call (r4240834083, r4249515112), upstreamAxumDevServerlayer seam (1074 r4186272608; no EdgeZero issue exists). - Docs: spec/plan reconciliation (r4240834094 and the spec halves of 1074 r4186272448, r4186272474, r4186272463).
- Several were pre-verified one-click suggestions that cost less to apply than to track:
noreferrer, the testunwrap(), the.gitignoretemplate name, the--punctuation, theexpectmessage form, the stalerun_auctioncomments, the Axum intra-doc link and the auction-token error message. - Existing issues to link and refresh: #1155 (delivery result; its premise that the symbols are absent and its
access_logs_rawtarget are stale) and #1148 (still saysaccess_enabledis rejected). - Three of the 10-13 replies call already-fixed items deferred: 1074 r4186272503 (disabled-path allocations), 1074 r4186272613 (
routes()doc) and 1121 r4162855722 (initial-document collector presence) all landed ine6d51e36c. Correcting those replies keeps them out of the issue list.
- Timing contract:
- 📌 The October RC still carries the round-1 Tinybird wrench.
origin/rc/202610(#1228) has the stacked-branchFORWARD_QUERYinaccess_logs_raw.datasourceanddefault_tinybird_access_dataset() = "access_logs_raw"; none ofe6d51e36c,06e13366c,3d39b1ef6or51aff4334is an ancestor. Atb deployfrom the RC hits the original failure, so refresh it from this branch before any Tinybird deploy from it. - 📝 PR description. The body is still the
e6d51e36ctext: "Draft and dependency blocker" on a non-draft PR, "All four originals remain open; no review threads have been resolved" (closed, and their threads now resolved), "Fixes … are ine6d51e36", 2,956/262 test counts, "FORWARD_QUERY fields align", the--punctuation row marked implemented, and no mention ofaccess_logs_v2. Prk-Jr's body-level items also have no reply:normalize_method's doc (CONNECT and TRACE map toother), the browser spec patchingattachShadowtwice, the Axum runtime and serve error context, the dictionary'sGPT-reported creativelabel, and the split suggestion. - 📝 Smaller items:
dispatch_auction's rustdoc (orchestrator.rs:1874-1877, outside the diff) still saysDispatchFailedmeans nothing could be started and that over-budget yieldsNotStarted; neither holds in the planned path now.routing_only_dispatched_navigation_keeps_milestones_nullusesrouting = "explicit"with no bidders, which skips at routing and never reaches theNoImpressions/Immediatearm, so the planned-Immediatefix is covered at unit level only and the test name over-claims.- On Cloudflare,
send_asyncexecutes the whole request, so a transport error after the request left the edge returns withoutProviderRequestStartedand is classified as not launched (plausible, unprobed; affects GPT-diagnostics timing only there). - Out of scope here: native
cargo test -p trusted-server-corefails 12settings::testsenv tests because Cargo injects main'sTRUSTED_SERVER__GIT_VERSIONat runtime; running the test binary directly passes all 3,008. It reproduces from main's build script, so it is worth its own issue.
CI Status
- cargo fmt: FAIL (required)
- cargo test: FAIL (required)
- cargo test (axum native): FAIL
- prepare integration artifacts: FAIL
- format-typescript: PASS (required)
- format-docs: PASS (required)
- vitest: PASS
- cargo check (cloudflare native + wasm32-unknown-unknown): PASS
- cargo check/build/test (spin native + wasm32-wasip1): PASS
- cargo test (cross-adapter parity): PASS
- cargo test (ts CLI, native) (macos-latest): PASS
- cargo test (ts CLI, native) (ubuntu-latest): PASS
- CLAUDE.md symlink guard: PASS
- CodeQL: PASS
- Analyze (actions): PASS
- Analyze (javascript-typescript): PASS
- Analyze (python): PASS
- Analyze (rust): PASS
- browser integration tests: SKIPPED
- integration tests: SKIPPED
- integration tests (Fastly EC lifecycle): SKIPPED
dhruv8sh
left a comment
There was a problem hiding this comment.
Summary
This combines request-phase timing, Server-Timing, sampled access telemetry, auction timeline joins and GPT diagnostics. The privacy design is solid: Server-Timing only goes out on conclusively private responses, and route templates and HTTP methods are bounded. It can't merge yet: the EdgeZero repin to ab444946 breaks the Fastly build, so four CI checks fail, including two required ones.
5 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 other comments describe the fix in prose because it touches multiple files or lines outside the diff and can't be auto-applied.
Blocking
🔧 wrench
- Failed CI:
cargo test(required),cargo fmt(required),cargo test (axum native),prepare integration artifacts. All four fail withcannot find lifecycle in edgezero_adapter_fastly. Because the artifacts step failed, the browser and integration suites were skipped.cargo fmt --checkpasses locally, so the fmt job fails at its build/clippy step. - The EdgeZero pin lacks the lifecycle API — see inline at
Cargo.toml:59-66.
Non-blocking
🤔 thinking
- Blocking access emission after delivery — see inline at
crates/trusted-server-adapter-fastly/src/main.rs:836 ts-originunderreports when the origin fetch is dispatched early — see inline atcrates/trusted-server-core/src/publisher.rs:5360- Page-bids /
/auctionnever recordPhase::AuctionWait— see inline atcrates/trusted-server-core/src/publisher.rs:7470 - Stale
access_logs_rawdataset not rejected — see inline atcrates/trusted-server-core/src/settings.rs:2038 - Diagnostics badges intercept ad clicks — see inline at
crates/trusted-server-js/lib/src/integrations/gpt_diagnostics/overlay.ts:104 - Prebid shim carries diagnostics-only code — see inline at
crates/trusted-server-js/lib/test/prebid-artifact-integration.test.mjs:313
♻️ refactor
- Delivery outcome is collected but never emitted — see inline at
crates/trusted-server-adapter-fastly/src/main.rs:870 - Duplicated planned-auction outcome mapping — see inline at
crates/trusted-server-core/src/publisher.rs:7441
⛏ nitpick
expectmessage convention — see inline atcrates/trusted-server-core/src/publisher.rs:6196,:6262unwrap()in a test — see inline atcrates/trusted-server-core/src/auction/endpoints.rs:1516randdependency order — see inline atcrates/trusted-server-adapter-fastly/Cargo.toml:37-38- Full Tinybird settings cloned per sampled request — see inline at
crates/trusted-server-adapter-fastly/src/main.rs:836 - Two names for one concept — see inline at
crates/trusted-server-core/src/publisher.rs:7169 - Spec contradictions / missing
asset— see inline atdocs/superpowers/specs/2026-08-24-request-phase-timing-design.md:294,:323 - Docs should say "bare"
private/no-store— see inline atdocs/guide/configuration.md:2984
Cross-cutting / body-level findings
- ⛏
route_sectionstrimming:ObservabilitySettings::normalize(crates/trusted-server-core/src/settings.rs) trims only non-control whitespace, so" news\t"is rejected even though the docs say names are trimmed. Either trim all whitespace before the control-character check, or say "spaces are trimmed". - ⛏ Duplicate docs: the
[tinybird]keys are documented twice indocs/guide/configuration.md(around lines 1322 and 3053) with slightly different wording. Point one table at the other. - 🏕 Test harness drift:
scripts/template-cache-local-test.sh:555probes for the literals(b,a), but with diagnostics active the seam script iss(b,a,d)(publisher.rs:6269). The comment atpublisher.rs:6255asks for the harness to be kept in sync. That file is outside the diff.
👍 praise
append_server_timing_if_privateonly emits on conclusively private responses: a bare directive is required, any edge/surrogate cache header suppresses it, and the value is appended rather than overwritten. It is thoroughly tested.publisher_route_templatebuilds templates only from the operator allowlist, andnormalize_methodkeeps the method column bounded, so no request data reaches the 30-day dataset.- Sampling is decided before any snapshot work. The overlay is
textContent-only, and the Prebid attempt map and diagnostics store are bounded.
CI Status
- fail: cargo test (required), cargo fmt (required), cargo test (axum native), prepare integration artifacts
- skipped: browser integration tests, integration tests, integration tests (Fastly EC lifecycle)
- pass: vitest, CodeQL / Analyze (rust, js-ts, actions, python), cargo test (cross-adapter parity), spin, cloudflare, ts CLI (ubuntu, macos), format-docs, format-typescript, CLAUDE.md symlink guard
| # Temporary integration pin for EdgeZero PR #389. Before merging TS into main, | ||
| # replace all six pins with the approved EdgeZero release tag and revalidate. | ||
| edgezero-adapter-axum = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402", default-features = false } | ||
| edgezero-adapter-cloudflare = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402", default-features = false } | ||
| edgezero-adapter-fastly = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402", default-features = false } | ||
| edgezero-adapter-spin = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402", default-features = false } | ||
| edgezero-cli = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402" } | ||
| edgezero-core = { git = "https://github.com/stackpop/edgezero", rev = "ab444946fcacb1d44c020c6079abb6ba29231402", default-features = false } |
There was a problem hiding this comment.
🔧 wrench — This repin to ab444946 breaks the build. Code already on main uses edgezero_adapter_fastly::lifecycle (crates/trusted-server-adapter-fastly/src/main.rs:125,146, sandbox.rs:61), and this rev doesn't have that module. cargo test, cargo fmt (its clippy step), cargo test (axum native) and prepare integration artifacts all fail with cannot find lifecycle in edgezero_adapter_fastly, so the browser/integration suites were skipped and the GPT diagnostics Playwright spec has never run.
Fix (apply manually; needs an upstream EdgeZero rev): publish an EdgeZero rev or release that has both the lifecycle API and the #389 timing collector, repin all six edgezero-* dependencies plus Cargo.lock, and re-run full CI including the browser/integration jobs. Until then, please mark this PR as draft. The description already says it is not mergeable.
|
Published eight targeted review-fix commits, ab58ced through c4cec08. The working tree is clean; EdgeZero pins and Cargo.lock are unchanged. The PR is now draft while required merge gates remain. Resolved 26 addressed threads with commit/check dispositions. Six non-EdgeZero threads remain open for the next contract/design discussion, plus the two unchanged dependency threads. Deferred work is tracked in #1458; #1148 and #1155 now describe the consolidation branch accurately. Three source-PR replies that incorrectly called already-implemented allocation, routes-doc and collector-presence fixes deferred have been corrected. Validation: all 1,237 Vitest tests, JS build/lint/format, docs build/lint/format, Markdown/domain checks, Axum 56, Cloudflare 55, Spin 89, parity 17, CLI 890, native/WASM Clippy outside Fastly, Rustfmt, portable-clock and build-digest checks pass. The page-bids and Axum regressions fail under their targeted mutations and pass after restoration. The rebuilt core binary passes all 3,011 tests without Cargo's build-only TRUSTED_SERVER__GIT_VERSION injection. Normal cargo test still fails 11 inherited environment-loader tests; this is not reported as a green Cargo gate. Native rustdoc retains 32 core warnings. Fastly test/reuse/lint remain blocked by the committed pin's missing lifecycle API, so the new Fastly constructor test and browser/integration runtime are unverified. No local dependency patch or live Tinybird deployment was used. GitHub still reports conflicts with current main. No merge-main, release-candidate update, deployment or review re-request was performed. |
|
Published six contract-fix commits, 7214c60 through 02f020a. All six remaining non-EdgeZero review threads are addressed and resolved; fresh verification leaves only the two dependency threads open. #1458 and #1155 now distinguish implemented changes from remaining validation/follow-ups. The access v2 row now has TS build version semantics, auction_collected_ms and delivery_result. Actual collection waits and planned-provider outcome mapping are shared across routes, including observed mediator work without fabricated provider dispatch or new requests. Access ingestion dispatches without waiting for the reply. Prebid diagnostics moved behind the optional recorder, with exact-instance/lifecycle coverage and a 1,744-byte smaller shim. Badge evidence passes clicks through; its small control sits outside observed creatives, and latest selection no longer opens history. Checks pass: 3,017 core tests in the isolated compiled binary, 1,264 Vitest tests, Axum/Cloudflare/Spin, parity, CLI, build-digest, non-Fastly native/WASM lint, JS/docs build/lint/format, Markdown, clock and domain checks. The actual emitter module passes 19 WASM tests and Clippy using the original dependency identities. The SDK lifetime probe verifies complete asynchronous request bodies after callback completion, including reuse, with a synchronous control. Limits remain explicit: normal Cargo core execution still fails the inherited build-only git_version environment tests; full Fastly/main tests/lint cannot build the committed lifecycle pin, so the new delivery-boundary regressions and browser integration are unverified. Native rustdoc retains 32 core warnings. No live Tinybird deployment or production Fastly guarantee is claimed. Dependencies/lockfile unchanged, worktree clean. PR stays draft and conflicts with current main. No merge-main, RC update, deployment or review re-request. |
Deny cross-site page-bids before diagnostics setup, preserve the disabled timing fast path, and consolidate send contexts and recorder calls. Return access-target setup errors instead of panicking after send, with recording-client regressions. Document route-section limitations and finish review wording corrections.\n\nDependency pins and lockfiles remain unchanged. Full Fastly checks still require the EdgeZero lifecycle API; post-send helper coverage is isolated WASM evidence.
|
Implemented the approved small cleanup batch in 9654deb7a, as one commit. No dependency pins, manifests or lockfiles changed.
Executed checks
Still blocked or unverifiedFull Fastly test/reuse/Clippy checks still fail on the committed EdgeZero pin's missing lifecycle API. Full application delivery-boundary, browser and live Tinybird deployment/ingestion/quarantine/rollback proof remain outstanding. Main conflicts are unchanged. The matching review replies and #1458 distinguish completed cleanup from larger deferred work. Only the two dependency threads are to remain unresolved. The PR stays draft, with no review re-request. |
Status and merge gates
Do not merge yet. This PR remains draft. The committed EdgeZero timing pin lacks the Fastly lifecycle API required by the application entry point. Updating that dependency and the store-binding migration remain separate work. GitHub also reports conflicts with current main; this batch does not merge main or update the RC branch.
Neither the contract nor cleanup batch changes dependency manifests/lockfiles, uses local dependency patches, deploys live Tinybird, or re-requests review.
Changes
Consolidates request-phase timing, private-response
Server-Timing, sampled post-send Fastly access telemetry, auction offsets/UUID joins and GPT diagnostics from #1074, #1076, #1121 and #1154. All four source PRs are closed as superseded.Access emission is off by default. The separate
access_logs_v2datasource has 31 columns, 30-day retention and its own APPEND token. The legacy nine-columnaccess_logs_rawremains intact, without aFORWARD_QUERYor raw-path backfill. A deployed preview v2 schema needs a coordinated migration before this producer is deployed.Agreed timing and delivery contracts
ts_versionis the compiled TS build identifier matchingx-ts-version: pipeline override, exact tag, branch, then six-character commit fallback. It is not the numeric Fastly activation version. No extra SHA or Fastly-version column was added.auction_collected_msnames the persisted collection-return milestone. Internal Rust and browserauctionResolvedMsnames remain unchanged. Collection return is not a separately observed provider transport-completion timestamp./auction, page-bids and HTML use shared orchestration/outcome mapping and actual collection waits, not R minus D. No-work outcomes keep wait/collection/commit null. Actual mediator-only network work can record those fields without inventing provider dispatch. Dispatch/admission choices and outgoing request counts are preserved.origin_msremains caller-blocking origin wait, including only the remaining wait after overlap. Fastly app-build means per-request setup plus cold construction when required, not a cold-start flag. Adapter T0 differences are documented rather than treated as equivalent.send_asyncfollowed by dropping the pending handle. Serialization/setup/start failures are observable; later transport errors, HTTP status and remote ingestion acceptance are not. There is no response wait, retry or durability guarantee.delivery_resultreports local transport handoff ascomplete,partialorerror, independently of HTTP status. It does not prove client receipt. The unused duplicate delivery-byte field was removed; response bytes remain in the timing snapshot.Diagnostics changes
Prebid targeting readers, the bidWon listener and bounded correlation state now live in the optional diagnostics bundle. The always-served shim only calls a narrow optional hook with its exact targeted Prebid instance. The served shim measures 40,983 bytes versus 42,727 at the previous batch, a 1,744-byte reduction under the unchanged artifact budget. Destruction unsubscribes only this runtime's listener when supported; otherwise the listener becomes inert and releases its recorder reference.
Badge evidence is pointer-transparent. A small native Ad #N control is placed outside observed bound creative rectangles and hidden if no viewport-fitting position exists. Selecting the latest request focuses current details without opening history; earlier selections open history.
The earlier eight targeted review fixes remain, including zero-provider diagnostics omission, disabled-auction UUID consistency, private-header gating, Prebid registration retry, Axum readiness, access-target borrowing, legacy-dataset rejection, dictionary-link referrer suppression, fixtures and rollout documentation.
Final small cleanup
9654deb7a denies cross-site page-bids before direct-handler diagnostics preparation, returns early on disabled Server-Timing emission, shares one Fastly send context, and removes duplicate GPT recorder-call branches. Access-target construction is fallible; recording-client tests cover missing credentials, sampled-out responses, independent toggles and best-effort start failures. The guide/example document route-section limitations without new validation restrictions, and remaining Axum/Wrangler wording is corrected.
Validation
Published contract batch:
7214c6058through02f020a80; final cleanup: 9654deb7a. Latest checks use the committed cleanup source, verified by file fingerprints. EdgeZero pins, SDK versions, manifests and Cargo.lock are unchanged.TRUSTED_SERVER__GIT_VERSIONabsent. Normalcargo test -p trusted-server-core --lib --lockedstill fails the same 11 inherited environment-loader tests withunknown field git_version; this is not a green normal Cargo gate.tinybird.rs, platform, backend and management modules compile in a standalone WASM test wrapper with all 281 external dependency identities/checksums matching the original lock. All 94 wrapper tests and wrapper Clippy pass, including 20 tests in the actual Tinybird module, four exact source-excerpt post-send regressions from main.rs, and 70 existing platform/backend/management tests. Coverage includes async start/drop, no response wait, framing/auth/body limits, missing-token setup, independent toggles, startup failures and no retries. The wrapper does not compile or validate the full application entry point.A temporary-file user quota interrupted some logs/checks. Only this session's scratch artifacts were moved into the cache, and interrupted checks were rerun with retained nonempty logs. No source/dependency workaround or unrelated cleanup was used.
The SDK lifetime probe uses only local Viceroy backends. It is not a production Fastly or Tinybird guarantee. Full application Fastly/main, integration and browser verification still require the dependency gate. Real-browser geometry, hit-testing and keyboard behavior have not been exercised; current UI evidence is unit/layout mocks and independently built artifact composition.
Remaining tracked work
#1458 is the checklist with original review links and current dispositions. #1148 retains adapter support/startup diagnostics work. #1155 records delivery-result implementation and its remaining full Fastly/rollout validation.
Remaining follow-ups include route identity on fallback errors, production adapter collector/health coverage, raw-TOML secret preflight, broader historical spec/plan reconciliation and transport-completion instrumentation if needed. This PR does not claim those are implemented merely because an earlier thread was resolved.