Skip to content

Commit 011bfea

Browse files
Add partner registry and admin registration endpoint
Implement Story 4 (#537): partner KV store with API key hashing, POST /admin/partners/register with basic-auth protection, strict field validation (ID format, URL allowlists, domain normalization), and pull-sync config validation. Includes index-based API key lookup and comprehensive unit tests.
1 parent a44ead1 commit 011bfea

8 files changed

Lines changed: 1150 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ regex = "1.12.3"
8282
serde = { version = "1.0", features = ["derive"] }
8383
serde_json = "1.0.149"
8484
sha2 = "0.10.9"
85+
subtle = "2.6"
8586
temp-env = "0.3.6"
8687
tokio = { version = "1.49", features = ["sync", "macros", "io-util", "rt", "time"] }
8788
tokio-test = "0.4"

crates/trusted-server-adapter-fastly/src/main.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use trusted_server_core::constants::{
1010
ENV_FASTLY_IS_STAGING, ENV_FASTLY_SERVICE_VERSION, HEADER_X_GEO_INFO_AVAILABLE,
1111
HEADER_X_TS_ENV, HEADER_X_TS_VERSION,
1212
};
13+
use trusted_server_core::ec::admin::handle_register_partner;
14+
use trusted_server_core::ec::partner::PartnerStore;
1315
use trusted_server_core::error::TrustedServerError;
1416
use trusted_server_core::geo::GeoInfo;
1517
use trusted_server_core::http_util::sanitize_forwarded_headers;
@@ -105,10 +107,13 @@ async fn route_request(
105107
// Signature verification endpoint
106108
(Method::POST, "/verify-signature") => handle_verify_signature(settings, req),
107109

108-
// Key rotation admin endpoints
110+
// Admin endpoints
109111
// Keep in sync with Settings::ADMIN_ENDPOINTS in crates/trusted-server-core/src/settings.rs
110112
(Method::POST, "/admin/keys/rotate") => handle_rotate_key(settings, req),
111113
(Method::POST, "/admin/keys/deactivate") => handle_deactivate_key(settings, req),
114+
(Method::POST, "/admin/partners/register") => {
115+
require_partner_store(settings).and_then(|store| handle_register_partner(&store, req))
116+
}
112117

113118
// Unified auction endpoint (returns creative HTML inline)
114119
(Method::POST, "/auction") => handle_auction(settings, orchestrator, req).await,
@@ -209,3 +214,15 @@ fn init_logger() {
209214
.apply()
210215
.expect("should initialize logger");
211216
}
217+
218+
/// Constructs a `PartnerStore` from settings, or returns 503 if the
219+
/// `partner_store` config is not set.
220+
fn require_partner_store(settings: &Settings) -> Result<PartnerStore, Report<TrustedServerError>> {
221+
let store_name = settings.ec.partner_store.as_deref().ok_or_else(|| {
222+
Report::new(TrustedServerError::KvStore {
223+
store_name: "ec.partner_store".to_owned(),
224+
message: "ec.partner_store is not configured".to_owned(),
225+
})
226+
})?;
227+
Ok(PartnerStore::new(store_name))
228+
}

crates/trusted-server-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ regex = { workspace = true }
4040
serde = { workspace = true }
4141
serde_json = { workspace = true }
4242
sha2 = { workspace = true }
43+
subtle = { workspace = true }
4344
tokio = { workspace = true }
4445
toml = { workspace = true }
4546
trusted-server-js = { path = "../js" }

0 commit comments

Comments
 (0)