Skip to content

Wire request signing to RuntimeServices store primitives (PR 9)#609

Merged
prk-Jr merged 90 commits intomainfrom
feature/edgezero-pr9-wire-signing-to-store-primitives
Apr 29, 2026
Merged

Wire request signing to RuntimeServices store primitives (PR 9)#609
prk-Jr merged 90 commits intomainfrom
feature/edgezero-pr9-wire-signing-to-store-primitives

Conversation

@prk-Jr
Copy link
Copy Markdown
Collaborator

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

Summary

  • Replaces direct FastlyConfigStore/FastlySecretStore construction in request_signing/ with RuntimeServices platform traits, making the signing subsystem platform-agnostic
  • Moves management API write operations (config item / secret CRUD) out of trusted-server-core into an adapter-only FastlyManagementApiClient, enforcing the EdgeZero layering rule that only the adapter may call Fastly-specific APIs
  • Threads RuntimeServices into AuctionContext so PrebidAuctionProvider (and future providers) can call RequestSigner::from_services without a deprecated FastlyConfigStore shim

Changes

File Change
crates/trusted-server-adapter-fastly/src/management_api.rs NewFastlyManagementApiClient with update_config_item, delete_config_item, create_secret, delete_secret via Fastly management API
crates/trusted-server-adapter-fastly/src/platform.rs FastlyPlatformConfigStore::put/delete and FastlyPlatformSecretStore::create/delete delegate to FastlyManagementApiClient
crates/trusted-server-adapter-fastly/src/main.rs Wire services into /verify-signature handler; add mod management_api
crates/trusted-server-core/src/request_signing/signing.rs Rewrite — RequestSigner::from_services(&RuntimeServices) replaces from_config(); verify_signature accepts &RuntimeServices; deprecated shim removed
crates/trusted-server-core/src/request_signing/rotation.rs Rewrite — KeyRotationManager::new() now infallible; all methods accept services: &RuntimeServices
crates/trusted-server-core/src/request_signing/endpoints.rs All handlers accept services: &RuntimeServices; tests use in-memory stub stores
crates/trusted-server-core/src/auction/types.rs AuctionContext gains pub services: &'a RuntimeServices
crates/trusted-server-core/src/auction/orchestrator.rs Pass services through derived AuctionContext construction sites
crates/trusted-server-core/src/auction/endpoints.rs Pass services when constructing AuctionContext
crates/trusted-server-core/src/integrations/prebid.rs Use RequestSigner::from_services(context.services) — no more #[allow(deprecated)]
crates/trusted-server-core/src/platform/test_support.rs Add build_services_with_config_and_secret test helper
crates/trusted-server-core/src/storage/api_client.rs DeletedFastlyApiClient moved to adapter-only management_api.rs
crates/trusted-server-core/src/storage/mod.rs Remove api_client module and FastlyApiClient re-export
docs/superpowers/plans/2026-03-31-pr9-wire-signing-to-store-primitives.md Implementation plan

Closes

Closes #490

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
  • Manual testing via fastly compute serve

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

prk-Jr and others added 30 commits March 18, 2026 16:54
Rename crates/common → crates/trusted-server-core and crates/fastly →
crates/trusted-server-adapter-fastly following the EdgeZero naming
convention. Add EdgeZero workspace dependencies pinned to rev 170b74b.
Update all references across docs, CI workflows, scripts, agent files,
and configuration.
Introduces trusted-server-core::platform with PlatformConfigStore,
PlatformSecretStore, PlatformKvStore, PlatformBackend, PlatformHttpClient,
and PlatformGeo traits alongside ClientInfo, PlatformError, and
RuntimeServices. Wires the Fastly adapter implementations and threads
RuntimeServices into route_request. Moves GeoInfo to platform/types as
platform-neutral data and adds geo_from_fastly for field mapping.
- Defer KV store opening: replace early error return with a local
  UnavailableKvStore fallback so routes that do not need synthetic ID
  access succeed when the KV store is missing or temporarily unavailable
- Use ConfigStore::try_open + try_get and SecretStore::try_get throughout
  FastlyPlatformConfigStore and FastlyPlatformSecretStore to honour the
  Result contract instead of panicking on open/lookup failure
- Encapsulate RuntimeServices service fields as pub(crate) with public
  getter methods (config_store, secret_store, backend, http_client, geo)
  and a pub new() constructor; adapter updated to use new()
- Reference #487 in FastlyPlatformHttpClient stub (PR 6 implements it)
- Remove unused KvPage re-export from platform/mod.rs
- Use super::KvHandle shorthand in RuntimeServices::kv_handle()
- 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)
- Make StoreName and StoreId inner fields private; From/AsRef provide all
  needed construction and access
- Add #[deprecated] to GeoInfo::from_request with #[allow(deprecated)] at
  the three legacy call sites to track migration progress
- Enumerate the six platform traits in the platform module doc comment
- Extract backend_config_from_spec helper to remove duplicate BackendConfig
  construction in predict_name and ensure
- Replace .into_iter().collect() with .to_vec() on secret plaintext bytes
- Remove unused bytes dependency from trusted-server-adapter-fastly
- Add comment on SecretStore::open clarifying it already returns Result
  (unlike ConfigStore::open which panics)
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.

Overall this is a well-architected PR — the core crate is now genuinely platform-agnostic for signing, and the management API isolation to the adapter is the right layering. A few correctness and structural items below, none blocking.


Note: One finding could not be placed as an inline comment because the relevant line is not part of the diff:

🤔 Module doc still references Fastly-specific store semantics (crates/trusted-server-core/src/request_signing/mod.rs, line 8)

The module doc still says "Fastly stores have two identifiers" and references ConfigStore::open / SecretStore::open. Since the whole point of this PR is platform-agnostic signing, this doc should use platform-neutral language (e.g. "Platform stores have two identifiers" and reference the trait methods).

Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/endpoints.rs
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/auction/orchestrator.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/mod.rs Outdated
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.

