Upgrade to Rust 1.98.1 and refresh dependencies - #366
Open
aram356 wants to merge 14 commits into
Open
Conversation
Move the pinned toolchain from 1.95.0 to 1.98.1 (current stable) and take every semver-compatible dependency update. Toolchain pins move together so a generated app builds on the same release this repo does: `.tool-versions`, the demo's Fastly `rust-toolchain.toml`, and the CLI scaffold generator. A new test asserts the generator's pin matches `.tool-versions` -- previously only a doc comment asked the two to be bumped in step, and they had already drifted. Three releases of new clippy `restriction` lints land with the bump: - `inline_trait_bounds` (~42 sites) -- generic bounds moved to `where` clauses. - `duration_suboptimal_units` -- `Duration::from_mins` is const-stable as of 1.98, so `MIN_TTL` uses it and its `#[expect]` is dropped. - `inline_modules` -- allowed workspace-wide, in the demo, and in the scaffold template. It flags every `#[cfg(test)] mod tests` block; colocated tests are the mainstream Rust idiom and what CLAUDE.md mandates. - `missing_trait_methods` now wants `Drop::pin_drop` on three RAII guards. That method is behind the unstable `pin_ergonomics` feature and the compiler rejects implementing it alongside `drop`, so no stable code satisfies the lint; each site gets an `#[expect]` that will fail once the method stabilises. redb 4.2.0 added an assertion that read references not outlive their transaction, which caught a latent bug in the persistent KV store: `get_bytes` held an `AccessGuard` borrowed from the table across the `drop(table); drop(read_txn)` in its lazy-expiry path. The value is now copied out before the transaction ends, so the update goes in rather than being pinned back. The demo workspace moves to edition 2024, matching the main workspace and the scaffold templates. `cargo fix --edition` wrapped the config test's `env::set_var`/`remove_var` in `unsafe` blocks with FIXMEs; the demo denies `unsafe_code`, so the test uses the existing `edgezero_core::test_env::EnvOverride` guard instead, which also restores the variable when an assertion panics. Edition 2024 let-chains collapse a nested `if let` in the demo handlers. All five CI gates pass on 1.98.1, and the three wasm targets (wasip1/wasip2/unknown-unknown) compile.
The `inline_trait_bounds` sweep ran on the host target, so it never linted code behind `target_arch = "wasm32"` or the adapters' wasm-only `tests/contract.rs`. CI's per-target clippy matrix caught seven remaining sites across the three adapters; all move to `where` clauses. Toolchain references outside `.tool-versions` now read 1.98.1: the CLAUDE.md toolchain table, the illustrative version in the two toolchain-file parsers, and the deploy-core test harness defaults that stand in for a real deploy. Two literals in `deploy-core/tests/run.sh` stay at 1.95.0 on purpose -- they pair with a 1.60.0 fixture to assert that an app's own `.tool-versions` wins over the deployer's, so the values are arbitrary and only their precedence matters. The `pub_with_shorthand` note claimed 6 offending items, verified on clippy 1.95. Re-running the check on 1.98 with the allow removed reports 44, so the comment now says 44 rather than carrying a stale count forward. `docs/superpowers/**` keeps its 1.95 mentions: those are dated design records describing the stack as it was when each was written, and the VitePress config excludes them from the published site.
Moves the tools `.tool-versions` pins to current releases, each verified against the workload CI actually runs it for: - Fastly CLI 15.1.0 -> 16.0.0. The major carries no breaking changes (a starter-kit bounds fix and dependency bumps); every subcommand the adapter shells out to -- `compute serve`, `config-store list --json`, `config-store-entry list`, `service`, `service-version`, `resource-link` -- still exists with the same flags. - Viceroy 0.17.0 -> 0.21.0. Runs the Fastly wasip1 suites: 6 contract tests and 88 runtime unit tests pass. - wasmtime 44.0.1 -> 48.0.1. Runs the Spin wasip2 contract suite: 12 tests, same result as on 44.0.1. - Node.js 24.12.0 -> 24.20.0, staying on the Krypton LTS line rather than jumping to 26.x. The docs site lints and builds on it. `deploy-fastly/versions.json` moves in lockstep with a real checksum for the v16.0.0 linux-amd64 archive, cross-checked against the `fastly_v16.0.0_SHA256SUMS` release asset. `install-fastly.sh` fails closed when versions.json and `.tool-versions` disagree, and the `real-install` job downloads and verifies the archive for real, so a wrong digest here breaks CI rather than shipping. The scaffold generator pins all four tools, so generated apps get the same set. Its drift test now covers nodejs, fastly and viceroy alongside rust -- confirmed to fail, with the offending tool named, when a pin is changed in only one of the two files. Two 15.1.0/1.95.0 literals in the deploy-core tests stay put: they are self-contained fixtures asserting resolution precedence and checksum-mismatch rejection, where only the relationship between the values matters.
sha2 0.11 returns `hybrid_array::Array` from `finalize()`/`digest()`.
Unlike 0.10's `GenericArray` it does not implement `LowerHex`, so the
two `format!("{:x}", ..)` call sites no longer compile.
Hand-rolling the hex is the wrong answer here: every version of it
trips a different `restriction` lint in turn (`indexing_slicing` for a
lookup table, `cast_possible_truncation` for `as`, then
`arithmetic_side_effects` for the nibble maths). `base16ct` is
RustCrypto's own encoder -- same org as sha2, `no_std`, and with no
dependencies of its own, so it stays WASM-safe -- and
`lower::encode_string` restores both call sites to a one-liner.
Taking 0.11 on our direct dependency drops sha2 0.10 from the tree
entirely; the workspace now resolves a single sha2.
Output is unchanged: `canonical_form_pin_v1` still pins
903a0e4a..., and the 51 `chunked_config` tests -- including the
writer/resolver round trip that reads back an envelope by its embedded
digest -- pass under Viceroy on wasm32-wasip1.
`cargo update` only moves within the ranges the manifests allow, so seven crates were still held a major behind. Six of them upgrade: - brotli 8 -> 9, similar 2 -> 3, validator 0.20 -> 0.21 (both workspaces, since the demo pins it separately) -- no source changes. - fastly and log-fastly 0.12 -> 0.13. The Fastly wasip1 suites pass under Viceroy: 88 runtime unit tests and 6 contract tests. - rusqlite 0.32 -> 0.40. `prepare_cached` is no longer on `Transaction`; the one call site in the Spin KV writer uses `prepare` instead, which prepares the statement once and reuses it across the batch exactly as before. The push_sqlite suite still passes, including the round trip through Spin's vendored schema. spin-sdk stays at ~6.0. 7.0 compiles clean on wasm32-wasip2 and its 12 contract tests pass under wasmtime, but it imports `wasi:http/types@0.3.0`, which Spin 4.0.2 does not provide -- the component fails to link at `spin up`, which neither `cargo check` nor the wasmtime-hosted tests can see. The pin comment now records that error verbatim so the next attempt starts from the evidence. Reverting restores `smoke_test_kv.sh spin` to 8/8. The scaffold generator seeds `validator` and `fastly` for generated apps, and its own comment requires the validator major to match this workspace or a generated crate fails to compile against `edgezero-core`'s re-derived `Validate`. Both seeds move with the workspace, and a new test asserts the shared seeds track the root manifest -- confirmed to fail, naming both versions, when they drift.
The six deploy smoke jobs failed on the validator 0.20 -> 0.21 bump: error[E0277]: the trait bound `FixtureAppConfig: validator::traits::Validate` is not satisfied `make-smoke-fixture.sh` generates an app-owned CLI that takes `edgezero-core` by path but pinned `validator` itself. Once the workspace moved to 0.21 the fixture still asked for 0.20, so the derive expanded against one `Validate` while the crate imported another. Confirmed by rebuilding the fixture locally: 0.20 reproduces the CI error exactly, 0.21 builds. That made three copies of the same pin found one failure at a time -- the workspace, the demo, the scaffold seeds, and now the fixture -- so `check_shared_dep_pins.sh` compares all of them against the root manifest and runs beside the existing gates in test.yml. Verified it reports each location, by name and version, when that pin is changed in only one file. Cargo cannot catch this itself: the demo workspace is excluded, the scaffold seed is a string literal, and the fixture manifest does not exist until CI generates it.
Self-review of the earlier commits. `get_bytes` copied the value bytes on every path, including the expired one where they are dropped two statements later in favour of `Ok(None)`. It also asked `is_expired` twice about the same value and left `Ok(Some(value))` depending on an invariant the reader has to reconstruct -- that the expired branch always returns first, so `value` cannot be `None` there. Expiry is now decided once, while the `AccessGuard` is still alive, and the bytes are copied only when they will be returned; the delete path falls through instead of nesting. The app-demo env test's comment still described mutating process env in place and leaned on a sibling test's `env_overlay: false` for safety. Both stopped being true when it moved to `env_lock` + `EnvOverride`; the comment now names the lock and the restore-on-drop. `check_shared_dep_pins.sh` matched only the table form of the pin. It fails closed on the bare form (`validator = "0.21"`) rather than passing silently, but that turns a harmless reformat into a red build, so `pin_in` now accepts either spelling.
The `base16ct` pin carried five lines explaining that sha2 0.11's `finalize()` stopped implementing `LowerHex`. That is why the change was made, not something a later reader has to know to avoid breaking anything, and the commit that introduced it already says so. The pin now reads like every other entry in the list. The redb comment spent its second half restating what the two following statements plainly do. What is worth keeping is the part a reader cannot see: redb asserts that no read reference outlives its transaction, so the borrow has to end before the drops. Without that the code looks needlessly roundabout and the obvious simplification reintroduces the panic. The `inline_modules` and `spin-sdk` comments stay. Every other entry in the clippy allow-list carries its reason, so a bare allow would be the odd one out and an easy deletion; and the spin-sdk note is what stops the next attempt rediscovering that 7.0 compiles, passes the contract tests, and only then fails to link at `spin up`.
Three issues from review. The demo lockfile still resolved validator_derive 0.20.0, which pulls proc-macro-error2 2.0.1 -- the crate behind the "rejected by a future version of Rust" warning that has been printing on every demo build. The root lockfile had already moved to 0.20.1 and proc-macro-error3; the demo now matches, and the warning is gone. brotli goes back to 8. `async-compression` 0.4.44 resolves brotli 8 through compression-codecs 0.4.39 (the current release), so taking 9 on the direct dependency never replaced that copy -- it added a second complete allocator/decompressor stack that every adapter graph compiles. Measured on the demo Spin release build: 7,169,574 bytes with both, 7,129,410 with one, so ~40 KB of wasm bought nothing. We call only `Decompressor` and `CompressorWriter`, which are unchanged across the two majors. This is the same duplicate-stack test that kept sha2 honest; it should have been applied to every major, not just that one. `check_shared_dep_pins.sh` read the pin with an unanchored match and took the first hit, so a commented-out `# validator = "0.19"` above the real line became the expected version and the gate reported three violations against three correct files. The match is now anchored to an assignment at line start (optionally inside a Rust string literal, which is how the scaffold seeds it), and a miss normalises to empty via `|| true` so the missing-pin diagnostics run instead of `set -e` killing the script at the command substitution.
spin-sdk moves to `~7.0`. The earlier hold was accurate about the symptom -- 7.0 imports `wasi:http/types@0.3.0` and the component fails to link -- but wrong to treat it as a property of the SDK. It is a property of the runtime that was installed: Spin 4.0.2 does not carry that interface and Spin 4.1.0 does. Verified end to end rather than by compiling: `smoke_test_kv.sh spin` is 8/8 against a real `spin up` on 4.1.0. The demo workspace and the scaffold seed pin spin-sdk separately and move with it; `.tool-versions` now names Spin 4.1 as the floor instead of the stale 3.7. `redb` was declared `4.1.0` while resolving 4.2.0. The caret made that work, but 4.2 is the release whose read-reference assertion caught the `AccessGuard` bug fixed earlier in this branch, so the declared floor now matches the version whose behaviour the code depends on. `check_shared_dep_pins.sh` had a second, unanchored parser for the generator seed that the earlier fix missed. A commented-out seed above the real assignment shadowed it, which both failed a correct tree and passed an incorrect one; a missing seed printed nothing at all, because `set -e` aborted at the command substitution. It now calls `pin_in` like the other paths and reports a missing seed by name. Also refreshes both lockfiles (20 packages in the root, a larger backlog in the demo, which had never taken the earlier sweep) and moves the demo off anyhow 1.0.102, which carries an unsoundness advisory. brotli stays at 8: compression-codecs 0.4.39 is current and still resolves brotli 8, so taking 9 adds a second allocator and decompressor rather than replacing the first.
aram356
requested review from
ChristianPavilonis and
prk-Jr
and removed request for
prk-Jr
September 5, 2026 22:53
`npm update` inside the declared ranges; `package.json` is unchanged. eslint 10.9.1 -> 10.10.0, @types/node 24.12.4 -> 24.13.3, and brace-expansion 5.0.6 -> 5.0.9 transitively, which is what Dependabot #353 proposes. @types/node stays on the 24 line on purpose: it describes the Node runtime, and `.tool-versions` pins nodejs 24.20.0 (the active LTS). Taking the 26 line that Dependabot #368 proposes would type against APIs the pinned runtime does not have. vitepress, prettier, @eslint/js and typescript-eslint were already at their latest releases. `npm audit` still reports three advisories, all the same root: vitepress 1.6.4 -> vite 5.4.21 -> esbuild 0.21.5, with no fix available. 1.6.4 is the newest vitepress (2.x is alpha only), and the advisory is a dev-server issue in a dev-only dependency, so it does not reach `vitepress build` or the published site.
`docs/guide/adapters/spin.md` still documented the `~6.0` pin in its schema-coupling note. It now names `~7.0`, matching the workspace. The prerequisites also listed "Spin CLI" with no floor. spin-sdk 7 imports `wasi:http/types@0.3.0`, which Spin 4.0.x does not provide, and the failure mode is unhelpful: the component builds, the contract tests pass under wasmtime, and only `spin up` reports a linker error naming an interface the reader never wrote. The requirement and that error are now stated where someone would look before hitting it. Checked the rest of the published guide for claims this branch invalidated: the remaining crate mentions are version-agnostic, and the `sha256` sections describe the envelope format, which the sha2 0.11 move left byte-identical.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cargo updatealone cannot reach. Onlybrotliis held back, with the reason and the measurement recorded at the pin.restrictionlints in code where a fix exists, and migratesexamples/app-demoto edition 2024 so it matches the main workspace and the scaffold templates.Changes
.tool-versions,examples/app-demo/.../rust-toolchain.toml1.95.0→1.98.1crates/edgezero-cli/src/generator.rs1.98.1and the current tool/crate versions, so new apps match this repo; drift tests assert both against the real filesCargo.toml,Cargo.lockinline_modulesallowcrates/edgezero-adapter-axum/src/key_value_store.rsget_bytescopies the value out before dropping the read txncrates/edgezero-core/src/key_value_store.rsMIN_TTLusesDuration::from_mins(1); stale#[expect]removed-core/src/canonical_form.rs,-adapter-fastly/src/chunked_config.rsbase16ct::lower::encode_stringedgezero-core,-adapter,-adapter-fastly,-adapter-axum,-cli,-macroswhereclauses (48 sites in total, incl. the wasm-only ones below)crates/edgezero-core/src/{app_config,test_env}.rs,-adapter-fastly/src/cli.rs#[expect]for the unsatisfiablepin_droplintcrates/edgezero-cli/src/templates/root/Cargo.toml.hbsinline_modulesallow tooexamples/app-demo/**EnvOverridereplacesunsafeenv access; let-chain collapse-adapter-{cloudflare,spin,fastly}wasm paths +tests/contract.rsCLAUDE.md, deploy-core scripts/tests.tool-versions,deploy-fastly/versions.jsonNew clippy lints
Three releases' worth arrive at once, because the workspace enables the entire
restrictiongroup atdeny.Fixed in code:
inline_trait_bounds(48 sites) — bounds moved towhereclauses.duration_suboptimal_units—Duration::from_minsis const-stable as of 1.98, soMIN_TTLuses it and its#[expect]is dropped.Allowed, with reasons:
inline_modulesflags every#[cfg(test)] mod testsblock — 77 of them. Complying means splitting each into a sibling file, which contradicts CLAUDE.md's "colocate tests with implementation modules". Colocation is also what std, tokio and serde do. Allowed in the workspace, the demo, and the scaffold template so generated apps don't inherit the problem.missing_trait_methodsnow wantsDrop::pin_dropon three RAII guards. That method sits behind the unstablepin_ergonomicsfeature, and the compiler rejects implementing it alongsidedrop(conflicting implementations of Drop::drop and Drop::pin_drop) — no stable code satisfies the lint. Each site gets an#[expect], which will itself fail once the method stabilises, prompting a revisit.redb 4.2.0 caught a real bug
redb 4.2.0 initially failed
ttl_expires_entryandcontract_ttl_expireswith a panic pointing into redb's own page manager:This reads like an upstream regression but isn't. redb added an assertion that read references must not outlive their transaction, and it caught
get_bytesholding anAccessGuard(borrowed from the table) across thedrop(table); drop(read_txn)in its lazy-expiry path — silently wrong on 4.1.x. The value is now copied out before the transaction ends, so the update goes in rather than being pinned back. Otherdrop(table)sites in that file are write transactions with no live read guard.CLI tooling
Each pin was verified against the workload CI runs it for, not just installed:
deploy-fastly/versions.jsonmoves in lockstep with a real SHA-256 for the v16.0.0 linux-amd64 archive, cross-checked against thefastly_v16.0.0_SHA256SUMSrelease asset. This matters:install-fastly.shfails closed when versions.json and.tool-versionsdisagree, and thereal-installjob downloads and verifies the archive for real — a wrong digest breaks CI rather than shipping.The scaffold generator pins all four, so generated apps get the same set, and its drift test covers nodejs/fastly/viceroy alongside rust. I confirmed it fails, naming the offending tool, when a pin is changed in only one of the two files.
Host clippy does not cover the wasm targets
cargo clippy --fixruns against the host target, so it never linted code behindtarget_arch = "wasm32"or the adapters' wasm-onlytests/contract.rs. CI's per-target clippy matrix caught 7 survivinginline_trait_boundssites there. Worth knowing for future lint sweeps: a cleancargo clippy --workspace --all-featureson the host does not imply the wasm targets are clean.Dependency majors
cargo updateonly moves within the ranges the manifests allow, so seven crates sat a major behind. Six upgrade:similarvalidatorfastly,log-fastlyrusqliteprepare_cachedis no longer onTransaction; the one call site usesprepare, which still prepares once and reuses across the batchredbAccessGuardfix above. The declared floor was4.1.0while resolving 4.2.0; 4.2 is the release whose assertion caught that bug, so the floor now matches the behaviour the code relies onspin-sdkbrotlistays at 8 — the one major not taken.async-compression0.4.44 resolves brotli 8 throughcompression-codecs0.4.39 (still the current release), so taking 9 on the direct dependency does not replace that copy — it adds a second complete allocator/decompressor stack that every adapter graph compiles. Measured on the demo Spin release build: 7,169,574 bytes with both stacks, 7,129,410 with one — ~40 KB of wasm for no gain, since we call onlyDecompressorandCompressorWriter, unchanged across the two majors. Whenasync-compressionmoves to 9 the pin should follow and the copies collapse.spin-sdk6 → 7 needed a runtime bump, not a code change. 7.0 importswasi:http/types@0.3.0; Spin 4.0.x does not provide it, so the component compiles and passes its wasmtime-hosted contract tests and then fails to link atspin up:Spin 4.1.0 ships that interface. Verified end to end rather than by compiling —
scripts/smoke_test_kv.sh spinis 8/8 against a realspin up. The demo workspace and the scaffold seed pinspin-sdkseparately and move with it, and.tool-versionsnow names Spin 4.1 as the floor (it still said 3.7).Worth flagging for reviewers:
cargo checkand the wasmtime contract suite both pass on a build that cannot boot. Only the smoke test catches this class.The scaffold generator seeds
validatorandfastly, and its own comment requires the validator major to match this workspace or a generated crate fails againstedgezero-core's re-derivedValidate. Both seeds move, and a new test asserts the shared seeds track the root manifest — confirmed to fail, naming both versions, when they drift.sha2 0.10 → 0.11
finalize()/digest()now returnhybrid_array::Array, which — unlike 0.10'sGenericArray— does not implementLowerHex, so bothformat!("{:x}", ..)call sites stop compiling.Hand-rolling the hex is a trap: each version trips a different
restrictionlint in turn (indexing_slicingfor a lookup table, thenas-truncation, thenarithmetic_side_effectsfor nibble maths).base16ctis RustCrypto's own encoder — same org as sha2,no_std, zero dependencies of its own — andlower::encode_stringrestores both sites to a one-liner.Taking 0.11 on our direct dependency drops sha2 0.10 from the tree. One older copy remains —
fastly0.13 pulls sha2 0.9 transitively — so this goes from three copies to two, not to one.Output is unchanged, which matters because these digests are persisted in config envelopes:
canonical_form_pin_v1still pins903a0e4a…, and the 51chunked_configtests — including the writer/resolver round trip that reads an envelope back by its embedded digest — pass under Viceroy onwasm32-wasip1.A fourth validator pin, and a gate for it
The first push of the
validator0.20 → 0.21 bump turned six deploy smoke jobs red:make-smoke-fixture.shgenerates an app-owned CLI at CI time that takesedgezero-coreby path but pinsvalidatoritself, so the derive expanded against oneValidatewhile the crate imported another. Rebuilding the fixture locally reproduces the error at 0.20 and builds clean at 0.21.That was the pin turning up in a fourth place, one failure at a time — this workspace, the excluded demo workspace, the scaffold seeds, and a manifest that does not exist until CI generates it.
scripts/check_shared_dep_pins.shnow compares all four against the root manifest and runs beside the existing gates intest.yml; it is verified to report each location, by name and version, when only one is changed. Cargo cannot do this itself for any of the three satellites.Review follow-ups
Three issues found reviewing the branch, all fixed in the final commit:
validator_derive0.20.0 →proc-macro-error22.0.1 — the crate behind therejected by a future version of Rustwarning that printed on every demo build. The root lockfile had already moved to 0.20.1 →proc-macro-error3; the demo now matches and the warning is gone.anyhow1.0.102, which has an unsoundness advisory. Both lockfiles are now refreshed and the demo is on 1.0.104.check_shared_dep_pins.shread the pin with an unanchored match and took the first hit, so a commented-out# validator = "0.19"above the real line became the expected version and the gate reported three violations against three correct files. The match is now anchored to an assignment at line start, and a miss normalises to empty via|| trueso the missing-pin diagnostics run instead ofset -eaborting at the command substitution.Toolchain references
Updated to 1.98.1 in
CLAUDE.md, the two toolchain-file parsers' illustrative versions, and the deploy-core test-harness defaults. Two deliberate exclusions:docs/superpowers/**keeps its 1.95 mentions — dated design records describing the stack as it was when each was written, andsrcExcluded from the published site.deploy-core/tests/run.shpair with a1.60.0fixture to assert an app's.tool-versionsbeats the deployer's; the values are arbitrary, only precedence matters.The
pub_with_shorthandcomment claimed 6 offending items (verified on 1.95). Re-running the check on 1.98 reports 44, so the note was corrected rather than renumbered.Note for reviewers
Rust here is managed by asdf, not rustup. After pulling this branch, run
asdf install rust 1.98.1followed byrustup target add wasm32-wasip1 wasm32-wasip2 wasm32-unknown-unknown. Without the asdf install, cargo fails withNo version is set for command cargo— and a clippy run can exit 0 on that message alone, which looks like a pass.Closes
Closes #365
Test plan
Verified on
rustc 1.98.1 (48a229cea 2026-09-01):cargo test --workspace --all-targets— 1424 passed, 0 failedcargo clippy --workspace --all-targets --all-features -- -D warningscargo fmt --all -- --checkcargo check --workspace --all-targets --features "fastly cloudflare spin"wasm32-wasip1(Fastly) /wasm32-wasip2(Spin) /wasm32-unknown-unknown(Cloudflare).github/actions/deploy-core/tests/run.sh— 260 passed, 0 failedexamples/app-demoworkspace: 33 passed, 0 failed, plus clippy clean on edition 2024npm ci && npm run lint && npm run buildon Node 24.20.0edgezero serve --adapter axum— not run; covered by the axum adapter's test suitecanonical_form_pin_v1passes, confirming config-envelope hashes are unchangedscripts/smoke_test_kv.sh spin— 8/8 against a realspin upon Spin 4.1.0 with spin-sdk 7Checklist
{id}syntax (not:id)edgezero_core(nothttpcrate)KvRegistry/ConfigRegistry/SecretRegistry(not the legacy single-handle setters)check_shared_dep_pins.shwired into CI