Repository navigation
Conversation
Round 50 — Fastly SDK correctness pass (commit
|
Round 51 — round-50 carry-overs + Spin WASI write mechanics (commit
|
Capture bounded request-owned SDK head, read and release observations on Axum and Cloudflare test builds. Bind cutoff evidence to the prepared URI, clock and budget without changing production policies. Preserve strict timing and record the remaining Miniflare 5 runtime verification gap. Validate fixture root paths before native runtime construction.
Keep the SDK body-read regression aligned with the hard-cut naming guard. Preserve the guard, original timing and all test behavior.
Use a bounded staged-file inventory with the selected SDK rule matcher and explicit-module converter. Preserve namespace identity, persistence and owned shutdown without a legacy runtime fallback. Record passing smoke and restart checks separately from retained cold-case lifetime timing failures. Keep qualification and capability levels unchanged.
Reuse the request-owned core witness at the raw WASI read and complete source-owner boundaries. Require native evidence for Spin pending-cutoff fixtures without changing production transport, timing or limits. Record passing root, native, pinned SDK and harness checks separately from retained lifetime timing failures. Keep Fastly native-wait and hosted qualification gates open.
Bind request-owned observations to the exact submitted SDK body handles and share a resource-before-release test owner with stream witnesses. Validate native wait outcomes, chronology and call counts without additional SDK probes or production policy changes. Retain strict timing failures and separate local characterization from exact-candidate and hosted qualification.
Extend the existing lifetime fixture and bounded wire origin with the required 100/800 ms streamed-body scenario. Observe the original batch only after EOF and validate arrival-based results, original cutoff, source framing and nonoverlapping operation records. Keep the expanded runtime inventory unqualified with both strict timing failures recorded. No production API, runtime pin, capability or CI invocation changes.
Exercise original origin streams alongside a pending bidder body and Send after batch creation through the existing lifetime fixture. Bound and validate actual read/Next-return observations, cutoff timing, arrival attribution and source framing without another transport or scheduler. Reject missing EOF evidence and waits that do not overlap continuing reads. Both new local cases pass; retain full-inventory timing failures and open exact-candidate and hosted qualification gates.
Reuse the existing lifetime binary, bounded three-slot origin and canonical log reader. Retain request-start-relative budgets, delay collection through the paired provider scope, and verify original elapsed values against actual SDK body releases and causal source writes. Add negative controls for collection-stamped or coordinated early timing, missing releases and malformed protocol tails. All five root gates, 454 harness tests and the expanded 24-case local Fastly inventory pass. Keep exact-candidate and hosted qualification open.
…ilures Add native SDK ownership, buffered parity, budget and lifecycle acceptance probes through existing suite owners. Reuse the fixture client factory rather than adding a public batch-context accessor. Reconcile all 217 required-local bindings, retain strict runtime failures and pending cancellation evidence, and keep hosted qualification open. Preserve original deadlines, limits, hard-cut APIs and scope.
Observe Workers writer closure during pending response production while preserving abort/deadline precedence and exactly-once cleanup. Separate the batch quiet timer from the unchanged auxiliary HTTP Send and validate both completion orders. Declare the single-exchange parity origin's connection lifetime and retain exact SDK-visible header caps, including Spin's hidden Connection field. Fix fixture observation-cutoff names and the published audit link. Verified: all five root gates (2666 tests), 576 harness tests, 84 qualification-fixture tests, 111 Workers SDK tests, and all four wire suites with 97 paired vectors each. Axum and repaired-Viceroy lifecycle suites pass. Retain Workers timing failures and Workers/Spin pending-source cancellation gaps; no hosted qualification is claimed.
Retain the first strict cancellation failure while observing bounded diagnostic records until the original coordination deadline. Preserve validated cursors, proof credit, row/byte caps, source budgets and success paths. Route the existing Workers fixture listener directly to the application default socket using pinned SDK APIs. Keep the SDK entry/control listener distinct and ephemeral, with no entry fallback or production transport change. Record the existing Linux Spin connect case: typed ConnectTimeout at 202813 us, exact SYN_SENT ownership and same-client recovery. Retain whole-suite failures and qualification:false; no cancellation, timing, hosted or candidate qualification is claimed. Verified five root gates (2666 tests), 583 serialized harness tests, strict lint/docs guards, 97 Workers paired wire vectors, overflow and fresh/retained smoke, and all 19 Axum lifecycle cases. Workers/Spin pending-source cancellation and remaining timing observations stay open.
prk-Jr
left a comment
There was a problem hiding this comment.
PR Review
Summary
Reviewed head 562acc1d against base 87456c70. The prior blocking findings R1–R4 are fixed at this head: the Axum exact-length EOF validation and detached fallback body, batch completion inference, and the Hooks::configure metadata guard were re-verified by source and targeted tests. No confirmed correctness defect was found in the paths reviewed. Requesting changes for one open question on Fastly NameInUse handling, which could make stable backend names fail on production Fastly. The other findings are non-blocking.
😃 Praise
- Every R1–R4 fix comes with discriminating regression tests (clean/zero/excess/pending EOF tails, trailing driver events, metadata replacement).
- Public error messages are fixed category-only strings; no URL/credential leakage found across core, Axum, Cloudflare, Fastly or Spin.
- The Brotli window is parsed and charged before decoder allocation, and batch index/EOF validation now fails closed.
Findings
Blocking
- ❓ Fastly
NameInUseis fail-closed despite stable cross-sandbox names (crates/edgezero-adapter-fastly/src/outbound.rs:1131)
Non-blocking
- 🤔 Exact
=pins propagate to downstream apps, plus unused direct deps that exist only to force pins (Cargo.toml:46,crates/edgezero-core/Cargo.toml:15) - 🤔 Empty
Connectionlist elements → 502 / fallback 5xx (crates/edgezero-core/src/outbound.rs:2091) - 🤔 Cloudflare 1 ms abort-polling loop (
crates/edgezero-adapter-cloudflare/src/response.rs:466) - 🤔 Batch: late observation + driver EOF → internal error instead of
Cutoff(crates/edgezero-core/src/outbound/batch.rs:519) - 🤔
*_bounded_untildeadline is only checked between chunks (crates/edgezero-core/src/outbound.rs:882) - 🤔 No Fastly dynamic-backend ceiling; blocking registration under the global lock (
crates/edgezero-adapter-fastly/src/outbound.rs:1058) - 🏕 Audit docs are published with local absolute paths.
docs/.vitepress/config.mts:13excludes onlysuperpowers/**, so thedocs/auditspages are built and linked from the guide. 16 audit files contain/Users/<name>/...paths, and guide pages link../audits/evidence/*.jsonfiles, which VitePress likely won't publish (not built to confirm). No secrets found. Suggest scrubbing paths to a placeholder, and deciding whether audits are public docs; if not, addaudits/**tosrcExcludeand link them on GitHub. - 🌱
spin-sdkgit fork: exit plan / source gate (Cargo.toml:106) - ⛏ Dependabot has no
groupsfor linked pin families (fastly/fastly-shared/fastly-sys,brotli/brotli-decompressor,async-compression/compression-codecs/compression-core), so it will open one failing PR per crate. Generator seeds also need hand edits on each bump. - ⛏ Minor:
- Spin maps
HttpRequestDenied(host not inallowed_outbound_hosts) to a 400, which shows a server config error as a client error. - A 204 with a malformed
Content-Lengthis rejected even though 204 strips that header (response_egress_framing.rs:98). - Fastly turns an inbound body read error (client abort mid-upload) into a 500.
- The new rejection of non-top-level
capabilitieskeys in the manifest has no CHANGELOG entry.
- Spin maps
📌 Out of Scope
- At ~500 files, +284k lines and 532 commits, this PR cannot realistically be reviewed exhaustively, so this review is a targeted pass over production paths, not a full audit. Not read in depth: the test harness and fixtures, most of
docs/superpowers/docs/audits,scripts/*.mjs, and the adapter store/CLI modules. Future work would be much easier to review split by core, each adapter, and docs/evidence. - The PR description still states it "remains draft" with every hosted gate unchecked, while the PR is marked ready for review. These findings do not replace that hosted qualification.
CI Status
All 30 checks passed on 562acc1d (fmt, clippy incl. per-target WASM, workspace/CLI/adapter/demo tests, CodeQL).
Local targeted runs passed:
- core batch: 22
- core app/egress/router: 39
- Axum response/hyper: 21
- Fastly lib: 174
- Spin lib: 83, plus store suites 12 + 10
Fastly/Spin/Cloudflare WASM suites were not run locally.
| BackendCreationError::Disallowed => EdgeError::bad_gateway_with_reason( | ||
| DYNAMIC_BACKENDS_DISABLED_MESSAGE, | ||
| BadGatewayReason::Unspecified, | ||
| ), |
There was a problem hiding this comment.
❓ NameInUse is fail-closed, but backend names are deliberately stable across sandboxes
Backend names are a hash of the full identity so they repeat across requests and sandboxes (EZ-2.3, for cross-sandbox connection pooling). The PR's own requirements spec (docs/superpowers/specs/2026-10-17-edgezero-pr275-requirements.md:368, :385) quotes Fastly: "Compute registers dynamic backends at the node level", and records that Trusted Server's Fastly adapter treats NameInUse as reuse.
Here, the only reuse path is the process-static BACKENDS cache (:1058-1075). If a fresh sandbox lands on a node where an earlier sandbox already registered ez_b31v1_<hash>, the cache is empty, finish() returns NameInUse, and this maps to EdgeError::internal — a 500 for every call to that origin until the node releases the backend. Viceroy keeps a per-sandbox backend table, so local/CI tests cannot observe this; it is source-predicted and unverified on hosted Fastly.
Which is the intended production behaviour? If node-level registration is real, a minimal fix would be: on NameInUse, open the existing backend by name, read back its settings (host, port, TLS, override host, timeouts — the audit notes these readbacks work), reuse it and populate the cache when they match the identity, and fail closed only on mismatch. Either way, a hosted probe for this case seems needed before this is production-ready (it is related to, but not covered by, the unchecked B31 hosted gate).
| bytes = "1" | ||
| brotli = "=8.0.4" | ||
| brotli-decompressor = "=5.0.1" | ||
| bytes = "=1.12.1" |
There was a problem hiding this comment.
🤔 Exact = pins on widely shared crates propagate to every downstream app
bytes = "=1.12.1", http = "=1.4.2" (:67), serde_json = "=1.0.150" (:94), url = "=2.5.8" (:117), plus async-compression, flate2, miniz_oxide, etc. Generated apps depend on edgezero-core by git (crates/edgezero-cli/src/generator.rs:344), so these requirements come along, and the generator also seeds bytes = "=1.12.1", fastly = "=0.13.1", worker = "=0.8.5" into the user's workspace.
Cargo allows one version per semver-compatible major, so any user dependency needing e.g. serde_json >= 1.0.151 makes the app unresolvable, and downstream users cannot pick up security patches to these crates until EdgeZero releases.
Suggestion: keep caret requirements in manifests and enforce exact versions through Cargo.lock + the existing --locked CI usage. If some exact pins must stay, limit them to the provider SDKs whose surfaces are matched exhaustively (fastly, worker, spin-sdk).
| @@ -12,11 +12,20 @@ workspace = true | |||
|
|
|||
| [dependencies] | |||
| edgezero-macros = { path = "../edgezero-macros" } | |||
| alloc-no-stdlib = { workspace = true } | |||
There was a problem hiding this comment.
🤔 Direct dependencies that are never used
alloc-no-stdlib, alloc-stdlib, adler2, crc32fast and simd-adler32 are declared here but not referenced anywhere in crates/edgezero-core/src/ (grep). They appear to exist only to force transitive exact pins. This widens the pin problem above to transitive crates, and Dependabot will try to bump each one independently (it has no groups for the linked families). Could these be dropped in favour of the lockfile?
| })?; | ||
| for raw_token in raw_value.split(',') { | ||
| let token = raw_token.trim_matches([' ', '\t']); | ||
| if token.is_empty() { |
There was a problem hiding this comment.
🤔 Empty Connection list elements turn a valid origin response into a 502
RFC 9110 §5.6.1 requires recipients to accept and ignore (a reasonable number of) empty list elements. Here an upstream response with Connection: close, or , close is rejected as a protocol error → 502. The response-egress side does the same (response_egress_framing.rs:325; a scratch probe confirmed "close,", ", close", "close, , x-foo" → InvalidConnectionHeader → adapter fallback 5xx).
Suggest continue on an empty trimmed token in both parsers, keeping the rejection for invalid non-empty tokens.
|
|
||
| use crate::outbound::copy_header_values; | ||
|
|
||
| const ABORT_POLL_INTERVAL: Duration = Duration::from_millis(1); |
There was a problem hiding this comment.
🤔 Abort detection polls with a 1 ms timer for the whole duration of every pending operation
wait_for_abort (:612-616) re-arms setTimeout(1ms) until the signal aborts, and race_operation builds a fresh one for each next_body / write / finish. During a slow upstream or a backpressuring client this is ~1000 timer wakeups per second, each re-polling the race future — Workers CPU time is billed and capped, so a slowly streamed response can cost noticeably more or hit CPU limits. (Source-predicted; no hosted measurement.)
Suggestion: register a one-shot abort event listener on the AbortSignal that sets a flag and wakes the task, keeping the signal.aborted() checks before/after each operation.
Minor, same function: Delay::from(remaining) truncates to whole ms (worker uses as_millis() as i32) and the Deadline branch is trusted without re-checking deadline.is_expired_at(clock.now()), so a write can be aborted up to 1 ms early. Rounding up (as HostEventYield already does) or re-checking would fix it.
| }, | ||
| Poll::Ready(Ok(Some(OutboundBatchDriverEvent::Cutoff))) => self.validate_cutoff(), | ||
| Poll::Ready(Ok(None)) => { | ||
| if self.resolved.iter().all(|resolved| *resolved) { |
There was a problem hiding this comment.
🤔 Late observation followed by driver EOF becomes an internal error instead of Cutoff
record (:640-650) correctly ignores an item completed after the observation cutoff (marks it seen, not resolved). But if a raw-observation driver then simply ends, this branch returns driver ended before every slot resolved. Executed scratch repro: 2 slots, cutoff 100, driver emits item 0 @10, item 1 @110, EOF → collect() is Err(internal) with slot 0 preserved, instead of a Cutoff result.
So every from_driver implementation must re-derive core's eligibility predicate to know when to emit Cutoff (Axum duplicates it at adapter-axum/src/outbound.rs:251-252), and that obligation is not stated on OutboundBatchDriverEvent::Cutoff. Drift (e.g. at the equality instant) turns a legitimate cutoff into a 500-class failure.
Suggest either: on Ok(None), if every unresolved slot was seen-after-cutoff, finish via validate_cutoff(); or document the obligation on the public enum and add a test for this sequence.
| /// Returns 504 when the deadline is observed expired, otherwise a typed source or | ||
| /// `BufferedBody` response-limit error. | ||
| #[inline] | ||
| pub async fn into_bytes_bounded_until( |
There was a problem hiding this comment.
🤔 *_bounded_until deadlines are only checked between chunks
collect_response_stream_inner checks the deadline before/after each source.next().await but arms no timer. If the upstream stalls mid-body, the call stays pending past the caller's deadline until the request budget timer fires (default 30 s), and the error then carries the request's cause rather than the caller's deadline. The docs say "cooperative", but _until reads as a hard bound.
Suggest racing time.wait_until(deadline) in the loop (as OwnedPayload::poll_active does), or stating the possible overrun explicitly in the rustdoc.
| if let Some(record) = observation { | ||
| record.configuration(name.clone()); | ||
| } | ||
| // Serialize registration and insertion; NameInUse alone cannot certify a configuration. |
There was a problem hiding this comment.
🤔 No ceiling on dynamic backend registrations; a blocking registration holds the global cache lock
Each distinct (host, authority, port, TLS, connect-ms) tuple can yield up to ~31 timer-rung backends, with no cap or eviction, against Fastly's 200-per-service limit. Per the spec, registration at the limit "blocks execution"; that finish() hostcall runs while holding the BACKENDS mutex inside the progress poll, stalling every in-flight exchange. The audit acknowledges no total ceiling is established.
Suggest a per-sandbox registration ceiling that fails fast with a typed 502, or documenting it as a hard operator constraint.
| spin-sdk = { version = "~7.0", default-features = false, features = ["http", "key-value", "variables"] } | ||
| # The Spin outbound classifier exhaustively matches this SDK's WASI HTTP | ||
| # snapshot, so both dependencies move only through an explicit review. | ||
| spin-sdk = { version = "=7.0.0", git = "https://github.com/stackpop/spin-rust-sdk.git", rev = "6c59ed5b4fcb377072763aee0b27a3abdd8edb72", default-features = false, features = ["http", "key-value", "variables"] } |
There was a problem hiding this comment.
🌱 spin-sdk from a git fork — consider an exit plan and a source gate
The reason is documented in the audits/CHANGELOG (executor fix; upstream spinframework/spin-rust-sdk#169), but this comment gives only the exhaustive-classifier reason, and the generator seeds the same fork into user projects. Suggest mentioning the executor reason and the upstream PR here, and adding cargo deny check sources advisories with allow-git limited to this URL (there is currently no deny/audit gate).
Summary
Implements the portable outbound HTTP and request-lifecycle contracts across core and the Axum, Cloudflare, Fastly, and Spin adapters.
start_batch_until, indexednext, explicitcancel, orderedcollect, and thesend_all_untilconvenience path.start_batch_untiltakes an observation cutoff: reaching it stops observation even when individual slots retain budget, while earlier cutoffs remain a supported partial-result operation.PlatformMetadatafacts for memory ceilings, live inbound request population, and host-ingress accounting, preserving source and explicit unknown reasons.Fits,Exceeds, and typedIndeterminateoutcomes; publishes canonical Axum, Cloudflare, Fastly, generic Spin, and Akamai Functions profiles.CompletedorCutoff. OnlyCutoffpermits unresolved slots in a successful result. Explicit adapter failure, premature driver EOF, and duplicate or out-of-range indices returnOutboundBatchFailure, preserving the precise error and every terminal slot collected before failure.MonotonicClock::deadline_afteranchors relative cutoffs to that clock. Equality expiry wins and backwards time fails closed.ResponseEgressCompletion, transferred directly throughPreparedIngress,ResponseEgressEnvelope, and the soleResponseEgressAttempt. Terminal state is stored before the response-scoped completion and global observer run, each exactly once and behind independent panic boundaries. No response-extension carrier or envelope extraction bypass remains.ResponseEgressCompletion::joincomposition so independent response-owned resources share one exactly-once terminal report, and hard-cuts detached normalized errors toSend { completion, deadline } | Abortwith request-start-relative bounded deadlines.AdmissionDecision::Abort. Axum closes the owned HTTP/1 connection before body polling; Cloudflare, Fastly, and Spin return a fixed provider error at their strongest available pre-response boundary and remain conservatively classifiedBestEffort.Hooks::configureplus core-ownedApp::build::<A>(platform). Successful hooks must preserve the complete adapter-selected metadata; core rejects changed facts instead of restoring them. Typed configuration failures propagate unchanged and stop serving before request handling. The generated scaffold keeps finite ingress policy with core-owned empty lifecycle tokens; the checked-in demo retains the full application-owned resource-composition example.AbortController, Fastly's low-levelstream_to_client, and Spin's WASI response/body/result writers.Current Checkpoint: Workers Batch Cutoff
Head:
8f82547b. Repairs a confirmed adapter-owned scheduling gap without changing public APIs, request budgets, capability levels or SDK/runtime pins. Specification, regression and native-evidence boundaries.The local review packet contains 99 hash-verified files:
/private/tmp/pr275-cutoff-coordinator-packet.tar.gz, SHA-25627837dc0fdb5785550ced06f7666e58091508e9ac64bbd11c884d2755195be68. It preserves RED/GREEN and final verification logs, the actual native patch/build and all failures, separately from the final source patch. Temporary local storage is not durable qualification. Demo/templates require no signature migration and inherit the adapter repair. No deployment, freeze, merge or maintainer review-state change is performed; the eight manual hosted checkboxes below are unchanged. New-head CI must execute separately.Earlier Checkpoint: Exact-Head Evidence Mapping
Tracking commit:
46019b2d. This documentation-only checkpoint maps evidence for reviewed source562acc1dedbf169315853900f9395e7ff5160076; it does not freeze or qualify either revision. Audit and evidence boundaries.12287f9f; Cloudflare/Spin do not embed a source SHA. The 30 successful checks associated with reviewed head562acc1ddo not establish exact-head runtime qualification.The local review packet contains 231 hash-verified files:
/private/tmp/pr275-562acc1d-closeout-packet.tar.gz. SHA-256:d96a6a50a80b87dad910fe43e2ca71d53ea887f7711d83cc5d26867af56fc4d6. It retains the original metadata draft separately, corrected pre-freeze record, complete derived leg map, raw captures/builds and supporting CI crosswalk. This temporary archive is not durable Q5 publication. Source APIs, adapters, demo/templates, SDK/runtime pins and outbound guarantees are unchanged. No deployment, freeze, merge or change to the maintainer-managed PR review state is performed. The eight manual hosted checkboxes below are preserved unchanged.Earlier Checkpoint: Workers Timer Setup Repair
Head:
562acc1d. The reviewed repair, regressions, specification, driver plan and changelog are committed and pushed. Source is clean. Investigation and evidence boundaries.Hosted CI at this update: 30 successful / 0 neutral or skipped / 0 running or queued / 0 failed reported checks. Local verification is not a substitute for unfinished hosted checks.
A separate, hash-verified review packet contains 111 files preserving raw controls, temporary instrumentation, RED/GREEN logs, final verification and exact-commit runtime artifacts. Packet SHA-256:
00a5573ac25d504e50e1953bb585ffb043b04a7d10bb6a440268bc0e78e6eb25. Lifetime Wasm SHA-256:e4730e8f068c15ac35b7c7e28e70327fb06097d787eee7eba60fa6ac26c6c6bd. Prior macOS/Linux failures and earlier packets remain retained separately; diagnostic passes are not copied into release evidence. Local temporary storage is not durable Q5 publication.No public API, SDK/runtime pin, capability, application policy, deadline, observation cutoff or tolerance is changed. Demo/template APIs remain unchanged. No deployment, candidate freeze or merge is performed; this PR remains draft. Hosted verification remains the maintainer's checklist below.
Maintainer Hosted Verification (Manual)
The maintainer will perform and check off these hosted gates manually. No deployment is delegated. Record the exact candidate SHA and link durable evidence; unchecked means unverified, not passed. Keep documented BestEffort/Unsupported limitations unless stronger behavior is actually proved.
Local CI, parser replay and native diagnostics do not check off these hosted gates. Acceptance identities and remaining local failures stay unchanged.
Earlier Checkpoint: Completed-Test Host-Diagnostic CI Repair
Head:
f82e4025. The prior head has 29 successful checks/one failed Fastly job. Its native library reports 309 passed/zero failed, but a known host diagnostic is concatenated directly after a complete namedok; the sentinel guard incorrectly rejects that line. This checkpoint changes only that guard, its co-located tests and tracking docs.fastly-lifecycle-evidenceartifact and fail-first regressions: 103 pass/6 expected failures, covering two formats and four exact inventory environments.okimmediately followed by the existing anchored timestamped Viceroy diagnostic. Reject arbitraryok...suffixes, malformed/missing timestamps, unrelated diagnostics, failed/ignored statuses and wrong names. Preserve every sentinel, listing checks, positive zero-failure summaries, and command/stream exit handling. No workflow, invocation or inventory change.See the repair and verification tracker and original failing job.
Earlier Checkpoint: Absolute Deferred Batch Dispatch
Head:
158b0c0e. This checkpoint corrects the existing lifecycle fixture, not production outbound behavior. APIs/adapters, SDK/runtime pins, original deadlines, caps, acceptance identities and capability levels remain unchanged.DeadlineExceeded1,001 ms, original per-call deadlines 1,034 ms. The complete local suite still exits 1, with 16 pass/3 fail plus a final-log-tail failure: cold Begin entry 9 ms, pending-body cutoff 206 ms, and ordinary-close cancellation remain unqualified. Pending-head cutoff returns at 204 ms in this run; earlier failed observations are not erased. Retain the initial missing-workerd preflight as unverified exit 2.See the current tracker and audit.
Earlier Checkpoint: Native Spin Result Before EOF
Head:
8fbc4f83. This checkpoint changes the existing Spin SDK controls, validation and retained evidence only. Production APIs/adapters, SDK/runtime pins, original deadlines, acceptance identities and capability levels are unchanged.See the native record, pinned source analysis and implementation tracker.
Earlier Checkpoint: Explicit Reset Diagnostic
Head:
cd214362. This checkpoint changes test tooling and evidence only. Production outbound APIs, adapters, SDK/runtime pins, original deadlines, caps, acceptance identities and capability levels are unchanged.RequestCancelled, exactly-once SDK/source release, healthy survivor work and a clean diagnostic tail. Ordinary close still fails, with no victim terminal through the original coordination window. Reset success is diagnostic only, not a replacement acceptance gate.See the current diagnostic and runtime tracker.
Earlier Checkpoint: Native Runtime Boundaries And Linux Connect
Head:
f036425b. Production adapters, public APIs, provider pins, deadlines, caps and original acceptance identities are unchanged.defaultsocket in the existing Workers fixture launcher using the pinned Miniflare API. No entry-forwarding fallback; the SDK entry/control listener remains on a distinct ephemeral loopback port. Guest flags, modules, bindings, persistence and owned shutdown remain intact. Standard serve/deploy paths are unchanged.qualified:false; external, conditional and unpromoted scope is unchanged.See the current tracker and canonical Linux connect evidence.
Earlier Checkpoint: CI And Local Lifecycle Repairs
Head:
22c6386c. All 217 required-local acceptance legs now have executable bindings (255 criteria/511 legs; 246 ready/265 planned overall). Binding completeness is not passing runtime qualification. External, conditional and unpromoted scope remains unchanged.See the current implementation and evidence tracker for exact observations and remaining gates.
Earlier Checkpoint: Fastly Post-Delivery Batch
Head:
775366fd. Extend the existing D6 lifetime suite with a three-slot batch created after canonical response handoff, using the same retained client and original request clock. Preserve 34 ms batch entry, 534 ms cutoff and one-second per-call timeouts. No production API, SDK/runtime pin, capability or CI invocation changes.Earlier Checkpoint: Fastly Trickling Slots And Live-Batch Send
Checkpoint
f0ce2b38adds EZ-6 criteria 7/8 to the existing Fastly fixture and lifetime suite. Production outbound APIs, transport, scheduler, deadlines, limits, SDK/runtime pins and CI invocations are unchanged.See the master/D6 tracker, SUITES.md and changelog for exact scope and retained results.
Earlier Checkpoint: Fastly Origin-Body Arrival Coverage
Checkpoint
eb8ac5dfadds the missing EZ-6 criterion 6 case to the existing Fastly lifetime suite. No new runner, transport, scheduler, SDK probe, production API/policy, pin or CI invocation.See the current master/D6 tracker, SUITES.md and changelog for exact scope and evidence.
Earlier Checkpoint: Fastly Native Body-Readiness Witness
Checkpoint
5950548dadds the distinctly labelled, request-owned test-only Fastly native readiness witness. Production outbound APIs, deadlines, B31 policy, limits, SDK/runtime pins and CI invocations remain unchanged.See the implementation tracker, SUITES.md and changelog for scope and retained evidence. Demo/templates require no migration for test-only metadata.
Earlier Checkpoint: Spin Native Pending-Body Witness
Checkpoint
92e03fe8extends the existing request-owned, test-only native witness to Spin. Production outbound APIs, transport, deadlines and resource policies are unchanged.See the implementation tracker, SUITES.md and changelog for the verified scope and retained evidence. Demo/templates need no change for this test-only integration.
Earlier Checkpoint: Cloudflare Native Module Manifests
Checkpoint
deb00840repairs the existing local launcher for the selected Wrangler 4.131.0 / Miniflare 5.20260910.0-alpha / workerd 2026-09-10 combination. Production outbound APIs and adapters are unchanged.persist/v3layout, startup attestation, private diagnostics and owned disposal. Both smoke modes pass, including seeded config, declared-KV and outbound-progress checks. A separate bounded local diagnostic proves namespace...02survives process restart and is read before another write.See the current implementation tracker and SUITES.md for exact scope, checks and retained evidence.
Earlier Checkpoint: Native Pending-Body Witnesses
Checkpoint
3523e121adds finite, request-owned test-only SDK observations on Axum and Cloudflare. Prepared URI, clock, mode and budget come from shared dispatch; production policies are unchanged.CI follow-up
c6f3aaf0uses canonicalobservation_cutoffnaming. The unchanged guard, 28 Axum contracts and strict lint pass locally; all 30 reported checks passed at that checkpoint.next, beforecollect. Require full controller-selected target/origin identity, Batch/BatchCutoff, the original deadline, Pending before cutoff and release between cutoff and return. Preserve 34/200/205 ms targets and zero-head/read control.rootPathagainst the owned config directory with sanitized errors.modulesRules. Failed runs get no credit; SDK-reader unit tests do not substitute for actual fetch/runtime proof.See the implementation tracker and SUITES.md for exact checks and retained failures. The prior Fastly dispatch checkpoint retains its SDK-dispatch-only scope and three guarded proofs.
The previous focus compiler checkpoint added numeric and compiler ownership through the existing grouped Rust check; its 434-test harness and other verification remain recorded separately, not relabelled as fresh evidence. Earlier provider-boundary proofs, typed-focus approval/CLI lint, audit formatting and tooling consolidation retain their scopes and open gates.
Earlier Checkpoint: Registration Observations And Connect Capabilities
outbound-connect-timeout: Fastly declares independent provider-backed support as Native; Axum, Cloudflare and Spin retain BestEffort acceptance. Fastly's split-free flexible phase budgeting is Native. These declarations do not qualify hosted connect precision, DNS/TLS coverage, blocking-call preemption, deadlines or cancellation.Checkpoint:
2cbbc549, following registration observations at00a9edbd. The implementation tracker records exact scope, evidence and remaining gates. This checkpoint is historical; current readiness and check status are recorded above.Earlier Checkpoint: Response-Owned Outbound Handoff
Checkpoint:
abbc2c11. Detailed local artifacts and failures are recorded in the D6 response-handoff tracker checkpoint.Earlier Checkpoint: Core Mixed-Observation Acceptance Binding
EZ-6/acceptance/22@unit/core, replacing its placeholder with five executable receipt/accumulator proofs. Run six exact three-slot cases: fresh and mixed check/next/collect under Completed, Cutoff and an original typed driver failure. Stage terminal production after both mixed receipts transfer.--lib outbound::; discover all 56 exact sentinels, including the original 51 redirect proofs. No new job or per-test CI list. The old redirect-only selection fails before execution because it omits the five batch proofs. Use the shared raw Cargo log path without relabelling older evidence.Checkpoint:
279c5a93.Earlier Checkpoint: Buffered Cap During Batch Progress
caps-while-waitinglifetime case through the production clients: 128 KiB decoded gzip trickling over 300 ms, independent 1 MiB decoded / 64 KiB buffered / 256 KiB encoded limits, healthy B/C siblings, and the original 34/534 ms batch timeline.Checkpoint:
8c11307d. Final local artifacts and individual failed timing preconditions are recorded in the D6 buffered-cap tracker checkpoint.Earlier Checkpoint: Reviewed Spin SDK Integration
6c59ed5b4fcb377072763aee0b27a3abdd8edb72(WASIp3 0.10.0 / wit-bindgen 0.63.0). Align the root, demo, reusable/request-fidelity fixtures, generator and all four application lockfiles.Checkpoint:
87b5e1ce. These are local regression results, not a frozen candidate or hosted qualification. D6 closure, native body-entry evidence, consumer acceptance and hosted qualification remain open. The acceptance inventory remains 32 ready / 479 planned and unqualified.Earlier Checkpoint: Fourth-Slot Per-Call Expiry
Implemented in cd8e77e4, within the approved D6 acceptance work:
Earlier Checkpoint: Readiness-Driven Test Origins
Implemented in d3f48564, under the requester's scoped fixture-accept approval:
CI diagnostic follow-up 11b8f2c4 adds underlying errors to two existing request-fidelity version-test assertions. The prior Linux workspace failure occurred before the collector tests; its OS/process cause was not exposed and remains unproven. The fresh run passes both the request-fidelity step and the complete shared-harness tests on Linux. No test conditions, retries, version policy or subprocess behavior changed; other CI checks and provider qualification remain separate.
Earlier Checkpoint: Same-Client CPU Calibration
Implemented in 0d09236a, under the requester's scoped calibration approval:
Earlier Checkpoint: CPU Stretch Characterization
Implemented in 44baaf3b:
Earlier Checkpoint: Pending Cutoff Lifetime Probes
Implemented in 73ed39ba, following the main integration:
host-head-written-only, not proof that the SDK consumed headers or entered a body read. Full criterion 16, remaining D6 work and hosted qualification stay open. Production outbound code, signed SDK/decoder pins, frozen requirements/interfaces and capability levels are unchanged; inventory remains 32 ready/479 planned and unqualified.Earlier Checkpoint: Coordinated Spin SDK Executor Upgrade
Implemented in 7b68f737:
e65ff90dadf4173b08b14194e878ad3acd555337; its DCO check passes. Upstream Rust 1.94 CI remains separate from local Rust 1.98.1 verification.spawn_local. Root, demo, reusable fixture and generator use identical Git URL/revision and package version; guards compare all three. Lock changes stay within the affected SDK/bindings/macro graph. Decoder/map contracts remain unchanged.qualified: false; full acceptance binding, candidate freeze and authorized hosted qualification remain open.Earlier Checkpoint: Begin/Batch Lifetime Probes and SDK Gap
Implemented in 834a009e:
wit-bindgen 0.57.1.qualified: false. CPU-stretch, remaining lifetime/registration/consumer acceptance, candidate freeze and authorized hosted qualification remain open.This is a verified test/diagnostic checkpoint, not a passing full lifetime suite or completed feature qualification.
Earlier Checkpoint: Standalone Test Harness and Redirect Bindings
Implemented in b5f94c70:
crates/edgezero-test-harness, with a non-published standalone workspace and its own lockfile. Remove the old runner package/directory without an alias or duplicate implementation. Keep deployable fixture apps separate and unit/contract tests in their owning crates.qualified: false. Readiness records executable assertions, not consumer adoption, applicability approval or exact-candidate qualification.This completes the approved runner relocation and local redirect binding checkpoint, not the whole adoption plan. Lifetime/registration acceptance, successful native optimizer transformation/redirect/performance evidence, consumer integration, candidate freeze and authorized hosted qualification remain open. Optional idle-body policy is not silently adopted. No deployment, capability promotion or production outbound behavior change occurs.
Earlier Checkpoint: Local Workerd Redirect Acceptance
Implemented in 4e64db99:
outbound-wirematrix and bounded two-origin servers as Spin. A fixture-only route obtains the production client from the canonical request context; no Fetch replacement, parallel outbound transport or new host-language runner is used.Successful native optimizer redirects, conditional idle-policy coverage, complete criterion-level binding and consumer/hosted acceptance remain open. The inventory remains eleven ready legs, 500 planned and
qualified: false.Earlier Checkpoint: Rust Spin Wire Harness
Implemented in 361da4f1:
--adapter spin --suite outbound-wirein the existing Rust fixture harness. No Python or Node replacement runner, compatibility wrapper, dependency changes or second process supervisor remains.This checkpoint is test-tooling only. No hosted deployment, capability promotion, candidate freeze or optimizer performance claim is made. The inventory remains eleven ready legs, 500 planned and
qualified: false.Earlier Checkpoint: Provider Redirect Boundaries
Implemented in 699cd49c:
Workerd/origin parity, successful optimized-first-hop redirects, conditional idle-policy coverage, complete criterion-level acceptance binding, candidate freeze and consumer/hosted qualification remain open. Native optimizer dispatch is preserved; unavailable-boundary controls do not establish transformation or performance. No deployment is performed. The inventory remains eleven ready legs, 500 planned and
qualified: false.Earlier Checkpoint: Fastly Cooperative-Wake CI Repair
Implemented in f57b8130:
qualification: false.Still open: provider-runtime redirect acceptance, exact-candidate criterion bindings, resource-policy decisions and consumer/hosted qualification. All previous outbound guarantees and direct native Image Optimizer integration remain intact.
Earlier Checkpoint: Explicit Redirect Following
Implemented in e02c2360:
HttpClient::followAPI with a required synchronous application policy and validated 1..=20 redirect limit. Plain Send, Begin and Batch remain unfollowed.Still open: other provider-runtime Follow parity, actual Fastly optimizer-hop mapping, consumer composition, exact-candidate criterion bindings, resource-policy decisions and hosted qualification. The inventory remains eleven ready legs, 500 planned and
qualified: false. No deployment or capability promotion occurred, and the PR remains draft. Current tracker.Earlier Checkpoint: Shared Outbound Pipeline and Ownership
Implemented in 2be1dd87:
Open at that checkpoint: explicit same-client redirect following (now implemented in the checkpoint above), remaining exact-candidate acceptance bindings, resource-policy decisions and hosted qualification. Local runtime evidence does not promote capabilities or prove end-client delivery. The PR remains draft. See the current tracker.
Earlier Checkpoint: Live Paired Time
Implemented in d86d4c0d, with the isolated Cloudflare test-ordering correction in f4d660b1:
with_time/ Axumtry_with_time, removing clock-only constructors without aliases.OutboundTimefor live asynchronous deadline handling. Check timers before source polling, preserve operational errors and diagnostics, retain clock high-water observations across chunks/yields, and release terminal/cancelled ownership.This completes only the approved sequencing checkpoint. The public head-first trait, settlement/context issuance, batch receipts, eager Begin, redirect integration and hosted qualification remain open. Requirements and frozen Plan 02 hashes are unchanged. See the verification audit.
Earlier Checkpoint: Bounded Synthesized Headers
Added in
d47c8026:This checkpoint is not completion of the broader adoption plan or hosted qualification. The full head-first/eager/redirect migration, Fastly's failed G2 preserving-read proof, all nine failed Fastly framing SDK parity controls, Cloudflare overflow recovery, consumer integration and exact-candidate hosted qualification remain open. No capability is promoted, no compatibility layer is restored, and the PR remains draft.
Reviewer correctness follow-up
Addressed R1–R4 in
92111839:Main merge and shared-policy follow-up
Addressed R5 and R6 in
91f4af38, merging main683202c6without restoring superseded APIs:OutboundBatch::from_futures; adapters retain preflight validation, exchange ownership, clocks, and terminal samples. Ready results remain retained, driver EOF/index invariants remain enforced, and cutoff releases pending futures before reporting termination. Fastly retains its distinct provider-handle driver.ResponseBodyPolicyandapply_response_body_policy, preserving declared-length checks, encoded limits, decoding/header rewriting, decoded limits, passthrough, and rechunk order. Transport reads, bodyless handling, deadlines, cancellation, and final buffering remain adapter-owned.Result<(), E>through a wrapper that prevents SDK-generated second responses.R7's dependency-audit-script deduplication remains deferred; dependency contract checks remain unchanged and pass.
Bounded native ingress and config follow-up
ConfigValuereturns. Axum constructors requireConfigStoreLimits;from_mapis fallible. Reads share payloads, and local config push updates require a server restart.serde_json 1.0.150, hash canonical JSON incrementally, and release extraction's raw handle before secret retrieval. A moving-reallocation malformed-root probe measured 36,428 requested peak bytes under a 100,060-byte staging cap, with zero retained bytes after rejection.Unsupportedand response egress remainsBestEffort. Local emulators and guest contract tests are not deployed runtime evidence.Bounded provider reads and lifecycle qualification infrastructure
FinalizationRegistrycleanup support. Generated and demo Workers explicitly enableenable_weak_ref, and regression tests inspect their TOML rather than assuming an exact one-flag string.try_opennow returns typedConfigStoreError.Downstream acceptance impact
Cloudflare
outbound-deadlinesandstreamed-upload-deadlinesareBestEffort, notNative. Downstream acceptance suites must use best-effort deadline wording and must not claim exact cancellation enforcement until deployed host-observed evidence exists.The response completion, ingress abort, and fallible application-assembly changes are intentional breaking changes. Consumers must provide a completion on every response-producing admission decision and propagate
App::build::<A>(platform)failures.Evidence boundaries
Capability declarations remain conservative where provider behavior is not proved:
Unsupportedon all adapters.Nativeon Axum andBestEfforton Cloudflare, Fastly, and Spin because finite host-side teardown is not proved or synchronously preemptible.Nativeon Axum's owned HTTP/1 connection andBestEfforton Cloudflare, Fastly, and Spin because provider transport reset/close is not directly observable.BestEfforton every adapter because no boundary proves end-client receipt; provider-specific blocking and teardown limits are documented.Unsupported; provider parsing/materialization, SDK copies, informational responses, trailers, allocator overhead, and other host-owned memory remain outside guest-visible caps.BestEfforton every adapter because provider operations are not proved cancellable within a finite wall-clock interval.BestEffortpending a deployed host-observed cancellation artifact. Fastly and Spin retain their separately documented deadline and isolation limitations. Fastly declares split-free phase budgeting Native; its independent connect setting remains unqualified for hosted timing precision.Validation
This checklist records validation across PR checkpoints. The exact latest reruns and remaining acceptance failures are listed above; it is not a claim of hosted qualification or a fresh run of every historical matrix.
scripts/run_tests.shcargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo test --workspace --all-targetscargo check --workspace --all-targets --features "fastly cloudflare spin"Closes
Closes #436.