Summary

This PR cleanly separates the Fastly management API client from trusted-server-core into the adapter layer, replacing direct FastlyConfigStore/FastlySecretStore usage with RuntimeServices platform traits. The architecture improvement is solid. Two items need clarification before merge.

Blocking

🔧 wrench

  • Secret storage format change: the new FastlyManagementApiClient::create_secret base64-encodes the secret field at the transport layer (and uses PUT), while the old FastlyApiClient::create_secret sent it as raw text (POST). Since rotation.rs::store_private_key already base64-encodes the raw key, the effective payload format has changed. Need confirmation on Fastly API contract and backward compatibility with existing keys. (management_api.rs:68)

❓ question

  • Broadened status check: old code checked for specific status codes (OK, NO_CONTENT), new code uses is_success() (any 2xx). Was this intentional? (management_api.rs:90)

Non-blocking

🤔 thinking

  • Per-call client construction: each write call constructs a new FastlyManagementApiClient (4x during rotate_key). SDK caching mitigates this, but worth considering caching at a higher level. (platform.rs:69)
  • parse_active_kids untested directly: edge cases like ",", "", " kid-a , , kid-b " are not covered by focused unit tests. (mod.rs:56)

♻️ refactor

  • signing_store_ids returns unnamed tuple: fine for two values, but a named struct would improve readability if more settings are added. (endpoints.rs:168)

⛏ nitpick

  • JWKS_STORE_NAME/SIGNING_STORE_NAME visibility: pub but only used within the crate — pub(crate) would be more precise. (mod.rs:49)
  • PR checklist says "tracing": actual code and CLAUDE.md use log macros.

CI Status

  • integration tests: PASS
  • browser integration tests: PASS
  • prepare integration artifacts: PASS

Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/platform.rs
Comment thread crates/trusted-server-core/src/request_signing/mod.rs
Comment thread crates/trusted-server-core/src/request_signing/mod.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/endpoints.rs Outdated
@prk-Jr prk-Jr requested a review from aram356 April 10, 2026 08:47
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.

Summary

The architectural move — extracting FastlyApiClient from trusted-server-core into trusted-server-adapter-fastly::management_api and threading RuntimeServices through signing and auction — is exactly the right direction for EdgeZero's platform-agnostic core. Local fmt/clippy/cargo test --workspace all pass, and integration checks on GitHub are green.

Four blocking items prevent merge as-is, all clustered around the rotate/deactivate lifecycle. Fixing (1) first will likely surface (2) and (3) via real tests without any further changes.

Blocking

🔧 wrench

1. Handler tests in request_signing/endpoints.rs assert nothing (crates/trusted-server-core/src/request_signing/endpoints.rs:542-658)

test_handle_rotate_key_with_empty_body, test_handle_rotate_key_with_custom_kid, test_handle_deactivate_key_request, test_handle_deactivate_key_with_delete, and test_handle_trusted_server_discovery all use this pattern:

match result {
    Ok(mut resp) => { /* log … no asserts */ }
    Err(e) => log::debug!("Expected error in test environment: {}", e),
}

They pass whether the handler succeeds or fails, so the new rotate/deactivate/discovery handler paths are effectively untested even though the PR checklist claims "New code has tests."

Fix: assert on response status and on the success/error fields of the parsed JSON body. Minimum:

let mut resp = handle_rotate_key(&settings, &noop_services(), req)
    .expect("should return a response even when stores are unavailable");
assert_eq!(resp.get_status(), StatusCode::INTERNAL_SERVER_ERROR);
let body: RotateKeyResponse = serde_json::from_str(&resp.take_body_str())
    .expect("should deserialize rotate response");
assert!(!body.success);
assert!(body.error.is_some());

2. SECRET_UPSERT_METHOD = "PUT" on the Fastly secret-store collection endpoint is not a documented API verb (crates/trusted-server-adapter-fastly/src/management_api.rs:31, 257-289)

The previous api_client.rs used POST (the documented create verb); upsert semantics in Fastly's secret-store API are expressed by posting with method: "create_or_recreate" in the JSON body, not by switching the verb.

The only guards here are secret_upsert_method_uses_put (asserts the constant against itself) and create_secret_uses_secret_store_error_for_transport_failures (uses a bogus backend). Neither touches the real API contract. As written, the second rotation of any kid — or a same-day re-rotation via generate_date_based_kid — will likely return 405/400 from the management API in production.

Fix:

const SECRET_UPSERT_METHOD: &str = "POST";

fn build_secret_payload(secret_name: &str, secret_value: &str) -> String {
    serde_json::json!({
        "name": secret_name,
        "secret": general_purpose::STANDARD.encode(secret_value.as_bytes()),
        "method": "create_or_recreate",
    })
    .to_string()
}

This is distinct from the earlier base64 finding — it's about the verb itself.

3. KeyRotationManager::rotate_key is non-atomic across four management-API writes with no rollback (crates/trusted-server-core/src/request_signing/rotation.rs:61-97)

Sequence:

  1. store_private_key (secret store)
  2. store_public_jwk (config store)
  3. update_current_kid (config store)
  4. update_active_kids (config store)

Failure modes that leave the store inconsistent:

  • Fail at (2): private key lives in the secret store with no corresponding JWK — orphaned key material.
  • Fail at (4): current-kid advances to a kid that isn't in active-kids. The edge starts signing with a kid whose JWK is not advertised in the JWKS discovery document, so downstream verifiers that refresh via active-kids will reject every signed request until the store is manually repaired. This is a signing outage.

Fix: on failure after (1) or (2), attempt best-effort deletion of the freshly written artifacts and surface the rollback status in the returned Report. Ideally, reorder so current-kid only flips after both artifacts AND active-kids are confirmed written:

store_private_key → store_public_jwk → update_active_kids → update_current_kid

That ordering ensures any partial failure leaves the old kid still active and the new kid visible in JWKS but unused — a recoverable state.

