From 76375f2eaa30739d490a036c5e4095d17d1e8674 Mon Sep 17 00:00:00 2001 From: Henry Park Date: Tue, 10 Mar 2026 13:25:32 -0700 Subject: [PATCH] refactor: centralize test credential constants into testing::credentials (#829) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: centralize test credential constants into testing::credentials Scattered test credential strings (API keys, OAuth tokens, crypto keys, Telegram tokens, session tokens) across ~25 files made security auditing harder and created unnecessary duplication. Centralize all test-only fake credentials into a new `src/testing/credentials.rs` module with named constants and a shared `test_secrets_store()` helper. - Convert `src/testing.rs` to directory module (`src/testing/mod.rs`) - Add `src/testing/credentials.rs` with ~30 named constants - Replace hardcoded literals in 24 source files - Deduplicate `test_store()` helper (was copy-pasted in 3 files) - Leave leak_detector/shell/signature tests as-is (inline values aid readability for pattern detection tests) [skip-regression-check] Co-Authored-By: Claude Opus 4.6 (1M context) * refactor: replace real Telegram bot token with obviously fake test stub Co-Authored-By: Claude Sonnet 4.6 * Update src/testing/credentials.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/testing/credentials.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * refactor: address PR review feedback on test credentials - Fix TEST_CRYPTO_KEY doc comment ("32-byte hex" → "32-character key string") - Rename confusing "real"/"fake" Anthropic constant names and values - Change TEST_STRIPE_KEY from "sk-live" to "sk_test_fake123" to avoid scanners - Use test_secrets_store() helper in orchestrator and http tool tests - Clarify config_round_trip.rs doc comment about integration test visibility Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/channels/channel.rs | 5 +- src/channels/wasm/wrapper.rs | 13 ++- src/channels/web/auth.rs | 53 +++++----- src/channels/web/server.rs | 7 +- src/config/embeddings.rs | 3 +- src/config/llm.rs | 15 +-- src/config/sandbox.rs | 27 ++++-- src/extensions/manager.rs | 4 +- src/llm/session.rs | 17 ++-- src/orchestrator/api.rs | 7 +- src/secrets/crypto.rs | 4 +- src/secrets/store.rs | 29 +++--- src/testing/credentials.rs | 134 ++++++++++++++++++++++++++ src/{testing.rs => testing/mod.rs} | 2 + src/tools/builtin/extension_tools.rs | 4 +- src/tools/builtin/http.rs | 30 +----- src/tools/builtin/job.rs | 19 ++-- src/tools/builtin/secrets_tools.rs | 13 +-- src/tools/tool.rs | 5 +- src/tools/wasm/credential_injector.rs | 17 ++-- src/tools/wasm/loader.rs | 12 ++- src/tools/wasm/wrapper.rs | 78 ++++++--------- src/tunnel/mod.rs | 3 +- src/worker/api.rs | 5 +- tests/config_round_trip.rs | 9 +- 25 files changed, 314 insertions(+), 201 deletions(-) create mode 100644 src/testing/credentials.rs rename src/{testing.rs => testing/mod.rs} (99%) diff --git a/src/channels/channel.rs b/src/channels/channel.rs index 60cdfe7a..938b1f4f 100644 --- a/src/channels/channel.rs +++ b/src/channels/channel.rs @@ -365,6 +365,7 @@ pub trait ChannelSecretUpdater: Send + Sync { #[cfg(test)] mod tests { use super::*; + use crate::testing::credentials::TEST_REDACT_SECRET_123; /// Stub tool that marks `"value"` as sensitive. struct SecretTool; @@ -394,7 +395,7 @@ mod tests { #[test] fn tool_completed_redacts_sensitive_params_on_failure() { - let params = serde_json::json!({"name": "api_key", "value": "sk-secret-123"}); + let params = serde_json::json!({"name": "api_key", "value": TEST_REDACT_SECRET_123}); let err: Result = Err(crate::error::ToolError::ExecutionFailed { name: "secret_save".into(), @@ -429,7 +430,7 @@ mod tests { param_str ); assert!( - !param_str.contains("sk-secret-123"), + !param_str.contains(TEST_REDACT_SECRET_123), "raw secret should not appear: {}", param_str ); diff --git a/src/channels/wasm/wrapper.rs b/src/channels/wasm/wrapper.rs index 3b788e89..a9fa4dbf 100644 --- a/src/channels/wasm/wrapper.rs +++ b/src/channels/wasm/wrapper.rs @@ -3059,6 +3059,7 @@ mod tests { }; use crate::channels::wasm::wrapper::{HttpResponse, WasmChannel}; use crate::pairing::PairingStore; + use crate::testing::credentials::TEST_TELEGRAM_BOT_TOKEN; use crate::tools::wasm::ResourceLimits; fn create_test_channel() -> WasmChannel { @@ -4009,7 +4010,7 @@ mod tests { let mut creds = std::collections::HashMap::new(); creds.insert( "TELEGRAM_BOT_TOKEN".to_string(), - "8218490433:AAEZeUxwqZ5OO3mOCXv7fKvpdhDgsmBBNis".to_string(), + TEST_TELEGRAM_BOT_TOKEN.to_string(), ); creds.insert("OTHER_SECRET".to_string(), "s3cret".to_string()); @@ -4022,13 +4023,15 @@ mod tests { Arc::new(PairingStore::new()), ); - let error = "HTTP request failed: error sending request for url \ - (https://api.telegram.org/bot8218490433:AAEZeUxwqZ5OO3mOCXv7fKvpdhDgsmBBNis/getUpdates)"; + let error = format!( + "HTTP request failed: error sending request for url \ + (https://api.telegram.org/bot{TEST_TELEGRAM_BOT_TOKEN}/getUpdates)" + ); - let redacted = store.redact_credentials(error); + let redacted = store.redact_credentials(&error); assert!( - !redacted.contains("8218490433:AAEZeUxwqZ5OO3mOCXv7fKvpdhDgsmBBNis"), + !redacted.contains(TEST_TELEGRAM_BOT_TOKEN), "credential value should be redacted" ); assert!( diff --git a/src/channels/web/auth.rs b/src/channels/web/auth.rs index 9b1f5b47..b2fa4e4f 100644 --- a/src/channels/web/auth.rs +++ b/src/channels/web/auth.rs @@ -83,14 +83,15 @@ pub async fn auth_middleware( #[cfg(test)] mod tests { use super::*; + use crate::testing::credentials::{TEST_AUTH_SECRET_TOKEN, TEST_BEARER_TOKEN}; #[test] fn test_auth_state_clone() { let state = AuthState { - token: "test-token".to_string(), + token: TEST_BEARER_TOKEN.to_string(), }; let cloned = state.clone(); - assert_eq!(cloned.token, "test-token"); + assert_eq!(cloned.token, TEST_BEARER_TOKEN); } use axum::Router; @@ -120,10 +121,10 @@ mod tests { #[tokio::test] async fn test_valid_bearer_token_passes() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") - .header("Authorization", "Bearer secret-token") + .header("Authorization", format!("Bearer {TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -132,7 +133,7 @@ mod tests { #[tokio::test] async fn test_invalid_bearer_token_rejected() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") .header("Authorization", "Bearer wrong-token") @@ -144,9 +145,9 @@ mod tests { #[tokio::test] async fn test_query_token_allowed_for_chat_events() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() - .uri("/api/chat/events?token=secret-token") + .uri(format!("/api/chat/events?token={TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -155,9 +156,9 @@ mod tests { #[tokio::test] async fn test_query_token_allowed_for_logs_events() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() - .uri("/api/logs/events?token=secret-token") + .uri(format!("/api/logs/events?token={TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -166,9 +167,9 @@ mod tests { #[tokio::test] async fn test_query_token_allowed_for_ws_upgrade() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() - .uri("/api/chat/ws?token=secret-token") + .uri(format!("/api/chat/ws?token={TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -202,9 +203,9 @@ mod tests { #[tokio::test] async fn test_query_token_rejected_for_non_sse_get() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() - .uri("/api/chat/history?token=secret-token") + .uri(format!("/api/chat/history?token={TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -213,10 +214,10 @@ mod tests { #[tokio::test] async fn test_query_token_rejected_for_post() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .method(Method::POST) - .uri("/api/chat/send?token=secret-token") + .uri(format!("/api/chat/send?token={TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -225,7 +226,7 @@ mod tests { #[tokio::test] async fn test_query_token_invalid_rejected() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events?token=wrong-token") .body(Body::empty()) @@ -236,7 +237,7 @@ mod tests { #[tokio::test] async fn test_no_auth_at_all_rejected() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") .body(Body::empty()) @@ -247,11 +248,11 @@ mod tests { #[tokio::test] async fn test_bearer_header_works_for_post() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .method(Method::POST) .uri("/api/chat/send") - .header("Authorization", "Bearer secret-token") + .header("Authorization", format!("Bearer {TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -260,10 +261,10 @@ mod tests { #[tokio::test] async fn test_bearer_prefix_case_insensitive() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") - .header("Authorization", "bearer secret-token") + .header("Authorization", format!("bearer {TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -272,10 +273,10 @@ mod tests { #[tokio::test] async fn test_bearer_prefix_mixed_case() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") - .header("Authorization", "BEARER secret-token") + .header("Authorization", format!("BEARER {TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); @@ -284,7 +285,7 @@ mod tests { #[tokio::test] async fn test_empty_bearer_token_rejected() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") .header("Authorization", "Bearer ") @@ -296,10 +297,10 @@ mod tests { #[tokio::test] async fn test_token_with_whitespace_rejected() { - let app = test_app("secret-token"); + let app = test_app(TEST_AUTH_SECRET_TOKEN); let req = Request::builder() .uri("/api/chat/events") - .header("Authorization", "Bearer secret-token") + .header("Authorization", format!("Bearer {TEST_AUTH_SECRET_TOKEN}")) .body(Body::empty()) .unwrap(); let resp = app.oneshot(req).await.unwrap(); diff --git a/src/channels/web/server.rs b/src/channels/web/server.rs index e6f78461..fce6caa5 100644 --- a/src/channels/web/server.rs +++ b/src/channels/web/server.rs @@ -2379,6 +2379,7 @@ struct GatewayStatusResponse { #[cfg(test)] mod tests { use super::*; + use crate::testing::credentials::TEST_GATEWAY_CRYPTO_KEY; #[test] fn test_build_turns_from_db_messages_complete() { @@ -2552,7 +2553,7 @@ mod tests { // Build an ExtensionManager so the handler can look up flows let secrets = Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "test-key-at-least-32-chars-long!!".to_string(), + TEST_GATEWAY_CRYPTO_KEY.to_string(), )) .expect("crypto"), ))); @@ -2602,7 +2603,7 @@ mod tests { let secrets: Arc = Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "test-key-at-least-32-chars-long!!".to_string(), + TEST_GATEWAY_CRYPTO_KEY.to_string(), )) .expect("crypto"), ))); @@ -2708,7 +2709,7 @@ mod tests { let secrets: Arc = Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "test-key-at-least-32-chars-long!!".to_string(), + TEST_GATEWAY_CRYPTO_KEY.to_string(), )) .expect("crypto"), ))); diff --git a/src/config/embeddings.rs b/src/config/embeddings.rs index 80719778..c5a84c00 100644 --- a/src/config/embeddings.rs +++ b/src/config/embeddings.rs @@ -154,6 +154,7 @@ mod tests { use super::*; use crate::config::helpers::ENV_MUTEX; use crate::settings::{EmbeddingsSettings, Settings}; + use crate::testing::credentials::*; /// Clear all embedding-related env vars. fn clear_embedding_env() { @@ -173,7 +174,7 @@ mod tests { clear_embedding_env(); // SAFETY: Under ENV_MUTEX, no concurrent env access. unsafe { - std::env::set_var("OPENAI_API_KEY", "sk-test-key-for-issue-129"); + std::env::set_var("OPENAI_API_KEY", TEST_OPENAI_API_KEY_ISSUE_129); } let settings = Settings { diff --git a/src/config/llm.rs b/src/config/llm.rs index cc02cd31..dd2c9563 100644 --- a/src/config/llm.rs +++ b/src/config/llm.rs @@ -389,6 +389,7 @@ mod tests { use super::*; use crate::config::helpers::ENV_MUTEX; use crate::settings::Settings; + use crate::testing::credentials::*; /// Clear all openai-compatible-related env vars. fn clear_openai_compatible_env() { @@ -657,7 +658,7 @@ mod tests { // SAFETY: Under ENV_MUTEX. unsafe { std::env::set_var("LLM_BACKEND", "open_ai"); - std::env::set_var("OPENAI_API_KEY", "test-key"); + std::env::set_var("OPENAI_API_KEY", TEST_API_KEY); } let settings = Settings::default(); @@ -791,7 +792,7 @@ mod tests { clear_anthropic_env(); // SAFETY: Under ENV_MUTEX. unsafe { - std::env::set_var("ANTHROPIC_OAUTH_TOKEN", "sk-ant-oat01-test-token"); + std::env::set_var("ANTHROPIC_OAUTH_TOKEN", TEST_ANTHROPIC_OAUTH_TOKEN); } let settings = Settings { @@ -815,7 +816,7 @@ mod tests { ); assert_eq!( provider.oauth_token.as_ref().unwrap().expose_secret(), - "sk-ant-oat01-test-token" + TEST_ANTHROPIC_OAUTH_TOKEN ); clear_anthropic_env(); @@ -829,8 +830,8 @@ mod tests { clear_anthropic_env(); // SAFETY: Under ENV_MUTEX. unsafe { - std::env::set_var("ANTHROPIC_API_KEY", "sk-ant-real-key"); - std::env::set_var("ANTHROPIC_OAUTH_TOKEN", "sk-ant-oat01-test-token"); + std::env::set_var("ANTHROPIC_API_KEY", TEST_ANTHROPIC_API_KEY); + std::env::set_var("ANTHROPIC_OAUTH_TOKEN", TEST_ANTHROPIC_OAUTH_TOKEN); } let settings = Settings { @@ -845,7 +846,7 @@ mod tests { .api_key .as_ref() .map(|k| k.expose_secret().to_string()), - Some("sk-ant-real-key".to_string()), + Some(TEST_ANTHROPIC_API_KEY.to_string()), "real API key should take priority over OAuth placeholder" ); assert!( @@ -862,7 +863,7 @@ mod tests { clear_anthropic_env(); // SAFETY: Under ENV_MUTEX. unsafe { - std::env::set_var("ANTHROPIC_OAUTH_TOKEN", "sk-ant-oat01-test-token"); + std::env::set_var("ANTHROPIC_OAUTH_TOKEN", TEST_ANTHROPIC_OAUTH_TOKEN); } let settings = Settings { diff --git a/src/config/sandbox.rs b/src/config/sandbox.rs index d757822d..35be4393 100644 --- a/src/config/sandbox.rs +++ b/src/config/sandbox.rs @@ -272,6 +272,7 @@ fn parse_oauth_access_token(json: &str) -> Option { #[cfg(test)] mod tests { use crate::config::sandbox::*; + use crate::testing::credentials::*; // ── SandboxModeConfig defaults ────────────────────────────────── @@ -405,9 +406,12 @@ mod tests { #[test] fn parse_oauth_token_valid() { - let json = r#"{"claudeAiOauth": {"accessToken": "sk-ant-oat01-fake"}}"#; - let token = parse_oauth_access_token(json); - assert_eq!(token, Some("sk-ant-oat01-fake".to_string())); + let json = format!( + r#"{{"claudeAiOauth": {{"accessToken": "{}"}}}}"#, + TEST_ANTHROPIC_OAUTH_BASIC + ); + let token = parse_oauth_access_token(&json); + assert_eq!(token, Some(TEST_ANTHROPIC_OAUTH_BASIC.to_string())); } #[test] @@ -434,16 +438,19 @@ mod tests { #[test] fn parse_oauth_token_nested_extra_fields() { - let json = r#"{ - "claudeAiOauth": { - "accessToken": "sk-ant-oat01-real-token", + let json = format!( + r#"{{ + "claudeAiOauth": {{ + "accessToken": "{}", "refreshToken": "rt-abc", "expiresAt": 1700000000 - } - }"#; + }} + }}"#, + TEST_ANTHROPIC_OAUTH_NESTED + ); assert_eq!( - parse_oauth_access_token(json), - Some("sk-ant-oat01-real-token".to_string()) + parse_oauth_access_token(&json), + Some(TEST_ANTHROPIC_OAUTH_NESTED.to_string()) ); } diff --git a/src/extensions/manager.rs b/src/extensions/manager.rs index 7cf4b49a..b34810e8 100644 --- a/src/extensions/manager.rs +++ b/src/extensions/manager.rs @@ -3990,6 +3990,7 @@ mod tests { channels_dir: std::path::PathBuf, ) -> ExtensionManager { use crate::secrets::{InMemorySecretsStore, SecretsCrypto}; + use crate::testing::credentials::TEST_CRYPTO_KEY; use crate::tools::ToolRegistry; use crate::tools::mcp::process::McpProcessManager; use crate::tools::mcp::session::McpSessionManager; @@ -3997,8 +3998,7 @@ mod tests { std::fs::create_dir_all(&tools_dir).ok(); std::fs::create_dir_all(&channels_dir).ok(); - let master_key = - secrecy::SecretString::from("0123456789abcdef0123456789abcdef".to_string()); + let master_key = secrecy::SecretString::from(TEST_CRYPTO_KEY.to_string()); let crypto = Arc::new(SecretsCrypto::new(master_key).unwrap()); ExtensionManager::new( diff --git a/src/llm/session.rs b/src/llm/session.rs index 3d1c4785..1cb858a1 100644 --- a/src/llm/session.rs +++ b/src/llm/session.rs @@ -627,6 +627,9 @@ pub async fn create_session_manager(config: SessionConfig) -> Arc SecretsCrypto { // 32-byte test key - let key = "0123456789abcdef0123456789abcdef"; - SecretsCrypto::new(SecretString::from(key.to_string())).unwrap() + SecretsCrypto::new(SecretString::from(TEST_CRYPTO_KEY.to_string())).unwrap() } #[test] diff --git a/src/secrets/store.rs b/src/secrets/store.rs index 0bc180a7..d98e0cca 100644 --- a/src/secrets/store.rs +++ b/src/secrets/store.rs @@ -802,30 +802,25 @@ pub mod in_memory { #[cfg(test)] mod tests { - use std::sync::Arc; - - use secrecy::SecretString; - - use crate::secrets::crypto::SecretsCrypto; use crate::secrets::store::SecretsStore; - use crate::secrets::store::in_memory::InMemorySecretsStore; use crate::secrets::types::CreateSecretParams; + use crate::testing::credentials::{ + TEST_OPENAI_API_KEY_SHORT, TEST_SECRET_VALUE, TEST_STRIPE_KEY, test_secrets_store, + }; - fn test_store() -> InMemorySecretsStore { - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - InMemorySecretsStore::new(crypto) + fn test_store() -> crate::secrets::store::in_memory::InMemorySecretsStore { + test_secrets_store() } #[tokio::test] async fn test_create_and_get() { let store = test_store(); - let params = CreateSecretParams::new("api_key", "sk-test-12345"); + let params = CreateSecretParams::new("api_key", TEST_SECRET_VALUE); store.create("user1", params).await.unwrap(); let decrypted = store.get_decrypted("user1", "api_key").await.unwrap(); - assert_eq!(decrypted.expose(), "sk-test-12345"); + assert_eq!(decrypted.expose(), TEST_SECRET_VALUE); } #[tokio::test] @@ -878,11 +873,17 @@ mod tests { async fn test_is_accessible() { let store = test_store(); store - .create("user1", CreateSecretParams::new("openai_key", "sk-test")) + .create( + "user1", + CreateSecretParams::new("openai_key", TEST_OPENAI_API_KEY_SHORT), + ) .await .unwrap(); store - .create("user1", CreateSecretParams::new("stripe_key", "sk-live")) + .create( + "user1", + CreateSecretParams::new("stripe_key", TEST_STRIPE_KEY), + ) .await .unwrap(); diff --git a/src/testing/credentials.rs b/src/testing/credentials.rs new file mode 100644 index 00000000..9492b69b --- /dev/null +++ b/src/testing/credentials.rs @@ -0,0 +1,134 @@ +//! Centralized fake credential constants for tests. +//! +//! All values here are intentionally fake. Centralizing them makes security +//! audits trivial (one file to verify) and eliminates duplication across +//! the test suite. + +use std::sync::Arc; + +use secrecy::SecretString; + +use crate::secrets::{InMemorySecretsStore, SecretsCrypto}; + +// ── Encryption keys ────────────────────────────────────────────────────── + +/// 32-character key string for `SecretsCrypto::new()` in tests. +pub const TEST_CRYPTO_KEY: &str = "0123456789abcdef0123456789abcdef"; + +/// 32+ char key for web gateway `SecretsCrypto` in tests. +pub const TEST_GATEWAY_CRYPTO_KEY: &str = "test-key-at-least-32-chars-long!!"; + +// ── OpenAI-style API keys ──────────────────────────────────────────────── + +/// Generic OpenAI-style test API key. +pub const TEST_OPENAI_API_KEY: &str = "sk-test123"; + +/// OpenAI API key with longer format (config round-trip tests). +pub const TEST_OPENAI_API_KEY_LONG: &str = "sk-test-key-1234567890"; + +/// Short OpenAI-style key for secrets store accessibility tests. +pub const TEST_OPENAI_API_KEY_SHORT: &str = "sk-test"; + +/// OpenAI API key used in embeddings config issue-129 test. +pub const TEST_OPENAI_API_KEY_ISSUE_129: &str = "sk-test-key-for-issue-129"; + +// ── Anthropic keys ─────────────────────────────────────────────────────── + +/// Anthropic OAuth token for config tests. +pub const TEST_ANTHROPIC_OAUTH_TOKEN: &str = "sk-ant-oat01-test-token"; + +/// Anthropic API key for priority tests. +pub const TEST_ANTHROPIC_API_KEY: &str = "sk-ant-priority-key"; + +/// Anthropic OAuth token for sandbox config parse tests. +pub const TEST_ANTHROPIC_OAUTH_BASIC: &str = "sk-ant-oat01-basic"; + +/// Anthropic OAuth token in nested JSON parse test. +pub const TEST_ANTHROPIC_OAUTH_NESTED: &str = "sk-ant-oat01-primary-token"; + +// ── Google OAuth ───────────────────────────────────────────────────────── + +/// Google OAuth access token (standard test). +pub const TEST_GOOGLE_OAUTH_TOKEN: &str = "ya29.test-token"; + +/// Google OAuth access token (fresh/non-expired variant). +pub const TEST_GOOGLE_OAUTH_FRESH: &str = "ya29.fresh-token"; + +/// Google OAuth access token (legacy/no-expiry variant). +pub const TEST_GOOGLE_OAUTH_LEGACY: &str = "ya29.legacy-token"; + +// ── GitHub ─────────────────────────────────────────────────────────────── + +/// GitHub personal access token (test). +pub const TEST_GITHUB_TOKEN: &str = "ghp_test123"; + +// ── Telegram ──────────────────────────────────────────────────────────── + +/// Telegram bot token for credential redaction tests. +pub const TEST_TELEGRAM_BOT_TOKEN: &str = "telegram-test-bot-token-not-a-real-token"; + +// ── OAuth client credentials ──────────────────────────────────────────── + +/// OAuth client ID for token refresh tests. +pub const TEST_OAUTH_CLIENT_ID: &str = "test-client-id"; + +/// OAuth client secret for token refresh tests. +pub const TEST_OAUTH_CLIENT_SECRET: &str = "test-client-secret"; + +// ── Bearer/auth tokens ────────────────────────────────────────────────── + +/// Generic test bearer token. +pub const TEST_BEARER_TOKEN: &str = "test-token"; + +/// Bearer token with suffix (wasm wrapper credential injection). +pub const TEST_BEARER_TOKEN_123: &str = "test-token-123"; + +/// Auth token used by web gateway middleware tests. +pub const TEST_AUTH_SECRET_TOKEN: &str = "secret-token"; + +// ── Stripe ────────────────────────────────────────────────────────────── + +/// Stripe-style test key. +pub const TEST_STRIPE_KEY: &str = "sk_test_fake123"; + +// ── Redaction test values ─────────────────────────────────────────────── + +/// Secret-prefixed key for redaction/sanitization tests. +pub const TEST_REDACT_SECRET: &str = "sk-secret"; + +/// Secret-prefixed key with suffix for redaction tests. +pub const TEST_REDACT_SECRET_123: &str = "sk-secret-123"; + +// ── Session tokens ────────────────────────────────────────────────────── + +/// Generic session token for persistence tests. +pub const TEST_SESSION_TOKEN: &str = "test_token_123"; + +/// NEAR AI session token variant A. +pub const TEST_SESSION_NEARAI_ABC: &str = "sess_abc123"; + +/// NEAR AI session token variant B. +pub const TEST_SESSION_NEARAI_XYZ: &str = "sess_xyz789"; + +// ── Generic ────────────────────────────────────────────────────────────── + +/// Generic test API key for LLM config, embedding config, nearai tests. +pub const TEST_API_KEY: &str = "test-key"; + +/// Stored secret value for create-and-get tests. +pub const TEST_SECRET_VALUE: &str = "sk-test-12345"; + +/// HTTP webhook secret for channel tests. +pub const TEST_HTTP_SECRET: &str = "test-secret-123"; + +// ── Helpers ────────────────────────────────────────────────────────────── + +/// Create an `InMemorySecretsStore` backed by [`TEST_CRYPTO_KEY`]. +/// +/// Replaces the duplicated `test_store()` pattern found across multiple +/// test modules. +pub fn test_secrets_store() -> InMemorySecretsStore { + let crypto = + Arc::new(SecretsCrypto::new(SecretString::from(TEST_CRYPTO_KEY.to_string())).unwrap()); + InMemorySecretsStore::new(crypto) +} diff --git a/src/testing.rs b/src/testing/mod.rs similarity index 99% rename from src/testing.rs rename to src/testing/mod.rs index 8f57cffc..97612887 100644 --- a/src/testing.rs +++ b/src/testing/mod.rs @@ -18,6 +18,8 @@ //! } //! ``` +pub mod credentials; + use std::sync::Arc; use std::sync::Mutex; use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; diff --git a/src/tools/builtin/extension_tools.rs b/src/tools/builtin/extension_tools.rs index ce8a06a8..793ae610 100644 --- a/src/tools/builtin/extension_tools.rs +++ b/src/tools/builtin/extension_tools.rs @@ -768,11 +768,11 @@ mod tests { /// Create a stub manager for schema tests (these don't call execute). fn test_manager_stub() -> Arc { use crate::secrets::{InMemorySecretsStore, SecretsCrypto}; + use crate::testing::credentials::TEST_CRYPTO_KEY; use crate::tools::ToolRegistry; use crate::tools::mcp::session::McpSessionManager; - let master_key = - secrecy::SecretString::from("0123456789abcdef0123456789abcdef".to_string()); + let master_key = secrecy::SecretString::from(TEST_CRYPTO_KEY.to_string()); let crypto = Arc::new(SecretsCrypto::new(master_key).unwrap()); Arc::new(ExtensionManager::new( diff --git a/src/tools/builtin/http.rs b/src/tools/builtin/http.rs index c6e09139..3b506c24 100644 --- a/src/tools/builtin/http.rs +++ b/src/tools/builtin/http.rs @@ -609,6 +609,7 @@ impl Tool for HttpTool { #[cfg(test)] mod tests { use super::*; + use crate::testing::credentials::{TEST_OPENAI_API_KEY, test_secrets_store}; #[test] fn test_http_tool_schema_headers_is_array() { @@ -868,12 +869,7 @@ mod tests { let tool = HttpTool::new().with_credentials( registry, // secrets_store is not used in requires_approval, just needs to be present - Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( - crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "0123456789abcdef0123456789abcdef".to_string(), - )) - .unwrap(), - ))), + Arc::new(test_secrets_store()), ); let params = serde_json::json!({ @@ -890,15 +886,7 @@ mod tests { let registry = Arc::new(SharedCredentialRegistry::new()); // Empty registry - no credential mappings - let tool = HttpTool::new().with_credentials( - registry, - Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( - crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "0123456789abcdef0123456789abcdef".to_string(), - )) - .unwrap(), - ))), - ); + let tool = HttpTool::new().with_credentials(registry, Arc::new(test_secrets_store())); let params = serde_json::json!({ "method": "GET", @@ -926,7 +914,7 @@ mod tests { let params = serde_json::json!({ "method": "GET", "url": "https://example.com", - "headers": {"X-Custom": "Bearer sk-test123"} + "headers": {"X-Custom": format!("Bearer {TEST_OPENAI_API_KEY}")} }); assert_eq!(tool.requires_approval(¶ms), ApprovalRequirement::Always); } @@ -957,15 +945,7 @@ mod tests { let registry = Arc::new(SharedCredentialRegistry::new()); registry.add_mappings(vec![CredentialMapping::bearer("test_key", "api.test.com")]); - let tool = HttpTool::new().with_credentials( - registry, - Arc::new(crate::secrets::InMemorySecretsStore::new(Arc::new( - crate::secrets::SecretsCrypto::new(secrecy::SecretString::from( - "0123456789abcdef0123456789abcdef".to_string(), - )) - .unwrap(), - ))), - ); + let tool = HttpTool::new().with_credentials(registry, Arc::new(test_secrets_store())); // These calls should not panic in multi-thread runtime let params_no_auth = serde_json::json!({ diff --git a/src/tools/builtin/job.rs b/src/tools/builtin/job.rs index f502259f..880f8622 100644 --- a/src/tools/builtin/job.rs +++ b/src/tools/builtin/job.rs @@ -1748,14 +1748,10 @@ mod tests { #[tokio::test] async fn test_parse_credentials_missing_secret() { - use crate::secrets::{InMemorySecretsStore, SecretsCrypto}; - use secrecy::SecretString; + use crate::testing::credentials::test_secrets_store; let manager = Arc::new(ContextManager::new(5)); - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let secrets: Arc = - Arc::new(InMemorySecretsStore::new(crypto)); + let secrets: Arc = Arc::new(test_secrets_store()); let tool = CreateJobTool::new(manager).with_secrets(Arc::clone(&secrets)); @@ -1772,20 +1768,17 @@ mod tests { #[tokio::test] async fn test_parse_credentials_valid() { - use crate::secrets::{CreateSecretParams, InMemorySecretsStore, SecretsCrypto}; - use secrecy::SecretString; + use crate::secrets::CreateSecretParams; + use crate::testing::credentials::{TEST_GITHUB_TOKEN, test_secrets_store}; let manager = Arc::new(ContextManager::new(5)); - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let secrets: Arc = - Arc::new(InMemorySecretsStore::new(Arc::clone(&crypto))); + let secrets: Arc = Arc::new(test_secrets_store()); // Store a secret secrets .create( "user1", - CreateSecretParams::new("github_token", "ghp_test123"), + CreateSecretParams::new("github_token", TEST_GITHUB_TOKEN), ) .await .unwrap(); diff --git a/src/tools/builtin/secrets_tools.rs b/src/tools/builtin/secrets_tools.rs index 8d5c8d62..af2d035b 100644 --- a/src/tools/builtin/secrets_tools.rs +++ b/src/tools/builtin/secrets_tools.rs @@ -158,16 +158,13 @@ impl Tool for SecretDeleteTool { mod tests { use std::sync::Arc; - use secrecy::SecretString; - use super::*; use crate::context::JobContext; - use crate::secrets::{CreateSecretParams, InMemorySecretsStore, SecretsCrypto}; + use crate::secrets::CreateSecretParams; + use crate::testing::credentials::{TEST_OPENAI_API_KEY_SHORT, test_secrets_store}; - fn test_store() -> Arc { - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - Arc::new(InMemorySecretsStore::new(crypto)) + fn test_store() -> Arc { + Arc::new(test_secrets_store()) } fn test_ctx() -> JobContext { @@ -183,7 +180,7 @@ mod tests { store .create( &ctx.user_id, - CreateSecretParams::new("openai_key", "sk-test"), + CreateSecretParams::new("openai_key", TEST_OPENAI_API_KEY_SHORT), ) .await .unwrap(); diff --git a/src/tools/tool.rs b/src/tools/tool.rs index 2e1b5183..8bf29168 100644 --- a/src/tools/tool.rs +++ b/src/tools/tool.rs @@ -480,6 +480,7 @@ pub fn validate_tool_schema(schema: &serde_json::Value, path: &str) -> Vec String { #[cfg(test)] mod tests { use std::collections::HashMap; - use std::sync::Arc; - - use secrecy::SecretString; use crate::secrets::{ CreateSecretParams, CredentialLocation, CredentialMapping, InMemorySecretsStore, - SecretsCrypto, SecretsStore, + SecretsStore, }; + use crate::testing::credentials::{TEST_OPENAI_API_KEY, test_secrets_store}; use crate::tools::wasm::credential_injector::{ CredentialInjector, base64_encode, host_matches_pattern, }; fn test_store() -> InMemorySecretsStore { - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - InMemorySecretsStore::new(crypto) + test_secrets_store() } #[test] @@ -406,7 +402,10 @@ mod tests { async fn test_inject_bearer() { let store = test_store(); store - .create("user1", CreateSecretParams::new("openai_key", "sk-test123")) + .create( + "user1", + CreateSecretParams::new("openai_key", TEST_OPENAI_API_KEY), + ) .await .unwrap(); @@ -428,7 +427,7 @@ mod tests { assert_eq!( result.headers.get("Authorization"), - Some(&"Bearer sk-test123".to_string()) + Some(&format!("Bearer {TEST_OPENAI_API_KEY}")) ); } diff --git a/src/tools/wasm/loader.rs b/src/tools/wasm/loader.rs index 07319f21..afa471a1 100644 --- a/src/tools/wasm/loader.rs +++ b/src/tools/wasm/loader.rs @@ -694,6 +694,7 @@ mod tests { use tempfile::TempDir; + use crate::testing::credentials::{TEST_OAUTH_CLIENT_ID, TEST_OAUTH_CLIENT_SECRET}; use crate::tools::wasm::loader::{WasmLoadError, check_wit_version_compat, discover_tools}; #[test] @@ -834,8 +835,8 @@ mod tests { oauth: Some(OAuthConfigSchema { authorization_url: "https://accounts.google.com/o/oauth2/v2/auth".to_string(), token_url: "https://oauth2.googleapis.com/token".to_string(), - client_id: Some("test-client-id".to_string()), - client_secret: Some("test-client-secret".to_string()), + client_id: Some(TEST_OAUTH_CLIENT_ID.to_string()), + client_secret: Some(TEST_OAUTH_CLIENT_SECRET.to_string()), ..Default::default() }), ..Default::default() @@ -848,8 +849,11 @@ mod tests { let config = config.unwrap(); assert_eq!(config.token_url, "https://oauth2.googleapis.com/token"); - assert_eq!(config.client_id, "test-client-id"); - assert_eq!(config.client_secret, Some("test-client-secret".to_string())); + assert_eq!(config.client_id, TEST_OAUTH_CLIENT_ID); + assert_eq!( + config.client_secret, + Some(TEST_OAUTH_CLIENT_SECRET.to_string()) + ); assert_eq!(config.secret_name, "google_oauth_token"); assert_eq!(config.provider, Some("google".to_string())); } diff --git a/src/tools/wasm/wrapper.rs b/src/tools/wasm/wrapper.rs index 591bf549..26c2d5d1 100644 --- a/src/tools/wasm/wrapper.rs +++ b/src/tools/wasm/wrapper.rs @@ -1223,6 +1223,11 @@ fn coerce_params_to_schema( mod tests { use std::sync::Arc; + use crate::testing::credentials::{ + TEST_BEARER_TOKEN_123, TEST_GOOGLE_OAUTH_FRESH, TEST_GOOGLE_OAUTH_LEGACY, + TEST_GOOGLE_OAUTH_TOKEN, TEST_OAUTH_CLIENT_ID, TEST_OAUTH_CLIENT_SECRET, + test_secrets_store, + }; use crate::tools::wasm::capabilities::Capabilities; use crate::tools::wasm::runtime::{WasmRuntimeConfig, WasmToolRuntime}; @@ -1290,12 +1295,12 @@ mod tests { let mut h = HashMap::new(); h.insert( "Authorization".to_string(), - "Bearer test-token-123".to_string(), + format!("Bearer {TEST_BEARER_TOKEN_123}"), ); h }, query_params: HashMap::new(), - secret_value: "test-token-123".to_string(), + secret_value: TEST_BEARER_TOKEN_123.to_string(), }]; let store_data = StoreData::new( @@ -1311,7 +1316,7 @@ mod tests { store_data.inject_host_credentials("www.googleapis.com", &mut headers, &mut url); assert_eq!( headers.get("Authorization"), - Some(&"Bearer test-token-123".to_string()) + Some(&format!("Bearer {TEST_BEARER_TOKEN_123}")) ); // Should not inject for non-matching host @@ -1387,13 +1392,9 @@ mod tests { #[tokio::test] async fn test_resolve_host_credentials_no_http_cap() { - use crate::secrets::{InMemorySecretsStore, SecretsCrypto}; use crate::tools::wasm::wrapper::resolve_host_credentials; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); let caps = Capabilities::default(); let result = resolve_host_credentials(&caps, Some(&store), "user1", None).await; @@ -1405,21 +1406,17 @@ mod tests { use std::collections::HashMap; use crate::secrets::{ - CreateSecretParams, CredentialLocation, CredentialMapping, InMemorySecretsStore, - SecretsCrypto, SecretsStore, + CreateSecretParams, CredentialLocation, CredentialMapping, SecretsStore, }; use crate::tools::wasm::capabilities::HttpCapability; use crate::tools::wasm::wrapper::resolve_host_credentials; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); store .create( "user1", - CreateSecretParams::new("google_oauth_token", "ya29.test-token"), + CreateSecretParams::new("google_oauth_token", TEST_GOOGLE_OAUTH_TOKEN), ) .await .unwrap(); @@ -1447,7 +1444,7 @@ mod tests { assert_eq!(result[0].host_patterns, vec!["www.googleapis.com"]); assert_eq!( result[0].headers.get("Authorization"), - Some(&"Bearer ya29.test-token".to_string()) + Some(&format!("Bearer {TEST_GOOGLE_OAUTH_TOKEN}")) ); } @@ -1455,16 +1452,11 @@ mod tests { async fn test_resolve_host_credentials_missing_secret() { use std::collections::HashMap; - use crate::secrets::{ - CredentialLocation, CredentialMapping, InMemorySecretsStore, SecretsCrypto, - }; + use crate::secrets::{CredentialLocation, CredentialMapping}; use crate::tools::wasm::capabilities::HttpCapability; use crate::tools::wasm::wrapper::resolve_host_credentials; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); // No secret stored, should silently skip let mut credentials = HashMap::new(); @@ -1494,23 +1486,19 @@ mod tests { use std::collections::HashMap; use crate::secrets::{ - CreateSecretParams, CredentialLocation, CredentialMapping, InMemorySecretsStore, - SecretsCrypto, SecretsStore, + CreateSecretParams, CredentialLocation, CredentialMapping, SecretsStore, }; use crate::tools::wasm::capabilities::HttpCapability; use crate::tools::wasm::wrapper::{OAuthRefreshConfig, resolve_host_credentials}; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); // Store a token that expires 2 hours from now (well within buffer) let expires_at = chrono::Utc::now() + chrono::Duration::hours(2); store .create( "user1", - CreateSecretParams::new("google_oauth_token", "ya29.fresh-token") + CreateSecretParams::new("google_oauth_token", TEST_GOOGLE_OAUTH_FRESH) .with_expiry(expires_at), ) .await @@ -1536,8 +1524,8 @@ mod tests { let oauth_config = OAuthRefreshConfig { token_url: "https://oauth2.googleapis.com/token".to_string(), - client_id: "test-client-id".to_string(), - client_secret: Some("test-client-secret".to_string()), + client_id: TEST_OAUTH_CLIENT_ID.to_string(), + client_secret: Some(TEST_OAUTH_CLIENT_SECRET.to_string()), secret_name: "google_oauth_token".to_string(), provider: Some("google".to_string()), }; @@ -1548,7 +1536,7 @@ mod tests { assert_eq!(result.len(), 1); assert_eq!( result[0].headers.get("Authorization"), - Some(&"Bearer ya29.fresh-token".to_string()) + Some(&format!("Bearer {TEST_GOOGLE_OAUTH_FRESH}")) ); } @@ -1557,16 +1545,12 @@ mod tests { use std::collections::HashMap; use crate::secrets::{ - CreateSecretParams, CredentialLocation, CredentialMapping, InMemorySecretsStore, - SecretsCrypto, SecretsStore, + CreateSecretParams, CredentialLocation, CredentialMapping, SecretsStore, }; use crate::tools::wasm::capabilities::HttpCapability; use crate::tools::wasm::wrapper::resolve_host_credentials; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); // Store an expired token let expires_at = chrono::Utc::now() - chrono::Duration::hours(1); @@ -1606,22 +1590,18 @@ mod tests { use std::collections::HashMap; use crate::secrets::{ - CreateSecretParams, CredentialLocation, CredentialMapping, InMemorySecretsStore, - SecretsCrypto, SecretsStore, + CreateSecretParams, CredentialLocation, CredentialMapping, SecretsStore, }; use crate::tools::wasm::capabilities::HttpCapability; use crate::tools::wasm::wrapper::{OAuthRefreshConfig, resolve_host_credentials}; - use secrecy::SecretString; - let key = "0123456789abcdef0123456789abcdef"; - let crypto = Arc::new(SecretsCrypto::new(SecretString::from(key.to_string())).unwrap()); - let store = InMemorySecretsStore::new(crypto); + let store = test_secrets_store(); // Legacy token: no expires_at set store .create( "user1", - CreateSecretParams::new("google_oauth_token", "ya29.legacy-token"), + CreateSecretParams::new("google_oauth_token", TEST_GOOGLE_OAUTH_LEGACY), ) .await .unwrap(); @@ -1646,8 +1626,8 @@ mod tests { let oauth_config = OAuthRefreshConfig { token_url: "https://oauth2.googleapis.com/token".to_string(), - client_id: "test-client-id".to_string(), - client_secret: Some("test-client-secret".to_string()), + client_id: TEST_OAUTH_CLIENT_ID.to_string(), + client_secret: Some(TEST_OAUTH_CLIENT_SECRET.to_string()), secret_name: "google_oauth_token".to_string(), provider: Some("google".to_string()), }; @@ -1658,7 +1638,7 @@ mod tests { assert_eq!(result.len(), 1); assert_eq!( result[0].headers.get("Authorization"), - Some(&"Bearer ya29.legacy-token".to_string()) + Some(&format!("Bearer {TEST_GOOGLE_OAUTH_LEGACY}")) ); } diff --git a/src/tunnel/mod.rs b/src/tunnel/mod.rs index 38ad814b..e6245b9e 100644 --- a/src/tunnel/mod.rs +++ b/src/tunnel/mod.rs @@ -294,10 +294,11 @@ mod tests { #[test] fn factory_cloudflare_with_config_ok() { + use crate::testing::credentials::TEST_BEARER_TOKEN; let cfg = TunnelProviderConfig { provider: "cloudflare".into(), cloudflare: Some(CloudflareTunnelConfig { - token: "test-token".into(), + token: TEST_BEARER_TOKEN.into(), }), ..Default::default() }; diff --git a/src/worker/api.rs b/src/worker/api.rs index d0048afc..459375b4 100644 --- a/src/worker/api.rs +++ b/src/worker/api.rs @@ -419,13 +419,14 @@ fn parse_finish_reason(s: &str) -> FinishReason { #[cfg(test)] mod tests { use super::*; + use crate::testing::credentials::TEST_BEARER_TOKEN; #[test] fn test_url_construction() { let client = WorkerHttpClient::new( "http://host.docker.internal:50051".to_string(), Uuid::nil(), - "test-token".to_string(), + TEST_BEARER_TOKEN.to_string(), ); assert_eq!( @@ -449,7 +450,7 @@ mod tests { let client = WorkerHttpClient::new( "http://host.docker.internal:50051".to_string(), Uuid::nil(), - "test-token".to_string(), + TEST_BEARER_TOKEN.to_string(), ); assert_eq!( diff --git a/tests/config_round_trip.rs b/tests/config_round_trip.rs index 9ae1e3a1..8351ff74 100644 --- a/tests/config_round_trip.rs +++ b/tests/config_round_trip.rs @@ -12,6 +12,11 @@ use tempfile::tempdir; use ironclaw::bootstrap::{save_bootstrap_env_to, upsert_bootstrap_var_to}; +/// Fake OpenAI API key for test use only. Mirrors the internal +/// `TEST_OPENAI_API_KEY_LONG` constant from the main crate, which is not +/// directly available to integration tests due to `#[cfg(test)]`. +const TEST_OPENAI_API_KEY_LONG: &str = "sk-test-key-1234567890"; + /// Parse a .env file into a HashMap using dotenvy. fn read_env_map(path: &std::path::Path) -> HashMap { dotenvy::from_path_iter(path) @@ -77,7 +82,7 @@ fn bootstrap_env_round_trips_embedding_disabled() { &[ ("DATABASE_BACKEND", "libsql"), ("EMBEDDING_ENABLED", "false"), - ("OPENAI_API_KEY", "sk-test-key-1234567890"), + ("OPENAI_API_KEY", TEST_OPENAI_API_KEY_LONG), ("ONBOARD_COMPLETED", "true"), ], ) @@ -92,7 +97,7 @@ fn bootstrap_env_round_trips_embedding_disabled() { ); assert_eq!( map.get("OPENAI_API_KEY").map(String::as_str), - Some("sk-test-key-1234567890"), + Some(TEST_OPENAI_API_KEY_LONG), "OPENAI_API_KEY must be preserved alongside EMBEDDING_ENABLED" ); }