//! Token-free bounded HTTP boundary. //! //! Local loopback API use may retain the operator runtime. Any non-loopback or //! explicitly hosted deployment is fail-closed unless it uses the PUB-1 //! request-ephemeral mode. Public mode exposes only `/`, `/health`, and //! `POST /chat`; every chat runs in a fresh child process and temporary data //! directory that is destroyed after one response. use anyhow::{anyhow, Context, Result}; use serde::Deserialize; use serde_json::{json, Value}; use star::Runtime; use std::collections::{hash_map::DefaultHasher, HashMap}; use std::fs; use std::hash::{Hash, Hasher}; use std::io::{Read, Write}; use std::net::IpAddr; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tracing::{info, warn}; pub const MAX_REQUEST_BODY_BYTES: usize = 256 * 1024; const DEFAULT_RATE_LIMIT_PER_MINUTE: u32 = 120; const RATE_WINDOW_SECONDS: u64 = 60; const MAX_TRACKED_CLIENTS: usize = 4_096; const PUBLIC_HISTORY_LIMIT: usize = 24; const PUBLIC_HISTORY_ITEM_BYTES: usize = 8 * 1024; const PUBLIC_MESSAGE_BYTES: usize = 16 * 1024; const PUBLIC_WORKER_TIMEOUT_SECONDS: u64 = 90; const PUBLIC_WORKER_OUTPUT_BYTES: u64 = 1024 * 1024; static PUBLIC_REQUEST_COUNTER: AtomicU64 = AtomicU64::new(1); #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum BoundaryMode { LocalShared, PublicRequestEphemeral, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum ProxyPolicy { DirectPeer, ForwardedForLast, } #[derive(Debug, Clone)] struct SecurityConfig { rate_limit_per_minute: u32, mode: BoundaryMode, proxy_policy: ProxyPolicy, rate_probe_enabled: bool, } impl SecurityConfig { fn from_env(host: &str) -> Result { let rate_limit_per_minute = std::env::var("STARFIRE_RATE_LIMIT_PER_MINUTE") .ok() .and_then(|value| value.parse::().ok()) .filter(|value| (1..=10_000).contains(value)) .unwrap_or(DEFAULT_RATE_LIMIT_PER_MINUTE); let requested_mode = std::env::var("STARFIRE_PUBLIC_RUNTIME_MODE").unwrap_or_default(); let hosted = env_truthy("STARFIRE_HOSTED_MODE"); let loopback = host_is_loopback(host); let mode = if requested_mode == "request_ephemeral" { BoundaryMode::PublicRequestEphemeral } else if !requested_mode.is_empty() { return Err(anyhow!( "unsupported STARFIRE_PUBLIC_RUNTIME_MODE: {}", requested_mode )); } else if hosted { // STARFIRE_HOSTED_MODE is the established deployment declaration. // Hosted mode must fail safe into request-ephemeral public isolation, // never into the legacy shared local runtime. BoundaryMode::PublicRequestEphemeral } else if !loopback { return Err(anyhow!( "non-loopback binding requires STARFIRE_PUBLIC_RUNTIME_MODE=request_ephemeral" )); } else { BoundaryMode::LocalShared }; let proxy_policy = match mode { BoundaryMode::LocalShared => ProxyPolicy::DirectPeer, BoundaryMode::PublicRequestEphemeral => { match std::env::var("STARFIRE_TRUSTED_PROXY_HEADERS").as_deref() { Ok("render") => ProxyPolicy::ForwardedForLast, _ if hosted => ProxyPolicy::ForwardedForLast, _ => { return Err(anyhow!( "non-hosted public mode requires STARFIRE_TRUSTED_PROXY_HEADERS=render" )) } } } }; Self::from_values( rate_limit_per_minute, mode, proxy_policy, hosted || env_truthy("STARFIRE_RATE_LIMIT_PROBE"), ) } fn from_values( rate_limit_per_minute: u32, mode: BoundaryMode, proxy_policy: ProxyPolicy, rate_probe_enabled: bool, ) -> Result { if rate_limit_per_minute == 0 { return Err(anyhow!("request rate limit must be greater than zero")); } Ok(Self { rate_limit_per_minute, mode, proxy_policy, rate_probe_enabled, }) } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum RoutePolicy { Health, Preflight, PublicRoot, PublicChat, ForwardLocal, NotFound, } fn route_policy(mode: BoundaryMode, method: &str, path: &str) -> RoutePolicy { if method == "OPTIONS" { return RoutePolicy::Preflight; } if method == "GET" && path == "/health" { return RoutePolicy::Health; } match mode { BoundaryMode::PublicRequestEphemeral => match (method, path) { ("GET", "/") => RoutePolicy::PublicRoot, ("POST", "/chat") => RoutePolicy::PublicChat, _ => RoutePolicy::NotFound, }, BoundaryMode::LocalShared => RoutePolicy::ForwardLocal, } } #[derive(Debug, Clone, PartialEq, Eq)] enum BoundaryError { PayloadTooLarge, RateLimited { retry_after: u64 }, BadRequest, WorkerTimeout, Internal, } impl BoundaryError { fn response(self) -> ApiResponse { match self { Self::PayloadTooLarge => ApiResponse::error( 413, "payload_too_large", "Request body exceeds the 262144-byte limit", ), Self::RateLimited { retry_after } => { ApiResponse::error(429, "rate_limited", "Too many requests") .with_header("Retry-After", retry_after.to_string()) } Self::BadRequest => { ApiResponse::error(400, "bad_request", "Malformed or incomplete JSON request") } Self::WorkerTimeout => { ApiResponse::error(503, "worker_timeout", "Temporary public session timed out") } Self::Internal => ApiResponse::error(500, "internal_error", "Internal server error"), } } } #[derive(Debug, Clone)] struct ApiResponse { status: u16, body: String, content_type: &'static str, headers: Vec<(&'static str, String)>, } impl ApiResponse { fn new(status: u16, body: String) -> Self { Self { status, body, content_type: "application/json; charset=utf-8", headers: Vec::new(), } } fn html(status: u16, body: String) -> Self { Self { status, body, content_type: "text/html; charset=utf-8", headers: Vec::new(), } } fn error(status: u16, code: &str, message: &str) -> Self { Self::new( status, json!({ "error": message, "code": code, }) .to_string(), ) } fn with_header(mut self, name: &'static str, value: impl Into) -> Self { self.headers.push((name, value.into())); self } } #[derive(Debug, Clone, Copy)] struct ClientWindow { started_at: u64, count: u32, } #[derive(Debug)] struct RateLimiter { limit: u32, window_seconds: u64, clients: HashMap, } impl RateLimiter { fn new(limit: u32) -> Self { Self { limit, window_seconds: RATE_WINDOW_SECONDS, clients: HashMap::new(), } } fn check(&mut self, client: &str) -> std::result::Result<(), BoundaryError> { self.check_at(client, unix_seconds()) } fn check_at(&mut self, client: &str, now: u64) -> std::result::Result<(), BoundaryError> { self.clients.retain(|_, window| { now.saturating_sub(window.started_at) < self.window_seconds.saturating_mul(2) }); if !self.clients.contains_key(client) && self.clients.len() >= MAX_TRACKED_CLIENTS { let oldest = self .clients .iter() .min_by(|(left_key, left), (right_key, right)| { left.started_at .cmp(&right.started_at) .then_with(|| left_key.cmp(right_key)) }) .map(|(key, _)| key.clone()); if let Some(oldest) = oldest { self.clients.remove(&oldest); } } let window = self .clients .entry(client.to_owned()) .or_insert(ClientWindow { started_at: now, count: 0, }); let elapsed = now.saturating_sub(window.started_at); if elapsed >= self.window_seconds { *window = ClientWindow { started_at: now, count: 0, }; } if window.count >= self.limit { let retry_after = self .window_seconds .saturating_sub(now.saturating_sub(window.started_at)) .max(1); return Err(BoundaryError::RateLimited { retry_after }); } window.count = window.count.saturating_add(1); Ok(()) } } #[derive(Debug, Clone)] struct ClientIdentity { key: String, source: &'static str, } #[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] struct PublicChatRequest { message: String, #[serde(default)] history: Vec, } #[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] struct PublicHistoryItem { role: String, content: String, } pub fn start(host: &str, port: u16, data_dir: &Path) -> Result<()> { let config = SecurityConfig::from_env(host)?; let backend_port = match config.mode { BoundaryMode::LocalShared => { let runtime = Runtime::new(data_dir)?; let runtime = Arc::new(Mutex::new(runtime)); let port = backend_port(port); let backend_data_dir = data_dir.to_path_buf(); thread::Builder::new() .name("starfire-local-backend".to_owned()) .spawn(move || { if let Err(error) = start_backend(runtime, port, &backend_data_dir) { warn!("Starfire loopback backend exited: {}", error); } }) .context("spawn Starfire loopback backend")?; wait_for_backend(port)?; Some(port) } BoundaryMode::PublicRequestEphemeral => None, }; let address = format!("{}:{}", host, port); let server = tiny_http::Server::http(&address) .map_err(|error| anyhow!("Starfire public API server error: {}", error))?; let mut rate_limiter = RateLimiter::new(config.rate_limit_per_minute); let probe_salt = probe_salt(); info!( "Starfire API ready at http://{} ({:?}; operator persistence exposed: false in public mode)", address, config.mode ); for request in server.incoming_requests() { if let Err(error) = handle_request( request, backend_port, data_dir, &config, &mut rate_limiter, probe_salt, ) { warn!("Starfire request transport failure: {}", error); } } Ok(()) } #[cfg(feature = "starfire-live")] fn start_backend(runtime: Arc>, port: u16, data_dir: &Path) -> Result<()> { crate::live_api::start(runtime, "127.0.0.1", port, data_dir) } #[cfg(not(feature = "starfire-live"))] fn start_backend(runtime: Arc>, port: u16, _data_dir: &Path) -> Result<()> { star::api::start(runtime, "127.0.0.1", port) } fn backend_port(external_port: u16) -> u16 { if let Some(parsed) = std::env::var("STARFIRE_SECURE_BACKEND_PORT") .ok() .and_then(|value| value.parse::().ok()) .filter(|parsed| *parsed != external_port) { return parsed; } external_port.checked_add(2).unwrap_or(18_082) } fn wait_for_backend(port: u16) -> Result<()> { let url = format!("http://127.0.0.1:{}/health", port); for _ in 0..400 { if ureq::get(&url).call().is_ok() { return Ok(()); } thread::sleep(Duration::from_millis(50)); } Err(anyhow!( "Starfire loopback backend did not become ready at {}", url )) } fn handle_request( mut request: tiny_http::Request, backend_port: Option, _operator_data_dir: &Path, config: &SecurityConfig, rate_limiter: &mut RateLimiter, probe_salt: u64, ) -> Result<()> { let method = request.method().as_str().to_owned(); let path = request.url().to_owned(); let policy = route_policy(config.mode, &method, &path); if policy == RoutePolicy::Preflight { return respond(request, ApiResponse::new(204, String::new())); } if policy == RoutePolicy::Health { let response = match config.mode { BoundaryMode::PublicRequestEphemeral => public_health_response(), BoundaryMode::LocalShared => forward( "GET", "/health", &[], backend_port.ok_or_else(|| anyhow!("local backend port missing"))?, ), }; return respond(request, response); } let identity = client_identity(&request, config.proxy_policy); let probe_requested = config.rate_probe_enabled && request_header(&request, "X-Starfire-Rate-Probe") == Some("1"); if let Err(error) = rate_limiter.check(&identity.key) { let response = attach_probe_headers(error.response(), probe_requested, &identity, probe_salt); return respond(request, response); } if policy == RoutePolicy::NotFound { let response = attach_probe_headers( ApiResponse::new(404, json!({ "error": "Not found" }).to_string()), probe_requested, &identity, probe_salt, ); return respond(request, response); } if content_length(&request).is_some_and(|length| length > MAX_REQUEST_BODY_BYTES) { let response = attach_probe_headers( BoundaryError::PayloadTooLarge.response(), probe_requested, &identity, probe_salt, ); return respond(request, response); } let mut body = Vec::new(); request .as_reader() .take((MAX_REQUEST_BODY_BYTES + 1) as u64) .read_to_end(&mut body) .context("read bounded request body")?; if body.len() > MAX_REQUEST_BODY_BYTES { let response = attach_probe_headers( BoundaryError::PayloadTooLarge.response(), probe_requested, &identity, probe_salt, ); return respond(request, response); } if validate_json_request(config.mode, &method, &path, &body).is_err() { let response = attach_probe_headers( BoundaryError::BadRequest.response(), probe_requested, &identity, probe_salt, ); return respond(request, response); } let response = match policy { RoutePolicy::PublicRoot => public_root_response(), RoutePolicy::PublicChat => run_public_chat_worker(&body), RoutePolicy::ForwardLocal => forward( &method, &path, &body, backend_port.ok_or_else(|| anyhow!("local backend port missing"))?, ), RoutePolicy::Health | RoutePolicy::Preflight | RoutePolicy::NotFound => { BoundaryError::Internal.response() } }; let response = attach_probe_headers(response, probe_requested, &identity, probe_salt); respond(request, response) } fn public_health_response() -> ApiResponse { ApiResponse::new( 200, json!({ "status": "ok", "mode": "public_request_ephemeral", "state_scope": "single_request", "persistent": false, "operator_state_access": false, "sensitive_routes_exposed": false, "ei_collection_enabled": false, "live_learning_enabled": false }) .to_string(), ) } fn public_root_response() -> ApiResponse { ApiResponse::html(200, PUBLIC_CHAT_UI.to_owned()).with_header( "Content-Security-Policy", "default-src 'self'; connect-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'self'", ) } const PUBLIC_CHAT_UI: &str = r#" Starfire