4. delete_key has a symmetric partial-failure hole that leaks private key material (crates/trusted-server-core/src/request_signing/rotation.rs:205-227)

If deactivate_key and the JWK delete both succeed but secret_store.delete fails, the private key remains in the secret store while its JWK is gone. A retry then fails at the JWK delete step because check_response rejects 404 (see ❓ below), so the operator can't converge by re-running the command.

Fix: order the secret-store delete before the JWK delete so a partial failure leaves a verifiable-but-not-signable orphan JWK (safer than orphaned key material), and treat 404 from both deletes as success so retries converge.

❓ question

5. Are management-API deletes meant to be idempotent? (crates/trusted-server-adapter-fastly/src/management_api.rs:224-322)

check_response rejects any non-2xx, so a 404 on delete_config_item/delete_secret propagates as an error. For key-lifecycle use, idempotent deletes are usually desirable so a retried delete_key converges after a partial failure. Intentional? A minimal change:

if response.get_status() == StatusCode::NOT_FOUND {
    return Ok(());
}

This interacts directly with finding (4).

6. Status check broadened from specific codes to is_success() (crates/trusted-server-adapter-fastly/src/management_api.rs:90)

Old api_client.rs checked specific status codes (OK/NO_CONTENT); now any 2xx passes. Usually a good thing, but worth confirming it's deliberate.

Non-blocking

🤔 thinking

  • TOCTOU in rotate_key (request_signing/rotation.rs:70-89): reads current-kid and active-kids, then writes unconditionally. Two concurrent rotations can lose one side's update. Rotation is admin-gated and rare, so probably acceptable — but a read-before-write invariant check would be cheap insurance.
  • parse_ed25519_signing_key length heuristic is fragile (request_signing/signing.rs:38-56): len > 32 → base64, else raw. The production path always writes base64 via rotation.rs::store_private_key, so a raw value >32 bytes in production means data corruption — and this code hides it behind a misleading "failed to decode base64" error. Consider requiring base64 unconditionally or gating the raw branch behind #[cfg(test)].
  • Per-call client construction (adapter-fastly/src/platform.rs:68-76, 129-142): every put/delete constructs a fresh FastlyManagementApiClient, which re-opens api-keys and re-registers the management backend. Doc acknowledges it, but for a single rotate_key call that's four back-to-back opens to read the same entry. Follow-up could cache an Arc<FastlyManagementApiClient> on the stores behind a OnceLock.

♻️ refactor

  • Inconsistent admin-endpoint response semantics (request_signing/endpoints.rs:237, :345): handle_verify_signature returns 200 with opaque verified: false on internal errors, while handle_rotate_key/handle_deactivate_key return 500 with error: Some(format!("{}", e)) stringifying the full error-stack report. These are admin endpoints and presumably auth-gated upstream, but either the error detail should be opt-in behind a debug flag or the contract should be documented.
  • KeyRotationManager::new takes impl Into<String> (request_signing/rotation.rs:49): CLAUDE.md's "prefer From over Into" guidance suggests &str would be clearer. Minor.

🏕 camp site

  • SpySecretStore::create unconditionally returns Ok (request_signing/rotation.rs:329-342): a failing-create variant would exercise the rollback path requested in (3). A minimal SpySecretStore::with_create_failure_after(n) would unlock real tests for partial-failure recovery.

⛏ nitpick

  • Cargo.toml dep ordering (crates/trusted-server-adapter-fastly/Cargo.toml): trusted-server-js now sits between urlencoding and the alphabetical dependencies.
  • api_key: String (management_api.rs:109): no zeroize-on-drop. Client is short-lived so low-risk, but the previous Vec<u8> is gone. Flagging for awareness only.

👍 praise

  • Extracting FastlyApiClient into the adapter layer is the right layering move — trusted-server-core is now genuinely platform-agnostic for request signing.
  • parse_active_kids now has focused unit tests covering trimming, empty segments, and whitespace-only segments (request_signing/mod.rs:86-128) — directly addresses a prior review comment.
  • SigningPayload using structured JSON instead of delimiter-based formats is a real security improvement (prevents signature confusion attacks), and the round-trip tests in signing.rs validate it end-to-end.

CI Status

  • cargo fmt --all -- --checkPASS (local)
  • cargo clippy --workspace --all-targets --all-features -- -D warningsPASS (local)
  • cargo test --workspacePASS (local)
  • integration tests — PASS (GitHub)
  • browser integration tests — PASS (GitHub)
  • prepare integration artifacts — PASS (GitHub)

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.

Follow-up with inline comments properly pinned to diff lines. Two corrections to the previous review:

  1. Retraction on the "handler tests assert nothing" 🔧: those weak match { Ok => log / Err => log } tests are pre-existing in feature/edgezero-pr8-content-rewriting; this PR only touched them mechanically to pass services through. Not blocking for PR 9. Reclassifying as a 🏕 for a follow-up: while you're in here, please replace them with real assertions — noop_services() returns Err deterministically, so an assertion like assert_eq!(resp.get_status(), StatusCode::INTERNAL_SERVER_ERROR) on the Ok(resp) branch would pin the contract.

  2. Remaining blockers stand (see inline):

    • SECRET_UPSERT_METHOD = "PUT" is not a documented Fastly verb — second same-kid rotation will hit the wire and likely 405.
    • rotate_key / delete_key are non-atomic across four management-API writes with no rollback — partial failures cause signing outages or orphaned key material.

The architectural direction remains the right one; these are lifecycle-correctness holes sitting on top of a clean refactor.

Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs
Comment thread crates/trusted-server-core/src/request_signing/signing.rs
Comment thread crates/trusted-server-adapter-fastly/src/platform.rs
@prk-Jr prk-Jr changed the base branch from feature/edgezero-pr8-content-rewriting to main April 15, 2026 11:50
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Dismissed
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Dismissed
@prk-Jr prk-Jr requested a review from aram356 April 16, 2026 12:56
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.

