Skip to content

Add config store read path and split storage module#548

Open
prk-Jr wants to merge 8 commits intofeature/edgezero-pr2-platform-traitsfrom
feature/edgezero-pr3-config-store
Open

Add config store read path and split storage module#548
prk-Jr wants to merge 8 commits intofeature/edgezero-pr2-platform-traitsfrom
feature/edgezero-pr3-config-store

Conversation

@prk-Jr
Copy link
Copy Markdown
Collaborator

@prk-Jr prk-Jr commented Mar 23, 2026

Summary

  • Split fastly_storage.rs into storage/{config_store,secret_store,api_client,mod}.rs for better separation of concerns
  • Add PlatformConfigStore read path in the Fastly adapter (FastlyPlatformConfigStore::get via ConfigStore::try_open/try_get)
  • Migrate get_active_jwks and handle_trusted_server_discovery to use &RuntimeServices instead of the legacy FastlyConfigStore directly

Changes

File Change
crates/trusted-server-core/src/storage/mod.rs New module root; re-exports StoreName, StoreId, UnavailableKvStore
crates/trusted-server-core/src/storage/config_store.rs New: PlatformConfigStore stub with read support and NotImplemented write stubs
crates/trusted-server-core/src/storage/secret_store.rs New: PlatformSecretStore with NotImplemented write stubs
crates/trusted-server-core/src/storage/api_client.rs Renamed/trimmed from fastly_storage.rs; retains API client helpers
crates/trusted-server-core/src/fastly_storage.rs Deleted; replaced by storage/ module
crates/trusted-server-core/src/lib.rs Export storage module; remove fastly_storage export
crates/trusted-server-core/src/platform/error.rs Add PlatformError::NotImplemented variant
crates/trusted-server-core/src/platform/traits.rs Document NotImplemented on write methods in trait doc comments
crates/trusted-server-core/src/platform/types.rs Add StoreName/StoreId newtypes; add UnavailableKvStore; add RuntimeServicesBuilder
crates/trusted-server-adapter-fastly/src/platform.rs Add FastlyPlatformConfigStore::get; stub write methods on config/secret store impls
crates/trusted-server-adapter-fastly/src/main.rs Use RuntimeServicesBuilder; update import paths after storage module rename
crates/trusted-server-core/src/request_signing/jwks.rs Migrate get_active_jwks to accept &RuntimeServices
crates/trusted-server-core/src/request_signing/endpoints.rs Migrate handle_trusted_server_discovery to accept &RuntimeServices; add success-path test using StubJwksConfigStore
crates/trusted-server-core/src/request_signing/rotation.rs Update call site (mechanical import rename)
crates/trusted-server-core/src/request_signing/signing.rs Update call site (mechanical import rename)

Closes

Closes #484

Test plan

  • cargo test --workspace
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • JS tests: cd crates/js/lib && npx vitest run
  • JS format: cd crates/js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses tracing macros (not println!)
  • New code has tests
  • No secrets or credentials committed

- Split fastly_storage.rs into storage/{config_store,secret_store,api_client,mod}.rs
- Add PlatformConfigStore read path via FastlyPlatformConfigStore::get using ConfigStore::try_open/try_get
- Add PlatformError::NotImplemented variant; stub write methods on FastlyPlatformConfigStore and FastlyPlatformSecretStore
- Add StoreName/StoreId newtypes with From<String>, From<&str>, AsRef<str>
- Add UnavailableKvStore to core platform module
- Add RuntimeServicesBuilder replacing 7-arg constructor
- Migrate get_active_jwks and handle_trusted_server_discovery to use &RuntimeServices
- Update call sites in signing.rs, rotation.rs, main.rs
- Add success-path test for handle_trusted_server_discovery using StubJwksConfigStore
- Fix test_parse_cookies_to_jar_empty typo (was emtpy)
@prk-Jr prk-Jr self-assigned this Mar 23, 2026
Copy link
Copy Markdown
Collaborator

@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.

Review Summary

Well-structured PR — the storage module split is clean, the PlatformConfigStore read path is correctly implemented, and the migration to &RuntimeServices preserves error context properly. No blockers. CI is fully green.

Highlights:

  • Strong newtype pattern for StoreName/StoreId prevents mix-up bugs
  • RuntimeServicesBuilder with exhaustive expect("should ...") messages
  • Graceful KV store degradation with UnavailableKvStore fallback
  • Excellent test_handle_trusted_server_discovery_returns_jwks_document test

Findings: 0 blockers, 2 high, 4 medium, 3 low


Findings placed in body (line not in diff)

🤔 [P2] Value not URL-encoded (pre-existing)crates/trusted-server-core/src/storage/api_client.rs line 122

The payload format!("item_value={}", value) sends application/x-www-form-urlencoded content but doesn't actually URL-encode value. If value contains &, =, +, spaces, or JSON characters ({, }, "), the Fastly API may misinterpret it. This is pre-existing code (moved from fastly_storage.rs) but worth flagging since it's used in key rotation.

Consider: let payload = format!("item_value={}", urlencoding::encode(value));

Copy link
Copy Markdown
Collaborator

@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.

👍 Looks good. Ship it


// TODO: Deduplicate this transitional helper with
// trusted-server-adapter-fastly/src/platform.rs:get_config_value once
// FastlyConfigStore is removed.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤔 thinking — This duplicated ConfigStoreReader trait (also in platform.rs) is acknowledged by the TODO. Worth tracking in an issue to make sure the cleanup happens soon — if the legacy removal drifts beyond the next 1-2 PRs, these could diverge silently.

Same applies to SecretStoreReader in secret_store.rs.

/// Explicit port, or `None` to use the scheme default.
pub port: Option<u16>,
/// Whether to verify the TLS certificate.
pub certificate_check: bool,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤔 thinkingcertificate_check is security-sensitive and defaults to true in BackendConfig, but PlatformBackendSpec is a plain struct where a caller could construct it and forget to set this field (getting false from Default). A constructor with a safe default would prevent that.

impl PlatformBackendSpec {
    pub fn new(scheme: String, host: String) -> Self {
        Self {
            scheme,
            host,
            port: None,
            certificate_check: true,
            first_byte_timeout: Duration::from_secs(30),
        }
    }
}

/// Geographic information lookup.
pub(crate) geo: Arc<dyn PlatformGeo>,
/// Per-request client metadata extracted at the entry point.
pub client_info: ClientInfo,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤔 thinking — Minor inconsistency: client_info is pub (directly mutable from outside the crate) while all other fields are pub(crate) with pub read-only accessors. Intentional since ClientInfo is a simple data struct?

/// preserved as context in the error chain.
pub fn get_active_jwks(services: &RuntimeServices) -> Result<String, Report<TrustedServerError>> {
let active_kids_str = services
.config_store()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤔 thinking — This reads active-kids, then reads each kid individually — each config_store().get() call opens the store fresh in the Fastly adapter. For the typical 1-2 kids this is fine, but worth noting if the kid count ever grows.

@prk-Jr prk-Jr changed the base branch from main to feature/edgezero-pr2-platform-traits March 30, 2026 09:43
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.

Split fastly_storage.rs + config store trait (read-only)

3 participants