refactor: centralize test credential constants into testing::credentials (#829)

* 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) <[email protected]>

* refactor: replace real Telegram bot token with obviously fake test stub

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* Update src/testing/credentials.rs

Co-authored-by: Copilot <[email protected]>

* Update src/testing/credentials.rs

Co-authored-by: Copilot <[email protected]>

* 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 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Henry Park
2026-03-10 13:25:32 -07:00
committed by GitHub
co-authored by Claude Opus 4.6 Copilot
parent 24d4fbb8a7
commit 76375f2eaa
25 changed files with 314 additions and 201 deletions
+3 -2
View File
@@ -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<String, crate::error::Error> =
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
);
+8 -5
View File
@@ -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!(
+27 -26
View File
@@ -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();
+4 -3
View File
@@ -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<dyn crate::secrets::SecretsStore + Send + Sync> =
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<dyn crate::secrets::SecretsStore + Send + Sync> =
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"),
)));