Summary

Prior review findings on rotation atomicity, POST-based secret upsert, 404-idempotent deletes, base64 contract hardening, and endpoint-test assertions are all resolved cleanly. Blocking concerns on this round are merge-conflict leftovers rather than signing-subsystem bugs.

Blocking

🔧 wrench

  • Out-of-scope proxy.rs regression: per-request allowed_domains is silently ignored — redirect_is_permitted now reads from settings.proxy.allowed_domains at both call sites, and the now-dead ProxyRequestHeaders::allowed_domains field is hidden behind #[allow(dead_code)]. Doc and behavior disagree; integration proxies that defaulted to open mode are now bounded by the global allowlist. (crates/trusted-server-core/src/proxy.rs:440, :604, :731)
  • Unused trusted-server-js dep re-introduced: PR #615 removed it from the adapter as unused; this branch's merge kept it back. base64/serde/serde_json/urlencoding are justified by management_api.rs, but trusted-server-js is not referenced anywhere under crates/trusted-server-adapter-fastly/. (crates/trusted-server-adapter-fastly/Cargo.toml:24)

Non-blocking

🤔 thinking

  • FastlyManagementApiClient reconstructed on every write — a single rotate_key pays four opens of api-keys + four backend re-registrations. (platform.rs:68-76, :129-142)
  • TOCTOU in rotate_key's active-kids RMW — admin-gated so concurrency is unlikely, but worth a cheap check-and-set. (rotation.rs:94-102)
  • Write-cost doc leads with the wrong concern — handle-open caching is a footnote; the outbound HTTPS round-trip to api.fastly.com is the headline. (platform.rs:37-45)

♻️ refactor

  • make_request dispatches HTTP method via string literals — typo-prone; taking fastly::http::Method eliminates the _ => unreachable branch. (management_api.rs:156-165)
  • signing_store_ids returns an unnamed (&str, &str) — flagged previously; a named struct would be clearer at both call sites. (endpoints.rs:168-184)

⛏ nitpick

  • check_response reads response body on success paths — move read_to_string into the error branch. (management_api.rs:86-94)
  • SECRET_UPSERT_METHOD test is self-referential — asserts a const against its own literal; inline the verb or drop the test. (management_api.rs:366-372)

📌 out of scope

  • Plan doc bundled in the diff (+1835 lines)docs/superpowers/plans/2026-03-31-pr9-wire-signing-to-store-primitives.md doubles the reviewer surface area. Plans belong in their own PR or outside review scope.

CI Status

  • fmt: PASS
  • clippy: PASS
  • cargo test: PASS
  • vitest: PASS
  • format-docs / format-typescript: PASS
  • integration tests / browser integration tests: PASS
  • CodeQL: PASS

Comment thread crates/trusted-server-core/src/proxy.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/Cargo.toml Outdated
Comment thread crates/trusted-server-adapter-fastly/src/platform.rs
Comment thread crates/trusted-server-adapter-fastly/src/platform.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/endpoints.rs
- Revert proxy.rs merge artifact: restore per-request allowed_domains
  at both redirect_is_permitted call sites; remove dead_code allow and
  stale comment — integration proxies defaulting to &[] get open mode
  again as documented
- Drop unused trusted-server-js dep from adapter Cargo.toml
- Fix check_response: gate body read behind error branch so 2xx paths
  do not buffer and discard the response body
- Remove self-referential SECRET_UPSERT_METHOD test
- Reorder write-cost doc so outbound HTTPS round-trip leads; handle-open
  caching noted as negligible
- Refactor make_request to take fastly::http::Method; drop string match
  and unreachable arm; remove SECRET_UPSERT_METHOD const
- Add SigningStoreIds named struct in endpoints.rs; update both call
  sites to destructure by name
@prk-Jr prk-Jr requested a review from aram356 April 21, 2026 03:05
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.

Summary

The architectural rewrite is clean — RequestSigner::from_services(&RuntimeServices), KeyRotationManager is infallible, management API writes are adapter-only, and test stubs exercise real crypto. Prior review rounds have addressed the HTTP status handling and Box::leak test-helper issues.

This pass surfaces four correctness/operational concerns around key rotation and the admin surface, plus a test-coverage gap for the rollback paths. None are data-loss bugs, but each can wedge request signing for operators using the admin endpoints.

Blocking

🔧 wrench

  • Same-day re-rotation silently invalidates prior signatures (rotation.rs:66) — inline.
  • No validation on operator-supplied kid (endpoints.rs:146, applies to both rotate and deactivate handlers) — inline.
  • Rollback paths are documented but untested (rotation.rs:80-129) — inline.
  • Deactivating or deleting the current-kid bricks signing (rotation.rs:227-275) — inline. Pre-existing, but this PR finalizes the admin surface.

❓ question

  • Rotation resurrects a previously deactivated previous_kid (rotation.rs:95-99) — inline.

Non-blocking

🌱 seedling

  • PlatformSecretStore::create taking &str forces double-base64 on binary keys (crates/trusted-server-core/src/platform/traits.rs:79). The signing key is base64-encoded in rotation::store_private_key, then base64-encoded again by management_api::build_secret_payload when serialized to the Fastly management API JSON payload. Documented and correct, but the root cause is value: &str in the trait signature — there's no way to pass opaque bytes. Not for this PR, but worth considering value: &[u8] when the trait is next revved. The Fastly adapter would base64-encode internally, other adapters can choose their encoding, and callers stop double-encoding.

⛏ nitpick

  • Transport-failure test reaches into FastlyManagementApiClient struct fields (management_api.rs:387-402) — inline.

