Documentation Index Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
Use this file to discover all available pages before exploring further.
Environment-Specific Secret Values
Use a single secret with different values for each environment. KnoxCall automatically uses the correct value based on the route’s active environment—no manual switching required.
The Problem
Traditional approach requires separate secrets per environment:
❌ Old Way: 3 Secrets
├─ stripe_production_key → sk_live_abc123
├─ stripe_staging_key → sk_test_staging_456
└─ stripe_development_key → sk_test_dev_789
Route config must change per environment:
Production: {{secret:stripe_production_key}}
Staging: {{secret:stripe_staging_key}}
Development: {{secret:stripe_development_key}}
Problems:
Accidental use of production keys in staging
Manual route config updates when switching environments
Difficult to audit which env uses which key
Secret sprawl (3x secrets)
The Solution
One secret, multiple environment-specific values:
✅ New Way: 1 Secret
stripe_api_key
├─ production: sk_live_abc123
├─ staging: sk_test_staging_456
└─ development: sk_test_dev_789
Route config stays the same:
All environments: {{secret:stripe_api_key}}
Benefits:
✅ Automatic environment-based resolution
✅ Hard fail if environment value missing (prevents accidents)
✅ Simplified route configuration
✅ Clear audit trail per environment
How It Works
Step 1: Create Secret
Create a secret normally:
Name: stripe_api_key
Type: String
Leave the initial value empty—we’ll set environment-specific values next.
In the secret detail page:
Select environment from dropdown (top right)
Enter value for that environment
Save
Repeat for other environments
Example:
Environment: production
Value: sk_live_4eC39HqLyjWDarjtT1zdp7dc
[Save]
Environment: staging
Value: sk_test_staging_BQokikJOvBiI2HlWgH4olfQ2
[Save]
Environment: development
Value: sk_test_dev_4eC39HqLyjWDarjtT1zdp7dc
[Save]
Step 3: Reference in Route
Use the secret in your route config:
{
"headers" : {
"Authorization" : "Bearer {{secret:stripe_api_key}}"
}
}
Step 4: Automatic Resolution
When a request comes in:
1. Client calls route
2. Route has active environment: "production"
3. KnoxCall looks up stripe_api_key environment config
4. Finds production value: sk_live_4eC39HqLyjWDarjtT1zdp7dc
5. Injects value into request
6. Proxies to Stripe API ✅
If route is in staging environment:
Same route, staging environment:
→ Uses sk_test_staging_BQokikJOvBiI2HlWgH4olfQ2 automatically
Hard Fail Behavior
Safety feature : If a secret lacks a value for the requested environment, the request fails immediately .
Scenario:
- Secret: stripe_api_key
- Configured environments: production, staging
- Route environment: development ❌
Result:
HTTP 500 Internal Server Error
{
"error": "Secret 'stripe_api_key' not configured for environment 'development'"
}
Why no fallback?
Prevents accidental production key usage in dev/staging
Forces explicit configuration
Makes missing config obvious during testing
Complies with principle of least privilege
Solution:
Add the missing environment value or change route’s active environment.
Supported Secret Types
Environment-specific values work with all secret types :
String Secrets
API Key: stripe_api_key
├─ production: sk_live_abc123
├─ staging: sk_test_staging_456
└─ development: sk_test_dev_789
OAuth2 Secrets
OAuth Client: google_oauth
├─ production:
│ client_id: prod-client-id.apps.googleusercontent.com
│ client_secret: GOCSPX-prod-abc123
│
├─ staging:
│ client_id: staging-client-id.apps.googleusercontent.com
│ client_secret: GOCSPX-staging-def456
│
└─ development:
client_id: dev-client-id.apps.googleusercontent.com
client_secret: GOCSPX-dev-ghi789
Certificate Secrets (mTLS)
Client Certificate: bank_mtls_cert
├─ production:
│ cert: -----BEGIN CERTIFICATE----- (prod cert)
│ key: -----BEGIN PRIVATE KEY----- (prod key)
│
├─ staging:
│ cert: -----BEGIN CERTIFICATE----- (staging cert)
│ key: -----BEGIN PRIVATE KEY----- (staging key)
│
└─ development:
cert: -----BEGIN CERTIFICATE----- (dev cert)
key: -----BEGIN PRIVATE KEY----- (dev key)
Advanced Usage
Partial Environment Coverage
You can configure only the environments you need:
Secret: internal_api_key
Configured:
✅ production
✅ staging
❌ development (not configured)
Routes in development environment:
→ Will fail (hard fail)
→ Forces you to add dev value or use different secret
Duplicating Environments
Clone an existing environment’s value:
Go to secret detail page
Select source environment (e.g., “production”)
Click Duplicate to another environment
Choose target environment (e.g., “staging”)
Modify the duplicated value if needed
Save
Use case: Copy production config to staging, then change specific values.
Deleting Environment Values
Protected deletion : Cannot delete an environment value if any route is actively using it in that environment.
Scenario:
- Secret: stripe_api_key has production value
- Route "Stripe Charges" is active in production environment
- Try to delete production value
Result:
❌ Error: Cannot delete - 1 route using this secret in production
Routes: Stripe Charges (route_abc123)
Solution:
Switch routes to different environment, OR
Update routes to use different secret, OR
Delete the routes first
Viewing All Environments
In the secret detail page, see all configured environments at a glance:
Secret: stripe_api_key
Environment Status:
✅ production (configured, 4 routes using)
✅ staging (configured, 2 routes using)
✅ development (configured, 0 routes using)
⚠️ testing (not configured)
API Reference
Get Secret Environments
GET /admin/secrets/{secret_id}/environments
Response:
{
"secret_id" : "uuid" ,
"secret_name" : "stripe-prod-key" ,
"secret_type" : "string" ,
"base_environment" : "production" ,
"environments" : [
{
"environment_name" : "production" ,
"created_at" : "2025-01-15T10:00:00Z" ,
"updated_at" : "2025-01-20T14:30:00Z"
},
{
"environment_name" : "staging" ,
"created_at" : "2025-01-15T10:05:00Z" ,
"updated_at" : "2025-01-15T10:05:00Z"
}
]
}
Note: Values are never returned via API for security.
Create/Update Environment Value
PUT /admin/secrets/{secret_id}/environments/{environment_name}
Body (String secret only):
{
"value" : "sk_test_abc123"
}
Note: This endpoint only accepts `string` secrets. OAuth 2 and certificate secrets have their own
dedicated endpoints for managing environment-level values.
Delete Environment Value
DELETE /admin/secrets/{secret_id}/environments/{environment_name}
Response:
{
"ok" : true
}
Or if in use by routes:
{
"error" : "Cannot remove environment 'production' from this secret. It is used by the following routes in that environment: stripe-charges. Remove the secret from those routes first." ,
"routes" : [{ "id" : "uuid" , "name" : "stripe-charges" }]
}
Duplicate Environment
POST /admin/secrets/{secret_id}/environments/{source_env}/duplicate
Body:
{
"target_environment" : "development"
}
Response:
{
"ok" : true ,
"environment" : "development" ,
"message" : "Successfully created environment 'development' from 'staging'"
}
Migration Guide
From Naming Convention to Environment Configs
Before:
Secrets:
- stripe_production_key
- stripe_staging_key
- stripe_development_key
Route config (production):
{
"Authorization": "Bearer {{secret:stripe_production_key}}"
}
After:
Secret: stripe_api_key
├─ production: (value from stripe_production_key)
├─ staging: (value from stripe_staging_key)
└─ development: (value from stripe_development_key)
Route config (all environments):
{
"Authorization": "Bearer {{secret:stripe_api_key}}"
}
Steps:
Create new secret : stripe_api_key (no initial value)
Copy values :
Environment: production → Paste value from stripe_production_key
Environment: staging → Paste value from stripe_staging_key
Environment: development → Paste value from stripe_development_key
Update routes :
Change {{secret:stripe_production_key}} to {{secret:stripe_api_key}}
Remove environment-specific references
Test in staging first
Deploy to production
Delete old secrets after 48 hours
Best Practices
✅ Do This
Use environment configs for new secrets
Simpler, safer, better audit trail
Configure all environments you use
Don’t leave gaps (hard fail protects you)
Test in staging first
Verify correct values loaded per environment
Use descriptive names
stripe_api_key not secret_42
Easier to manage across environments
Document your environments
Keep a list of which environments exist
Standard: production, staging, development
❌ Avoid This
Don’t mix approaches for same service
Either use env configs OR naming convention
Don’t use both for Stripe (confusing)
Don’t delete environment values carelessly
Check if routes are using them first
System prevents deletion, but verify manually
Don’t share values across environments
Never use production keys in staging
Even if system allows it, don’t do it
Don’t skip testing after migration
Always test in dev/staging first
Verify hard fail works as expected
Troubleshooting
Problem:
Route fails with:
"Secret 'api_key' not configured for environment 'staging'"
Solutions:
Add the missing environment value
Change route’s active environment
Use a different secret that has the environment
Can’t delete environment value
Problem:
Cannot delete - 3 routes using this secret in production
Solution:
-- Find routes using this secret
SELECT r.name, r.id
FROM routes r
JOIN route_environment_configs rec ON r.id = rec.route_id
WHERE rec.environment_name = 'production'
AND rec.active = true;
-- Then either:
1 . Switch those routes to different environment
2 . Update routes to use different secret
3 . Accept that you can 't delete (it' s in use !)
Environment dropdown not showing
Problem: Can’t see environment selector in secret detail page
Possible causes:
Secret type doesn’t support environments (shouldn’t happen - all types do)
Browser cache issue - hard refresh (Ctrl+F5)
Old UI version - ensure admin-ui is up to date
Solution:
cd admin-ui && npm run build
pm2 restart knoxcall
Wrong value being used
Problem: Route in staging is using production value
Debug steps:
Check route’s active environment (top right dropdown)
Verify secret has value for that environment
Check route config uses correct secret name
Test with a different route
Common cause: Route’s active environment is set to “production” even though you think it’s staging.
Security Considerations
Encryption
All environment values are encrypted individually:
Secret: stripe_api_key
Each environment value:
├─ Encrypted with unique data encryption key (DEK)
├─ DEK encrypted with master key (KEK)
├─ Stored: ciphertext + IV + auth tag
└─ Decrypted only when route resolves secret
Audit Trail
Every environment value change is logged:
SELECT
secret_id,
environment_name,
operation, -- 'create', 'update', 'delete'
performed_by,
performed_at
FROM secret_environment_audit_log
WHERE secret_id = 'sec_abc123' ;
Access Control
Only tenant admins can view/edit secret environment configs
API requires authentication via JWT
No way to retrieve values via API (write-only)
Environment values never logged or transmitted in plaintext
Compliance
Environment-specific secrets help with:
PCI DSS : Separate production and test credentials
SOC 2 : Audit trail of secret changes per environment
GDPR : Environment isolation for data protection
HIPAA : Segregation of production and non-production
Next Steps
Creating Secrets Learn how to create secrets in KnoxCall
Using Secrets in Routes Reference secrets in route configurations
Environment Basics Understand KnoxCall environments
Secret Rotation Best practices for rotating secrets
📊 Guide Info
Level : Intermediate
Time : 10 minutes
Prerequisites : Basic understanding of secrets and environments
🏷️ Tags secrets, environments, configuration, security, credentials