Skip to content

Add store support for Spin adapter (KV, config, secret)#253

Open
prk-Jr wants to merge 22 commits into
mainfrom
feat/spin-store-support
Open

Add store support for Spin adapter (KV, config, secret)#253
prk-Jr wants to merge 22 commits into
mainfrom
feat/spin-store-support

Conversation

@prk-Jr
Copy link
Copy Markdown
Contributor

@prk-Jr prk-Jr commented Apr 24, 2026

Summary

  • Implements SpinKvStore, SpinConfigStore, and SpinSecretStore so Spin handlers can access key-value, configuration, and secret data through the same ctx.kv_handle(), ctx.config_store(), and ctx.secret_handle() API as every other adapter.
  • Makes Spin run_app manifest-aware: it resolves the KV label, config-store presence, and secret-store enablement from the embedded edgezero.toml before injecting request handles.
  • Adds Spin wasm CI coverage, store injection contract tests, and Spin support to the KV/config/secrets smoke test scripts.
  • Documents Spin-specific store behavior: no KV TTL support, unsupported key listing, flat component-variable config/secrets namespace, and lowercase Spin variable names.

Changes

Crate / File Change
crates/edgezero-adapter-spin/src/config_store.rs New SpinConfigStore backed by spin_sdk::variables; production backend is gated on all(feature = "spin", target_arch = "wasm32"); in-memory test backend runs config-store contract tests on the host
crates/edgezero-adapter-spin/src/key_value_store.rs New SpinKvStore backed by spin_sdk::key_value; regular get/put/delete/exists operations are supported; TTL writes return KvError::Validation; key listing is rejected because Spin Store::get_keys() is unbounded
crates/edgezero-adapter-spin/src/secret_store.rs New SpinSecretStore backed by spin_sdk::variables; uses Spin's flat component-variable namespace and normalizes keys to lowercase to match Spin variable naming rules
crates/edgezero-adapter-spin/src/request.rs Adds manifest-aware store resolution and injects config/KV/secret handles only when enabled or declared by the manifest path
crates/edgezero-adapter-spin/src/lib.rs Updates run_app to accept embedded edgezero.toml, resolves Spin store settings from the manifest, and re-exports manifest-aware dispatch helpers
crates/edgezero-adapter-spin/tests/contract.rs Store injection smoke tests + wasm32 compile-time trait checks for SpinKvStore and SpinSecretStore
crates/edgezero-core/src/manifest.rs Keeps spin out of SUPPORTED_CONFIG_STORE_ADAPTERS and documents why [stores.config.adapters.spin] is rejected
crates/edgezero-core/src/secret_store.rs Documents flat secret namespaces for Cloudflare and Spin, including Spin lowercase component-variable names
docs/guide/kv.md Documents Spin KV binding labels, manifest-aware run_app, unsupported TTL, and unsupported key listing
docs/guide/configuration.md Documents Spin config/secrets as flat component variables and notes that Spin run_app honors manifest gating
.github/workflows/test.yml Adds Spin wasm matrix coverage and caches Wasmtime so the conditional install guard can skip restored binaries
examples/app-demo/edgezero.toml Adds "spin" to the config/KV/secrets routes and sets [stores.kv.adapters.spin] name = "default" for Spin local runtime
examples/app-demo/crates/app-demo-adapter-spin/spin.toml Binds the Spin component to key_value_stores = ["default"] and declares variables for greeting and smoke_secret
examples/app-demo/crates/app-demo-adapter-spin/src/lib.rs Passes the embedded edgezero.toml manifest to edgezero_adapter_spin::run_app
scripts/smoke_test_kv.sh Adds spin case
scripts/smoke_test_config.sh Adds spin case; skips dotted-key checks because Spin variable names cannot contain dots
scripts/smoke_test_secrets.sh Adds spin case; passes secret value via SPIN_VARIABLE_SMOKE_SECRET at startup
.gitignore Adds .spin/ for runtime SQLite KV database and component logs

Closes

Closes #73
Closes #74