CI Status

  • fmt: PASS
  • clippy: PASS
  • rust tests: PASS
  • js tests: PASS
  • browser integration: PASS
  • format-typescript / format-docs: PASS

Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs Outdated
Comment thread crates/trusted-server-core/src/request_signing/endpoints.rs
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs
Comment thread crates/trusted-server-core/src/request_signing/rotation.rs
Comment thread crates/trusted-server-adapter-fastly/src/management_api.rs
@prk-Jr prk-Jr requested a review from aram356 April 24, 2026 08:05
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

Move logging initialization into Fastly adapter (PR 10) (#610)

- Reverted gratuitous _message rename and record.args() usage in logging.rs, returning to the idiomatic message parameter inside the fern format closure.
- Refactored target_label to use .rsplit_once("::") rather than .split("::").last(). This provides a more explicit and robust way to extract the final module segment.
- Expanded target_label test coverage to explicitly test edge cases such as inputs without :: separators, empty strings, and inputs with trailing ::.
@prk-Jr prk-Jr merged commit c7e1e69 into main Apr 29, 2026
13 checks passed
ChristianPavilonis pushed a commit that referenced this pull request May 5, 2026
… and Move logging initialization into Fastly adapter (#610)

* Rename crates to trusted-server-core and trusted-server-adapter-fastly

Rename crates/common → crates/trusted-server-core and crates/fastly →
crates/trusted-server-adapter-fastly following the EdgeZero naming
convention. Add EdgeZero workspace dependencies pinned to rev 170b74b.
Update all references across docs, CI workflows, scripts, agent files,
and configuration.

* Add platform abstraction layer with traits and RuntimeServices

Introduces trusted-server-core::platform with PlatformConfigStore,
PlatformSecretStore, PlatformKvStore, PlatformBackend, PlatformHttpClient,
and PlatformGeo traits alongside ClientInfo, PlatformError, and
RuntimeServices. Wires the Fastly adapter implementations and threads
RuntimeServices into route_request. Moves GeoInfo to platform/types as
platform-neutral data and adds geo_from_fastly for field mapping.

* Address platform layer review feedback

- Defer KV store opening: replace early error return with a local
  UnavailableKvStore fallback so routes that do not need synthetic ID
  access succeed when the KV store is missing or temporarily unavailable
- Use ConfigStore::try_open + try_get and SecretStore::try_get throughout
  FastlyPlatformConfigStore and FastlyPlatformSecretStore to honour the
  Result contract instead of panicking on open/lookup failure
- Encapsulate RuntimeServices service fields as pub(crate) with public
  getter methods (config_store, secret_store, backend, http_client, geo)
  and a pub new() constructor; adapter updated to use new()
- Reference #487 in FastlyPlatformHttpClient stub (PR 6 implements it)
- Remove unused KvPage re-export from platform/mod.rs
- Use super::KvHandle shorthand in RuntimeServices::kv_handle()

* Reject host strings containing control characters in BackendConfig

* Fix clippy error

* Validate scheme and host for control characters in BackendConfig

* Address review findings on platform abstraction layer

* Address review findings on platform abstraction layer

* Add config store read path and storage module split

- 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)

* Harden legacy config-store reads and align Fastly adapter stubs

* Address storage review feedback

* Resolved github-advanced-security bot problems

* Address PR review feedback on platform abstraction layer

- Make StoreName and StoreId inner fields private; From/AsRef provide all
  needed construction and access
- Add #[deprecated] to GeoInfo::from_request with #[allow(deprecated)] at
  the three legacy call sites to track migration progress
- Enumerate the six platform traits in the platform module doc comment
- Extract backend_config_from_spec helper to remove duplicate BackendConfig
  construction in predict_name and ensure
- Replace .into_iter().collect() with .to_vec() on secret plaintext bytes
- Remove unused bytes dependency from trusted-server-adapter-fastly
- Add comment on SecretStore::open clarifying it already returns Result
  (unlike ConfigStore::open which panics)

* Add PR 4 design spec for secret store trait (read-only)

* Clarify test scope and deferred branches in PR 4 spec

* Add implementation plan for PR 4 secret store trait

* Add test for get_secret_bytes open-failure path

* Add NotImplemented tests for FastlyPlatformSecretStore write stubs

* Inline StoreId binding and add section comment in write-stub tests

* Remove plan

* Add PR 6 design spec for backend and HTTP client traits

* Address spec review findings on PR 6 design

* Implement PlatformHttpClient and thread RuntimeServices through proxy layer

- Add PlatformHttpClient trait with send(), send_async(), and select() methods
- Add PlatformBackend trait with predict_name() and ensure() methods
- Add PlatformResponse wrapper around EdgeZero HTTP responses
- Add PlatformPendingRequest and PlatformSelectResult for auction fan-out
- Thread RuntimeServices through IntegrationProxy::handle(), IntegrationRegistry::handle_proxy(),
  and all first-party proxy endpoints so handlers can reach the HTTP client
- Add StubHttpClient and StubBackend test stubs with build_services_with_http_client helper
- Add proxy_request_calls_platform_http_client_send integration test
- Fix proxy_with_redirects to stay within 7-arg clippy limit via ProxyRequestHeaders struct
- Document Body::Stream limitation in edge_request_to_fastly with warning log
- Document intentional duplication of platform_response_to_fastly across proxy and orchestrator
- Remove spec file (promoted to plan + implementation)

* Address pr review findings

* Resolve pr review findings

* Add PR7 design spec for geo lookup + client info extract-once

Documents the call site migration plan: five Fastly SDK extraction
points in trusted-server-core replaced by RuntimeServices::client_info
reads, following Phase 1 injection pattern from the EdgeZero migration design.

* Fix spec review issues in PR7 design doc

- Correct erroneous claim about generate_synthetic_id being called twice
  via DeviceInfo; it is called once (line 91 for fresh_id), DeviceInfo.ip
  is a separate req.get_client_ip_addr() call fixed independently
- Add before/after snippet for handle_publisher_request call site in main.rs
- Add noop_services import instruction for http_util.rs test module
- Clarify _services rename (drop underscore, not add new param) in didomi.rs
- Clarify nextjs #[allow(deprecated)] annotations are out of scope (different function)

* Update PR7 spec to address all five agent review findings

- Change RequestInfo::from_request signature to &ClientInfo (not
  &RuntimeServices) so prebid can call it with context.client_info
- Scope SDK-call acceptance criteria to active non-deprecated code only
- List all six AuctionContext construction sites including two production
  sites in orchestrator.rs and three test helpers in orchestrator/prebid
- Add explicit warn-and-continue pattern for publisher.rs geo lookup
- Correct testing table: formats.rs and endpoints.rs have no test modules;
  add orchestrator.rs and prebid.rs test helper update rows

* Add PR7 implementation plan and address plan review findings

Plan covers 6 tasks in compilation-safe order: AuctionContext struct change
first, then from_request signature, then synthetic.rs cascade, then publisher
geo, then didomi. Includes two new copy_headers unit tests (Some/None).

Spec fixes: clarify injection pattern exceptions for &ClientInfo and
Option<IpAddr>; reword acceptance criterion to reflect that provider-layer
reads flow through AuctionContext.client_info.

* Fix three plan review findings and two open questions

- Finding 1 (High): Add missing publisher.rs test call site at line ~695
  for get_or_generate_synthetic_id — was omitted from Task 3 Step 6
- Finding 2 (Medium): Remove crate::geo::GeoInfo import from endpoints.rs
  rather than replacing it — type is not used by name after the change,
  keeping any import fails clippy -D warnings
- Finding 3 (Low): Replace interactive git add -p in Task 6 with explicit
  file staging instruction
- Open Q1: Add Task 2 step to update stale handle_publisher_request
  signature in auction/README.md
- Open Q2: Add Task 2 step to update from_request doc comment to reflect
  ClientInfo-based TLS detection instead of Fastly SDK calls

* Broaden two low-severity doc cleanup steps in PR7 plan

- Step 7: cover all four stale Fastly-SDK-specific locations in
  http_util.rs (SPOOFABLE_FORWARDED_HEADERS doc, RequestInfo struct doc,
  from_request doc, detect_request_scheme doc)
- Step 8: replace the whole routing snippet in auction/README.md, not
  just the one handle_publisher_request line — handle_auction and
  integration_registry.handle_proxy are also stale in that snippet

* Fix two remaining low findings in PR7 plan

- Add missing Location 2 (RequestInfo.scheme field doc, line ~67) to
  Step 7; renumber subsequent locations 3-5
- Replace &runtime_services with runtime_services in Step 5 and README
  snippet — runtime_services is already &RuntimeServices in route_request

* Fix count drift in Step 7: four → five locations

* Add client_info field to AuctionContext and fix all construction sites

* Change RequestInfo::from_request to take &ClientInfo, thread services into handle_publisher_request

* Add Task 2 follow-up coverage and README route fixes

* Add services param to generate_synthetic_id, remove Fastly IP/geo calls in formats and endpoints

* Revert premature publisher geo change from Task 3

* Replace deprecated GeoInfo::from_request in publisher.rs with services.geo().lookup()

* Remove Fastly IP extraction from Didomi copy_headers, use ClientInfo instead

* Move IpAddr import to test module level in didomi.rs

* Apply rustfmt formatting to didomi.rs, publisher.rs, and synthetic.rs

Fix multi-line function call style in didomi.rs, line-break wrapping in
publisher.rs test, and import ordering in synthetic.rs test module.

* Add test coverage for generate_synthetic_id with concrete client IP

Adds noop_services_with_client_ip helper to test_support and a new
test that verifies the client_ip path through generate_synthetic_id
by asserting the HMAC differs when the IP changes.

* Align geo lookup warn log format with codebase convention ({e} not {e:?})

* Apply Prettier formatting to PR7 plan and spec docs

* Document content rewriting as platform-agnostic in platform module

* Document html_processor as platform-agnostic

* Document streaming_processor as platform-agnostic

* Fix unresolved doc link: replace EdgeRequest with edgezero_core::http::Request

* Add plan for content rewriting

* Add plan for PR9: wire signing to store primitives

* Add build_services_with_config_and_secret to test_support

* Add FastlyManagementApiClient to adapter

* Implement FastlyPlatformConfigStore and FastlyPlatformSecretStore write methods via management API

Replace FastlyApiClient with FastlyManagementApiClient in the put/delete
methods of FastlyPlatformConfigStore and the create/delete methods of
FastlyPlatformSecretStore. Remove the now-unused FastlyApiClient import.

* Add services to AuctionContext; remove deprecated from_config shim

Thread RuntimeServices into AuctionContext so auction providers can
access platform stores directly. Update PrebidAuctionProvider to use
RequestSigner::from_services(context.services) instead of the now-
removed from_config() shim. All construction sites and test helpers
updated accordingly.

This satisfies the final acceptance criterion of #490: no
FastlyConfigStore/FastlySecretStore construction remains in the
request_signing/ modules.

* Fix rotate/delete atomicity, HTTP verb, idempotent deletes, and weak tests

- Revert proxy.rs merge artifact: restore per-request allowed_domains
  at both redirect_is_permitted call sites; remove dead_code allow and
  stale comment — integration proxies defaulting to &[] get open mode
  again as documented
- Drop unused trusted-server-js dep from adapter Cargo.toml
- Fix check_response: gate body read behind error branch so 2xx paths
  do not buffer and discard the response body
- Remove self-referential SECRET_UPSERT_METHOD test
- Reorder write-cost doc so outbound HTTPS round-trip leads; handle-open
  caching noted as negligible
- Refactor make_request to take fastly::http::Method; drop string match
  and unreachable arm; remove SECRET_UPSERT_METHOD const
- Add SigningStoreIds named struct in endpoints.rs; update both call
  sites to destructure by name

* Move logging initialization into Fastly adapter (PR 10) (#610)

Move logging initialization into Fastly adapter (PR 10) (#610)

- Reverted gratuitous _message rename and record.args() usage in logging.rs, returning to the idiomatic message parameter inside the fern format closure.
- Refactored target_label to use .rsplit_once("::") rather than .split("::").last(). This provides a more explicit and robust way to extract the final module segment.
- Expanded target_label test coverage to explicitly test edge cases such as inputs without :: separators, empty strings, and inputs with trailing ::.
ChristianPavilonis pushed a commit that referenced this pull request May 5, 2026
… and Move logging initialization into Fastly adapter (#610)

* Rename crates to trusted-server-core and trusted-server-adapter-fastly

Rename crates/common → crates/trusted-server-core and crates/fastly →
crates/trusted-server-adapter-fastly following the EdgeZero naming
convention. Add EdgeZero workspace dependencies pinned to rev 170b74b.
Update all references across docs, CI workflows, scripts, agent files,
and configuration.

* Add platform abstraction layer with traits and RuntimeServices

Introduces trusted-server-core::platform with PlatformConfigStore,
PlatformSecretStore, PlatformKvStore, PlatformBackend, PlatformHttpClient,
and PlatformGeo traits alongside ClientInfo, PlatformError, and
RuntimeServices. Wires the Fastly adapter implementations and threads
RuntimeServices into route_request. Moves GeoInfo to platform/types as
platform-neutral data and adds geo_from_fastly for field mapping.

* Address platform layer review feedback

- Defer KV store opening: replace early error return with a local
  UnavailableKvStore fallback so routes that do not need synthetic ID
  access succeed when the KV store is missing or temporarily unavailable
- Use ConfigStore::try_open + try_get and SecretStore::try_get throughout
  FastlyPlatformConfigStore and FastlyPlatformSecretStore to honour the
  Result contract instead of panicking on open/lookup failure
- Encapsulate RuntimeServices service fields as pub(crate) with public
  getter methods (config_store, secret_store, backend, http_client, geo)
  and a pub new() constructor; adapter updated to use new()
- Reference #487 in FastlyPlatformHttpClient stub (PR 6 implements it)
- Remove unused KvPage re-export from platform/mod.rs
- Use super::KvHandle shorthand in RuntimeServices::kv_handle()

* Reject host strings containing control characters in BackendConfig

* Fix clippy error

* Validate scheme and host for control characters in BackendConfig

* Address review findings on platform abstraction layer

* Address review findings on platform abstraction layer

* Add config store read path and storage module split

- 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)

* Harden legacy config-store reads and align Fastly adapter stubs

* Address storage review feedback

* Resolved github-advanced-security bot problems

* Address PR review feedback on platform abstraction layer

- Make StoreName and StoreId inner fields private; From/AsRef provide all
  needed construction and access
- Add #[deprecated] to GeoInfo::from_request with #[allow(deprecated)] at
  the three legacy call sites to track migration progress
- Enumerate the six platform traits in the platform module doc comment
- Extract backend_config_from_spec helper to remove duplicate BackendConfig
  construction in predict_name and ensure
- Replace .into_iter().collect() with .to_vec() on secret plaintext bytes
- Remove unused bytes dependency from trusted-server-adapter-fastly
- Add comment on SecretStore::open clarifying it already returns Result
  (unlike ConfigStore::open which panics)

* Add PR 4 design spec for secret store trait (read-only)

* Clarify test scope and deferred branches in PR 4 spec

* Add implementation plan for PR 4 secret store trait

* Add test for get_secret_bytes open-failure path

* Add NotImplemented tests for FastlyPlatformSecretStore write stubs

* Inline StoreId binding and add section comment in write-stub tests

* Remove plan

* Add PR 6 design spec for backend and HTTP client traits

* Address spec review findings on PR 6 design

* Implement PlatformHttpClient and thread RuntimeServices through proxy layer

- Add PlatformHttpClient trait with send(), send_async(), and select() methods
- Add PlatformBackend trait with predict_name() and ensure() methods
- Add PlatformResponse wrapper around EdgeZero HTTP responses
- Add PlatformPendingRequest and PlatformSelectResult for auction fan-out
- Thread RuntimeServices through IntegrationProxy::handle(), IntegrationRegistry::handle_proxy(),
  and all first-party proxy endpoints so handlers can reach the HTTP client
- Add StubHttpClient and StubBackend test stubs with build_services_with_http_client helper
- Add proxy_request_calls_platform_http_client_send integration test
- Fix proxy_with_redirects to stay within 7-arg clippy limit via ProxyRequestHeaders struct
- Document Body::Stream limitation in edge_request_to_fastly with warning log
- Document intentional duplication of platform_response_to_fastly across proxy and orchestrator
- Remove spec file (promoted to plan + implementation)

* Address pr review findings

* Resolve pr review findings

* Add PR7 design spec for geo lookup + client info extract-once

Documents the call site migration plan: five Fastly SDK extraction
points in trusted-server-core replaced by RuntimeServices::client_info
reads, following Phase 1 injection pattern from the EdgeZero migration design.

* Fix spec review issues in PR7 design doc

- Correct erroneous claim about generate_synthetic_id being called twice
  via DeviceInfo; it is called once (line 91 for fresh_id), DeviceInfo.ip
  is a separate req.get_client_ip_addr() call fixed independently
- Add before/after snippet for handle_publisher_request call site in main.rs
- Add noop_services import instruction for http_util.rs test module
- Clarify _services rename (drop underscore, not add new param) in didomi.rs
- Clarify nextjs #[allow(deprecated)] annotations are out of scope (different function)

* Update PR7 spec to address all five agent review findings

- Change RequestInfo::from_request signature to &ClientInfo (not
  &RuntimeServices) so prebid can call it with context.client_info
- Scope SDK-call acceptance criteria to active non-deprecated code only
- List all six AuctionContext construction sites including two production
  sites in orchestrator.rs and three test helpers in orchestrator/prebid
- Add explicit warn-and-continue pattern for publisher.rs geo lookup
- Correct testing table: formats.rs and endpoints.rs have no test modules;
  add orchestrator.rs and prebid.rs test helper update rows

* Add PR7 implementation plan and address plan review findings

Plan covers 6 tasks in compilation-safe order: AuctionContext struct change
first, then from_request signature, then synthetic.rs cascade, then publisher
geo, then didomi. Includes two new copy_headers unit tests (Some/None).

Spec fixes: clarify injection pattern exceptions for &ClientInfo and
Option<IpAddr>; reword acceptance criterion to reflect that provider-layer
reads flow through AuctionContext.client_info.

* Fix three plan review findings and two open questions

- Finding 1 (High): Add missing publisher.rs test call site at line ~695
  for get_or_generate_synthetic_id — was omitted from Task 3 Step 6
- Finding 2 (Medium): Remove crate::geo::GeoInfo import from endpoints.rs
  rather than replacing it — type is not used by name after the change,
  keeping any import fails clippy -D warnings
- Finding 3 (Low): Replace interactive git add -p in Task 6 with explicit
  file staging instruction
- Open Q1: Add Task 2 step to update stale handle_publisher_request
  signature in auction/README.md
- Open Q2: Add Task 2 step to update from_request doc comment to reflect
  ClientInfo-based TLS detection instead of Fastly SDK calls

* Broaden two low-severity doc cleanup steps in PR7 plan

- Step 7: cover all four stale Fastly-SDK-specific locations in
  http_util.rs (SPOOFABLE_FORWARDED_HEADERS doc, RequestInfo struct doc,
  from_request doc, detect_request_scheme doc)
- Step 8: replace the whole routing snippet in auction/README.md, not
  just the one handle_publisher_request line — handle_auction and
  integration_registry.handle_proxy are also stale in that snippet

* Fix two remaining low findings in PR7 plan

- Add missing Location 2 (RequestInfo.scheme field doc, line ~67) to
  Step 7; renumber subsequent locations 3-5
- Replace &runtime_services with runtime_services in Step 5 and README
  snippet — runtime_services is already &RuntimeServices in route_request

* Fix count drift in Step 7: four → five locations

* Add client_info field to AuctionContext and fix all construction sites

* Change RequestInfo::from_request to take &ClientInfo, thread services into handle_publisher_request

* Add Task 2 follow-up coverage and README route fixes

* Add services param to generate_synthetic_id, remove Fastly IP/geo calls in formats and endpoints

* Revert premature publisher geo change from Task 3

* Replace deprecated GeoInfo::from_request in publisher.rs with services.geo().lookup()

* Remove Fastly IP extraction from Didomi copy_headers, use ClientInfo instead

* Move IpAddr import to test module level in didomi.rs

* Apply rustfmt formatting to didomi.rs, publisher.rs, and synthetic.rs

Fix multi-line function call style in didomi.rs, line-break wrapping in
publisher.rs test, and import ordering in synthetic.rs test module.

* Add test coverage for generate_synthetic_id with concrete client IP

Adds noop_services_with_client_ip helper to test_support and a new
test that verifies the client_ip path through generate_synthetic_id
by asserting the HMAC differs when the IP changes.

* Align geo lookup warn log format with codebase convention ({e} not {e:?})

* Apply Prettier formatting to PR7 plan and spec docs

* Document content rewriting as platform-agnostic in platform module

* Document html_processor as platform-agnostic

* Document streaming_processor as platform-agnostic

* Fix unresolved doc link: replace EdgeRequest with edgezero_core::http::Request

* Add plan for content rewriting

* Add plan for PR9: wire signing to store primitives

* Add build_services_with_config_and_secret to test_support

* Add FastlyManagementApiClient to adapter

* Implement FastlyPlatformConfigStore and FastlyPlatformSecretStore write methods via management API

Replace FastlyApiClient with FastlyManagementApiClient in the put/delete
methods of FastlyPlatformConfigStore and the create/delete methods of
FastlyPlatformSecretStore. Remove the now-unused FastlyApiClient import.

* Add services to AuctionContext; remove deprecated from_config shim

Thread RuntimeServices into AuctionContext so auction providers can
access platform stores directly. Update PrebidAuctionProvider to use
RequestSigner::from_services(context.services) instead of the now-
removed from_config() shim. All construction sites and test helpers
updated accordingly.

This satisfies the final acceptance criterion of #490: no
FastlyConfigStore/FastlySecretStore construction remains in the
request_signing/ modules.

* Fix rotate/delete atomicity, HTTP verb, idempotent deletes, and weak tests

- Revert proxy.rs merge artifact: restore per-request allowed_domains
  at both redirect_is_permitted call sites; remove dead_code allow and
  stale comment — integration proxies defaulting to &[] get open mode
  again as documented
- Drop unused trusted-server-js dep from adapter Cargo.toml
- Fix check_response: gate body read behind error branch so 2xx paths
  do not buffer and discard the response body
- Remove self-referential SECRET_UPSERT_METHOD test
- Reorder write-cost doc so outbound HTTPS round-trip leads; handle-open
  caching noted as negligible
- Refactor make_request to take fastly::http::Method; drop string match
  and unreachable arm; remove SECRET_UPSERT_METHOD const
- Add SigningStoreIds named struct in endpoints.rs; update both call
  sites to destructure by name

* Move logging initialization into Fastly adapter (PR 10) (#610)

Move logging initialization into Fastly adapter (PR 10) (#610)

- Reverted gratuitous _message rename and record.args() usage in logging.rs, returning to the idiomatic message parameter inside the fern format closure.
- Refactored target_label to use .rsplit_once("::") rather than .split("::").last(). This provides a more explicit and robust way to extract the final module segment.
- Expanded target_label test coverage to explicitly test edge cases such as inputs without :: separators, empty strings, and inputs with trailing ::.
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.

Wire signing to store write primitives

4 participants