Starfire

Public, request-ephemeral conversation. Nothing is saved between requests.

Hi — what would you like to explore?
Temporary browser history is kept only in this tab to provide conversational context.
"#; fn run_public_chat_worker(body: &[u8]) -> ApiResponse { let session = match EphemeralDirectory::create() { Ok(session) => session, Err(error) => { warn!("create public ephemeral directory: {}", error); return BoundaryError::Internal.response(); } }; let request_id = session.request_id().to_owned(); let executable = match std::env::current_exe() { Ok(executable) => executable, Err(error) => { warn!("resolve public worker executable: {}", error); return BoundaryError::Internal.response(); } }; let mut child = match Command::new(executable) .arg("--data-dir") .arg(session.path()) .arg("public-chat-once") .env("STARFIRE_HOSTED_MODE", "false") .env_remove("STARFIRE_PUBLIC_RUNTIME_MODE") .env_remove("STARFIRE_TRUSTED_PROXY_HEADERS") .env_remove("STARFIRE_RATE_LIMIT_PROBE") .env("STARFIRE_PUBLIC_REQUEST_ID", &request_id) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::null()) .spawn() { Ok(child) => child, Err(error) => { warn!("spawn public chat worker: {}", error); return BoundaryError::Internal.response(); } }; if let Some(mut stdin) = child.stdin.take() { if let Err(error) = stdin.write_all(body) { let _ = child.kill(); let _ = child.wait(); warn!("write public chat worker request: {}", error); return BoundaryError::Internal.response(); } } let deadline = Instant::now() + Duration::from_secs(PUBLIC_WORKER_TIMEOUT_SECONDS); let status = loop { match child.try_wait() { Ok(Some(status)) => break status, Ok(None) if Instant::now() < deadline => { thread::sleep(Duration::from_millis(20)); } Ok(None) => { let _ = child.kill(); let _ = child.wait(); return BoundaryError::WorkerTimeout.response(); } Err(error) => { let _ = child.kill(); let _ = child.wait(); warn!("wait for public chat worker: {}", error); return BoundaryError::Internal.response(); } } }; let mut output = Vec::new(); if let Some(stdout) = child.stdout.take() { let mut bounded = stdout.take(PUBLIC_WORKER_OUTPUT_BYTES + 1); if let Err(error) = bounded.read_to_end(&mut output) { warn!("read public chat worker response: {}", error); return BoundaryError::Internal.response(); } } if !status.success() || output.len() as u64 > PUBLIC_WORKER_OUTPUT_BYTES { warn!( "public chat worker failed: status={}, output_bytes={}", status, output.len() ); return BoundaryError::Internal.response(); } let value = match worker_json_value(&output) { Some(value) => value, None => { warn!("public chat worker returned no valid JSON payload"); return BoundaryError::Internal.response(); } }; let valid = value.get("response").and_then(Value::as_str).is_some() && value .get("public_session") .and_then(|session| session.get("request_id")) .and_then(Value::as_str) == Some(request_id.as_str()) && value .pointer("/public_session/persistence") .and_then(Value::as_bool) == Some(false) && value .pointer("/public_session/operator_state_access") .and_then(Value::as_bool) == Some(false); if !valid { warn!("public chat worker returned an invalid authority envelope"); return BoundaryError::Internal.response(); } ApiResponse::new(200, value.to_string()) } fn worker_json_value(output: &[u8]) -> Option { output .split(|byte| *byte == b'\n') .rev() .find_map(|line| serde_json::from_slice::(line).ok()) } struct EphemeralDirectory { path: PathBuf, request_id: String, } impl EphemeralDirectory { fn create() -> Result { let counter = PUBLIC_REQUEST_COUNTER.fetch_add(1, Ordering::Relaxed); let request_id = format!("public-{}-{}-{}", std::process::id(), unix_nanos(), counter); let root = std::env::temp_dir().join("starfire-public-requests"); fs::create_dir_all(&root) .with_context(|| format!("create public request root {}", root.display()))?; let path = root.join(&request_id); fs::create_dir(&path) .with_context(|| format!("create public request directory {}", path.display()))?; Ok(Self { path, request_id }) } fn path(&self) -> &Path { &self.path } fn request_id(&self) -> &str { &self.request_id } } impl Drop for EphemeralDirectory { fn drop(&mut self) { if let Err(error) = fs::remove_dir_all(&self.path) { warn!( "remove public request directory {}: {}", self.path.display(), error ); } } } fn forward(method: &str, path: &str, body: &[u8], port: u16) -> ApiResponse { let url = format!("http://127.0.0.1:{}{}", port, path); let forwarded = ureq::request(method, &url).set("Content-Type", "application/json"); let result = if body.is_empty() { forwarded.call() } else { forwarded.send_bytes(body) }; match result { Ok(response) => { let status = response.status(); match response.into_string() { Ok(body) => map_backend_response(status, body), Err(_) => BoundaryError::Internal.response(), } } Err(ureq::Error::Status(status, response)) => { let body = response .into_string() .unwrap_or_else(|_| json!({ "error": "Backend request failed" }).to_string()); map_backend_response(status, body) } Err(ureq::Error::Transport(_)) => BoundaryError::Internal.response(), } } fn map_backend_response(status: u16, body: String) -> ApiResponse { if status == 404 { return ApiResponse::new(404, json!({ "error": "Not found" }).to_string()); } if status >= 500 { return BoundaryError::Internal.response(); } if status >= 400 { return ApiResponse::new(status, body); } let backend_error = serde_json::from_str::(&body).ok().and_then(|value| { value .get("error") .and_then(Value::as_str) .map(str::to_owned) }); match backend_error.as_deref() { Some(error) if error.starts_with("Invalid request:") => { BoundaryError::BadRequest.response() } Some(error) if error.starts_with("Lock poisoned:") || error.starts_with("Chat error:") || error.starts_with("Serialization:") => { BoundaryError::Internal.response() } _ => ApiResponse::new(status, body), } } fn validate_json_request( mode: BoundaryMode, method: &str, path: &str, body: &[u8], ) -> std::result::Result<(), BoundaryError> { if method != "POST" { return Ok(()); } if mode == BoundaryMode::PublicRequestEphemeral && path == "/chat" { let request: PublicChatRequest = serde_json::from_slice(body).map_err(|_| BoundaryError::BadRequest)?; if request.message.trim().is_empty() || request.message.len() > PUBLIC_MESSAGE_BYTES { return Err(BoundaryError::BadRequest); } if request.history.len() > PUBLIC_HISTORY_LIMIT { return Err(BoundaryError::BadRequest); } for item in request.history { if !matches!(item.role.as_str(), "user" | "assistant") || item.content.trim().is_empty() || item.content.len() > PUBLIC_HISTORY_ITEM_BYTES { return Err(BoundaryError::BadRequest); } } return Ok(()); } let required_field = match path { "/chat" => Some("message"), "/reason" => Some("query"), "/remember" => Some("topic"), _ => return Ok(()), }; let value: Value = serde_json::from_slice(body).map_err(|_| BoundaryError::BadRequest)?; let object = value.as_object().ok_or(BoundaryError::BadRequest)?; if let Some(field) = required_field { let valid = object .get(field) .and_then(Value::as_str) .is_some_and(|text| !text.trim().is_empty()); if !valid { return Err(BoundaryError::BadRequest); } } if path == "/reason" { if let Some(memories) = object.get("memories") { let valid = memories .as_array() .is_some_and(|items| items.iter().all(Value::is_string)); if !valid { return Err(BoundaryError::BadRequest); } } } if path == "/remember" { if let Some(limit) = object.get("limit") { if !limit.is_null() && limit.as_u64().is_none() { return Err(BoundaryError::BadRequest); } } } Ok(()) } fn client_identity(request: &tiny_http::Request, policy: ProxyPolicy) -> ClientIdentity { if policy == ProxyPolicy::ForwardedForLast { if let Some(ip) = request_header(request, "X-Forwarded-For").and_then(forwarded_for_last) { return ClientIdentity { key: ip, source: "x-forwarded-for-last", }; } } ClientIdentity { key: request .remote_addr() .map(|address| address.ip().to_string()) .unwrap_or_else(|| "unknown-client".to_owned()), source: if policy == ProxyPolicy::ForwardedForLast { "proxy-peer-fallback" } else { "direct-peer" }, } } fn forwarded_for_last(value: &str) -> Option { value .split(',') .rev() .map(str::trim) .find_map(|candidate| candidate.parse::().ok()) .map(|ip| ip.to_string()) } fn attach_probe_headers( response: ApiResponse, requested: bool, identity: &ClientIdentity, salt: u64, ) -> ApiResponse { if !requested { return response; } response .with_header("X-Starfire-Rate-Key-Source", identity.source) .with_header( "X-Starfire-Rate-Bucket", format!("{:016x}", bucket_fingerprint(&identity.key, salt)), ) } fn bucket_fingerprint(key: &str, salt: u64) -> u64 { let mut hasher = DefaultHasher::new(); salt.hash(&mut hasher); key.hash(&mut hasher); hasher.finish() } fn request_header<'a>(request: &'a tiny_http::Request, name: &'static str) -> Option<&'a str> { request .headers() .iter() .find(|header| header.field.equiv(name)) .map(|header| header.value.as_str()) } fn content_length(request: &tiny_http::Request) -> Option { request_header(request, "Content-Length")? .parse::() .ok() } fn respond(request: tiny_http::Request, api: ApiResponse) -> Result<()> { let mut response = tiny_http::Response::from_data(api.body.into_bytes()) .with_status_code(api.status) .with_header(header("Content-Type", api.content_type)) .with_header(header("Access-Control-Allow-Origin", "*")) .with_header(header("Access-Control-Allow-Methods", "GET,POST,OPTIONS")) .with_header(header("Access-Control-Allow-Headers", "Content-Type")) .with_header(header("Access-Control-Max-Age", "600")) .with_header(header("Cache-Control", "no-store")) .with_header(header("X-Content-Type-Options", "nosniff")); for (name, value) in api.headers { response.add_header(header(name, &value)); } request .respond(response) .map_err(|error| anyhow!("send Starfire response: {}", error)) } fn header(name: &str, value: &str) -> tiny_http::Header { tiny_http::Header::from_bytes(name.as_bytes(), value.as_bytes()) .expect("static HTTP header must be valid") } fn env_truthy(name: &str) -> bool { std::env::var(name) .ok() .is_some_and(|value| matches!(value.to_ascii_lowercase().as_str(), "1" | "true" | "yes")) } fn host_is_loopback(host: &str) -> bool { host == "localhost" || host .parse::() .ok() .is_some_and(|address| address.is_loopback()) } fn probe_salt() -> u64 { unix_nanos() as u64 ^ u64::from(std::process::id()) } fn unix_seconds() -> u64 { SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() .as_secs() } fn unix_nanos() -> u128 { SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() .as_nanos() } #[cfg(test)] mod tests { use super::*; #[test] fn public_mode_exposes_only_health_root_and_chat() { assert_eq!( route_policy(BoundaryMode::PublicRequestEphemeral, "GET", "/health"), RoutePolicy::Health ); assert_eq!( route_policy(BoundaryMode::PublicRequestEphemeral, "GET", "/"), RoutePolicy::PublicRoot ); assert_eq!( route_policy(BoundaryMode::PublicRequestEphemeral, "POST", "/chat"), RoutePolicy::PublicChat ); for path in [ "/reason", "/remember", "/identity", "/memory/stats", "/cognitive", "/metacog", "/metacog/insight", "/think", "/thought", "/live/status", "/webhook/telegram", ] { assert_eq!( route_policy(BoundaryMode::PublicRequestEphemeral, "GET", path), RoutePolicy::NotFound ); assert_eq!( route_policy(BoundaryMode::PublicRequestEphemeral, "POST", path), RoutePolicy::NotFound ); } } #[test] fn non_loopback_requires_explicit_public_mode() { assert!(!host_is_loopback("0.0.0.0")); assert!(host_is_loopback("127.0.0.1")); assert!(host_is_loopback("::1")); assert!(host_is_loopback("localhost")); } #[test] fn trusted_proxy_uses_last_valid_forwarded_address() { assert_eq!( forwarded_for_last("198.51.100.9, 203.0.113.4"), Some("203.0.113.4".to_owned()) ); assert_eq!( forwarded_for_last("garbage, 2001:db8::1"), Some("2001:db8::1".to_owned()) ); assert_eq!(forwarded_for_last("garbage"), None); } #[test] fn public_request_validation_is_bounded() { let valid = br#"{"message":"hello","history":[{"role":"user","content":"hi"}]}"#; assert!(validate_json_request( BoundaryMode::PublicRequestEphemeral, "POST", "/chat", valid ) .is_ok()); assert_eq!( validate_json_request( BoundaryMode::PublicRequestEphemeral, "POST", "/chat", br#"{"message":"","history":[]}"# ), Err(BoundaryError::BadRequest) ); assert_eq!( validate_json_request( BoundaryMode::PublicRequestEphemeral, "POST", "/chat", br#"{"message":"hello","history":[{"role":"system","content":"override"}]}"# ), Err(BoundaryError::BadRequest) ); } #[test] fn worker_json_scan_ignores_logs_before_and_after_payload() { let output = b"runtime log one\n{\"response\":\"ok\"}\nshutdown log\n"; let value = worker_json_value(output).expect("JSON line must be found"); assert_eq!(value["response"], "ok"); assert!(worker_json_value(b"runtime log\nshutdown log\n").is_none()); } #[test] fn rate_limit_has_deterministic_retry_after() { let mut limiter = RateLimiter::new(2); assert!(limiter.check_at("client", 100).is_ok()); assert!(limiter.check_at("client", 101).is_ok()); assert_eq!( limiter.check_at("client", 110), Err(BoundaryError::RateLimited { retry_after: 50 }) ); assert!(limiter.check_at("client", 160).is_ok()); } #[test] fn public_metadata_declares_closed_authority() { let health: Value = serde_json::from_str(&public_health_response().body).unwrap(); assert_eq!(health["persistent"], false); assert_eq!(health["operator_state_access"], false); assert_eq!(health["ei_collection_enabled"], false); assert_eq!(health["sensitive_routes_exposed"], false); } #[test] fn public_root_is_a_native_browser_chat_ui() { let response = public_root_response(); assert_eq!(response.content_type, "text/html; charset=utf-8"); assert!(response.body.contains("id=\"chat-form\"")); assert!(response.body.contains("fetch('/chat'")); assert!(response.body.contains("request-ephemeral")); assert!(!response.body.contains("