Test plan

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-targets
  • cargo check --workspace --all-targets --features "fastly cloudflare spin"
  • cargo check -p edgezero-adapter-spin --target wasm32-wasip1 --no-default-features
  • cargo check -p edgezero-adapter-spin --target wasm32-wasip1 --features spin
  • cargo check --manifest-path examples/app-demo/Cargo.toml -p app-demo-adapter-spin --target wasm32-wasip1
  • ./scripts/smoke_test_kv.sh spin
  • ./scripts/smoke_test_config.sh spin
  • ./scripts/smoke_test_secrets.sh spin

Checklist

  • Changes follow CLAUDE.md conventions
  • No Tokio deps added to core or adapter crates
  • Route params use {id} syntax (not :id)
  • Types imported from edgezero_core (not http crate)
  • New code has tests
  • No secrets or credentials committed

prk-Jr added 14 commits April 24, 2026 20:05
- dispatch() in request.rs now injects ConfigStoreHandle, KvHandle, and
  SecretHandle into request extensions on every request
- SpinSecretStore normalises the lookup key to lowercase so conventional
  uppercase names (e.g. SMOKE_SECRET) resolve to the correct Spin variable
- contract.rs gains store injection smoke tests (config, kv, secret) and
  wasm32 compile-time trait checks for SpinKvStore and SpinSecretStore
- spin.toml gains key_value_stores = ["default"] binding and variables
  declarations for greeting and smoke_secret
- edgezero.toml adds "spin" to adapters for config, kv, and secrets routes
- smoke_test_kv/config/secrets.sh each gain a spin case that builds the
  WASM binary and starts spin up --listen 127.0.0.1:3000; the config
  script skips dotted-key checks (Spin variable names cannot contain dots);
  the secrets script passes SPIN_VARIABLE_SMOKE_SECRET at startup
spin up creates .spin/ (SQLite KV database and component logs) in the
adapter directory during local development, mirroring .wrangler/ for CF.
@prk-Jr prk-Jr self-assigned this Apr 24, 2026
prk-Jr added 2 commits April 25, 2026 18:12
  instead of silently truncating; callers now get an explicit signal
  rather than incomplete pagination results
- Correct DEFAULT_MAX_LIST_KEYS, with_max_list_keys, and module-level
  docs to accurately describe error-return behaviour (not truncation,
  not "unbounded allocation" guarding)
- Add log::debug in SpinSecretStore::get_bytes when store_name is
  non-empty so callers learn the flat-namespace constraint at runtime
- Add comment in config_store contract tests explaining the InMemory
  backend accepts dotted/uppercase keys that the real Spin backend
  would reject via InvalidName
- Add comment in lib.rs explaining why SpinConfigStore has different
  feature gating than SpinKvStore and SpinSecretStore
Copy link
Copy Markdown
Contributor

@ChristianPavilonis ChristianPavilonis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Thanks for adding Spin store support and the smoke/CI coverage. CI is green. I found two configuration-semantics issues worth addressing before relying on non-default store names: Spin KV dispatch is hard-coded to default, and accepting a Spin config-store adapter override is misleading because the runtime does not consume that name.

Comment thread crates/edgezero-adapter-spin/src/request.rs Outdated
Comment thread crates/edgezero-core/src/manifest.rs Outdated
prk-Jr added 2 commits May 14, 2026 12:07
Resolve conflict in test.yml: keep matrix-based wasm test job
(cloudflare/fastly/spin) from this branch; drop main's per-adapter
split jobs which pre-date Spin support.
@prk-Jr prk-Jr requested a review from ChristianPavilonis May 14, 2026 07:04
Copy link
Copy Markdown
Contributor

@ChristianPavilonis ChristianPavilonis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Reviewed the Spin store support changes. The implementation adds useful store coverage and CI/smoke-test expansion, but a few issues need attention before merge: one wasm no-default feature build currently fails, Spin store dispatch bypasses manifest resolution, and KV TTL/listing behavior does not match the core contract.

Cross-cutting finding

  • 📝 Document Spin-specific store behavior: The user docs and secret-store rustdoc still describe KV TTL, config store behavior, and named secret stores as if Spin behaves like the other adapters. After the implementation behavior is finalized, please update docs/guide/kv.md, docs/guide/configuration.md, and crates/edgezero-core/src/secret_store.rs to cover Spin's KV limitations, component variables/flat namespace, lowercase variable names, and whether run_app honors manifest gating.

😃 Praise

  • 😃 The Spin wasm CI matrix entry plus the new smoke-test coverage are a strong addition and should catch real integration regressions across the adapter.

CI Status

  • cargo fmt --all -- --check: PASS
  • cargo clippy --workspace --all-targets --all-features -- -D warnings: PASS
  • cargo test --workspace --all-targets: PASS
  • cargo check --workspace --all-targets --features "fastly cloudflare spin": PASS
  • cargo check -p edgezero-adapter-spin --target wasm32-wasip1 --features spin: PASS
  • Additional check: cargo check -p edgezero-adapter-spin --target wasm32-wasip1 --no-default-features: FAIL (see inline comment on SpinConfigStore)

Comment thread crates/edgezero-adapter-spin/src/config_store.rs
Comment thread crates/edgezero-adapter-spin/src/request.rs
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs Outdated
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs Outdated
Comment thread crates/edgezero-core/src/manifest.rs Outdated
Copy link
Copy Markdown
Contributor

@aram356 aram356 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review

Summary

Adds SpinKvStore / SpinConfigStore / SpinSecretStore plus dispatch wiring, a CI matrix entry, and smoke-test coverage. The CI matrix refactor and smoke-test integration are solid, but several correctness and convention issues need addressing before merge — a wasm32 build that breaks without the spin feature, manifest-unaware dispatch, a TTL contract violation, and the most complex new code path (KV pagination) having no test coverage.

Findings

Blocking

  • 🔧 SpinConfigStore not gated on the spin featurecargo check -p edgezero-adapter-spin --target wasm32-wasip1 without --features spin fails; CI masks it (config_store.rs:47).
  • 🔧 Dispatch ignores the manifest — hardcoded "default" KV label, unconditional config/secret injection (request.rs:116).
  • 🔧 put_bytes_with_ttl reports success while silently dropping the TTL (key_value_store.rs:99).
  • 🔧 max_list_keys cap is checked after the full fetch — does not bound allocation (key_value_store.rs:129).
  • 🔧 manifest doc lists spin as a supported config adapter, contradicting validation (manifest.rs:411).
  • 🔧 list_keys_page pagination logic has zero test coverage (key_value_store.rs:123).

Non-blocking

  • 🤔 KvError::Validation for the cap-exceeded case → HTTP 400 misclassifies a server-state condition as a client error (key_value_store.rs:135).
  • ♻️ run_app cannot reach the non-default KV label (lib.rs:97).
  • 🤔 SpinConfigStore is exported but unconstructable on native non-test builds (lib.rs:26).
  • CI wasmtime conditional-install guard never hits (test.yml:141).
  • 📝 Docs not updateddocs/guide/kv.md and docs/guide/configuration.md have no Spin content; secret_store.rs rustdoc still describes named stores generically. Add Spin's KV limitations (no TTL, O(n) listing), the flat config/secrets variable namespace, and lowercase key normalization.
  • 📝 PR description inaccuracy — the "Changes" table says Added "spin" to SUPPORTED_CONFIG_STORE_ADAPTERS, but the change does the opposite (keeps spin out and adds an explanatory comment). Please correct the description.

CI Status

  • cargo fmt --all -- --check: PASS
  • cargo clippy --workspace --all-targets --all-features -- -D warnings: PASS
  • cargo test --workspace --all-targets: PASS
  • cargo check -p edgezero-adapter-spin --target wasm32-wasip1 (no spin feature): FAIL — see config_store.rs:47

Comment thread crates/edgezero-adapter-spin/src/config_store.rs Outdated
Comment thread crates/edgezero-adapter-spin/src/request.rs
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs Outdated
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs Outdated
Comment thread crates/edgezero-adapter-spin/src/key_value_store.rs
Comment thread crates/edgezero-adapter-spin/src/lib.rs
Comment thread crates/edgezero-adapter-spin/src/lib.rs
Comment thread crates/edgezero-core/src/manifest.rs Outdated
Comment thread .github/workflows/test.yml
@prk-Jr prk-Jr requested a review from aram356 May 20, 2026 12:17
@prk-Jr prk-Jr requested a review from ChristianPavilonis May 20, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spin config/secret store implementation Spin KV store implementation

3 participants