Files
orion/docs/development/environment-detection.md
Samir Boulahtit e9253fbd84 refactor: rename Wizamart to Orion across entire codebase
Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart
with Orion/orion/ORION across 184 files. This includes database
identifiers, email addresses, domain references, R2 bucket names,
DNS prefixes, encryption salt, Celery app name, config defaults,
Docker configs, CI configs, documentation, seed data, and templates.

Renames homepage-wizamart.html template to homepage-orion.html.
Fixes duplicate file_pattern key in api.yaml architecture rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:46:56 +01:00

1116 lines
27 KiB
Markdown

# Environment Detection System
**Version:** 1.0
**Last Updated:** November 2025
**Audience:** Development Team
---
## Table of Contents
1. [Overview](#overview)
2. [How It Works](#how-it-works)
3. [Using Environment Detection](#using-environment-detection)
4. [Configuration](#configuration)
5. [Development Guidelines](#development-guidelines)
6. [Deployment Guide](#deployment-guide)
7. [Testing](#testing)
8. [Best Practices](#best-practices)
---
## Overview
The Orion platform uses **automatic environment detection** to determine the runtime environment (development, staging, or production) and adjust security settings accordingly.
### Why Auto-Detection?
Instead of manually configuring environment settings in code, the system automatically detects the environment based on:
- Environment variables
- Runtime indicators (hostname, debug mode, etc.)
- Safe defaults for local development
This approach:
- ✅ Works out of the box in development (no configuration needed)
- ✅ Reduces configuration errors
- ✅ Follows "convention over configuration" principle
- ✅ Simplifies deployment process
### Key Use Cases
The environment detection system is primarily used to determine:
1. **Cookie Security** - Should cookies require HTTPS? (`secure` flag)
2. **Debug Mode** - Enable detailed error messages in development
3. **CORS Settings** - Stricter in production, relaxed in development
4. **Logging Level** - Verbose in development, structured in production
---
## How It Works
### Detection Logic
The system determines the environment using a priority-based approach:
```
1. Check ENV environment variable
↓ (if not set)
2. Check ENVIRONMENT environment variable
↓ (if not set)
3. Auto-detect from system indicators
↓ (if no indicators)
4. Default to "development" (safe for local work)
```
### Detection Details
#### Priority 1: ENV Variable
```bash
ENV=production
ENV=staging
ENV=development # or "dev" or "local"
```
#### Priority 2: ENVIRONMENT Variable
```bash
ENVIRONMENT=production
ENVIRONMENT=staging
ENVIRONMENT=development
```
#### Priority 3: Auto-Detection
The system checks for indicators:
**Development Indicators:**
- `DEBUG=true` environment variable
- Hostname contains: "local", "dev", "laptop", "desktop"
- Running on: localhost, 127.0.0.1
**Staging Indicators:**
- Hostname contains: "staging", "stage"
**Production Indicators:**
- None of the above (explicit production setting recommended)
#### Priority 4: Safe Default
If no environment is detected: **defaults to development**
- Safe for local development
- Cookies work with HTTP
- Detailed error messages enabled
---
## Using Environment Detection
### Module Location
```python
app/core/environment.py
```
### Available Functions
```python
from app.core.environment import (
get_environment, # Returns: "development" | "staging" | "production"
is_development, # Returns: bool
is_staging, # Returns: bool
is_production, # Returns: bool
should_use_secure_cookies, # Returns: bool
get_cached_environment, # Returns: cached environment (performance)
)
```
### Common Usage Patterns
#### 1. Cookie Security Settings
```python
from fastapi import Response
from app.core.environment import should_use_secure_cookies
@router.post("/api/v1/admin/auth/login")
def login(response: Response):
# Set authentication cookie
response.set_cookie(
key="admin_token",
value=token,
httponly=True,
secure=should_use_secure_cookies(), # Auto-detects environment
samesite="lax",
path="/admin"
)
return {"message": "Logged in"}
```
**Behavior:**
- **Development** → `secure=False` (works with HTTP)
- **Production** → `secure=True` (requires HTTPS)
#### 2. Conditional Features
```python
from app.core.environment import is_development, is_production
@router.get("/api/v1/debug/info")
def debug_info():
if not is_development():
raise HTTPException(status_code=404, detail="Not found")
# Only accessible in development
return {
"database": get_db_info(),
"cache": get_cache_stats(),
"config": get_config_dump()
}
```
#### 3. Error Messages
```python
from app.core.environment import is_development
@app.exception_handler(Exception)
async def exception_handler(request: Request, exc: Exception):
if is_development():
# Detailed error in development
return JSONResponse(
status_code=500,
content={
"error": str(exc),
"traceback": traceback.format_exc(),
"request": str(request.url)
}
)
else:
# Generic error in production
return JSONResponse(
status_code=500,
content={"error": "Internal server error"}
)
```
#### 4. CORS Configuration
```python
from fastapi.middleware.cors import CORSMiddleware
from app.core.environment import is_development
if is_development():
# Relaxed CORS for development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
else:
# Strict CORS for production
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"],
)
```
#### 5. Logging Configuration
```python
import logging
from app.core.environment import get_environment
def configure_logging():
env = get_environment()
if env == "development":
# Verbose logging for development
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
elif env == "staging":
# Moderate logging for staging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
else: # production
# Structured logging for production
logging.basicConfig(
level=logging.WARNING,
format='{"timestamp":"%(asctime)s","level":"%(levelname)s","message":"%(message)s"}'
)
```
#### 6. Performance Optimization
```python
from app.core.environment import get_cached_environment
def process_request(request: Request):
# Use cached version for frequent calls
env = get_cached_environment() # Cached - faster
# Instead of:
# env = get_environment() # Re-detects every time
if env == "production":
# Production-specific optimization
use_cache = True
else:
use_cache = False
```
---
## Configuration
### Development (Default)
**No configuration needed!** The system auto-detects development mode.
**Indicators:**
- Running on localhost or 127.0.0.1
- No environment variables set
- DEBUG mode enabled
**Settings:**
- `should_use_secure_cookies()``False`
- Cookies work with HTTP (http://localhost:8000)
- Detailed error messages
### Staging Environment
**Set environment variable:**
```bash
# Option 1: ENV
export ENV=staging
# Option 2: ENVIRONMENT
export ENVIRONMENT=staging
# Start application
uvicorn main:app --host 0.0.0.0 --port 8000
```
**Or in Docker:**
```dockerfile
ENV ENV=staging
```
**Settings:**
- `should_use_secure_cookies()``True`
- Requires HTTPS
- Moderate logging
### Production Environment
**Set environment variable:**
```bash
# Option 1: ENV
export ENV=production
# Option 2: ENVIRONMENT
export ENVIRONMENT=production
# Start application
uvicorn main:app --host 0.0.0.0 --port 8000
```
**Or in systemd service:**
```ini
[Service]
Environment="ENV=production"
ExecStart=/usr/bin/uvicorn main:app --host 0.0.0.0 --port 8000
```
**Or in Docker Compose:**
```yaml
services:
web:
image: orion:latest
environment:
- ENV=production
ports:
- "8000:8000"
```
**Settings:**
- `should_use_secure_cookies()``True`
- Requires HTTPS
- Minimal logging (warnings/errors only)
- Generic error messages
---
## Development Guidelines
### When Writing New Code
#### Use Environment Functions
**DO:**
```python
from app.core.environment import should_use_secure_cookies, is_development
# Use the utility functions
if is_development():
enable_debug_toolbar()
response.set_cookie(secure=should_use_secure_cookies())
```
**DON'T:**
```python
# Don't manually check environment strings
if os.getenv("ENV") == "production": # ❌ Bad
...
# Don't hardcode environment logic
response.set_cookie(secure=True) # ❌ Won't work in development
```
#### Keep Environment Logic Centralized
If you need custom environment-based behavior:
**Option 1: Add to environment.py**
```python
# app/core/environment.py
def should_enable_caching() -> bool:
"""Determine if caching should be enabled."""
return not is_development()
def get_max_upload_size() -> int:
"""Get maximum upload size based on environment."""
env = get_environment()
if env == "development":
return 10 * 1024 * 1024 # 10MB in dev
elif env == "staging":
return 50 * 1024 * 1024 # 50MB in staging
else:
return 100 * 1024 * 1024 # 100MB in prod
```
**Option 2: Use in your module**
```python
from app.core.environment import is_production
def get_cache_ttl() -> int:
"""Get cache TTL based on environment."""
return 3600 if is_production() else 60 # 1 hour in prod, 1 min in dev
```
### Testing Environment Detection
#### Unit Tests
```python
import os
import pytest
from app.core.environment import get_environment, should_use_secure_cookies
def test_environment_detection_with_env_var():
"""Test environment detection with ENV variable."""
os.environ["ENV"] = "production"
# Clear cache first
import app.core.environment as env_module
env_module._cached_environment = None
assert get_environment() == "production"
assert should_use_secure_cookies() == True
# Cleanup
del os.environ["ENV"]
def test_environment_defaults_to_development():
"""Test that environment defaults to development."""
# Ensure no env vars set
os.environ.pop("ENV", None)
os.environ.pop("ENVIRONMENT", None)
# Clear cache
import app.core.environment as env_module
env_module._cached_environment = None
assert get_environment() == "development"
assert should_use_secure_cookies() == False
```
#### Integration Tests
```python
def test_login_sets_secure_cookie_in_production(test_client, monkeypatch):
"""Test that login sets secure cookie in production."""
# Mock production environment
monkeypatch.setenv("ENV", "production")
# Clear cache
import app.core.environment as env_module
env_module._cached_environment = None
# Test login
response = test_client.post("/api/v1/admin/auth/login", json={
"username": "admin",
"password": "admin123"
})
# Check cookie has secure flag
set_cookie_header = response.headers.get("set-cookie")
assert "Secure" in set_cookie_header
```
### Debugging Environment Detection
#### Print Current Environment
```python
# Add to your startup or debug endpoint
from app.core.environment import get_environment, should_use_secure_cookies
@app.on_event("startup")
async def startup_event():
env = get_environment()
secure = should_use_secure_cookies()
print(f"🌍 Environment: {env}")
print(f"🔒 Secure cookies: {secure}")
print(f"📍 Running on: {os.getenv('HOSTNAME', 'localhost')}")
```
#### Debug Endpoint (Development Only)
```python
from app.core.environment import get_environment, is_development
import os
@router.get("/debug/environment")
def debug_environment():
"""Debug endpoint to check environment detection."""
if not is_development():
raise HTTPException(status_code=404)
return {
"detected_environment": get_environment(),
"should_use_secure_cookies": should_use_secure_cookies(),
"env_var_ENV": os.getenv("ENV"),
"env_var_ENVIRONMENT": os.getenv("ENVIRONMENT"),
"env_var_DEBUG": os.getenv("DEBUG"),
"hostname": os.getenv("HOSTNAME", "unknown"),
}
```
---
## Deployment Guide
### Local Development
**Setup:**
```bash
# Clone repo
git clone <orion-repo>
cd orion-repo
# Create virtual environment
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
# Install dependencies
pip install -r requirements.txt
# Run application (no environment config needed!)
uvicorn main:app --reload
```
**Access:**
- Admin: http://localhost:8000/admin
- Store: http://localhost:8000/store/{code}
- Shop: http://localhost:8000/shop
**Environment:**
- Auto-detected as "development"
- Cookies work with HTTP
- Debug mode enabled
### Staging Deployment
**Docker Compose:**
```yaml
version: '3.8'
services:
web:
build: .
environment:
- ENV=staging
- DATABASE_URL=postgresql://user:pass@db:5432/orion_staging
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_DB=orion_staging
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
```
**Kubernetes:**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: orion-staging
spec:
template:
spec:
containers:
- name: web
image: orion:latest
env:
- name: ENV
value: "staging"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
```
**Requirements:**
- HTTPS enabled (nginx/traefik)
- SSL certificates configured
- Environment variable set: `ENV=staging`
### Production Deployment
**systemd Service:**
```ini
[Unit]
Description=Orion Platform
After=network.target
[Service]
User=orion
WorkingDirectory=/opt/orion
Environment="ENV=production"
Environment="DATABASE_URL=postgresql://user:pass@localhost/orion_prod"
ExecStart=/opt/orion/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
Restart=always
[Install]
WantedBy=multi-user.target
```
**Docker:**
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV ENV=production
ENV PYTHONUNBUFFERED=1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
```
**Requirements:**
- ✅ HTTPS enabled and enforced
- ✅ SSL certificates valid
- ✅ Environment variable: `ENV=production`
- ✅ Database backups configured
- ✅ Monitoring and logging enabled
- ✅ Security headers configured
### Environment Variable Checklist
| Environment | ENV Variable | HTTPS Required | Debug Mode | Cookie Secure |
|-------------|-------------|----------------|------------|---------------|
| Development | Not set (or "development") | ❌ No | ✅ Yes | ❌ No |
| Staging | "staging" | ✅ Yes | ⚠️ Limited | ✅ Yes |
| Production | "production" | ✅ Yes | ❌ No | ✅ Yes |
---
## Testing
### Manual Testing
#### Test Environment Detection
```bash
# Test development (default)
python -c "
from app.core.environment import get_environment, should_use_secure_cookies
print(f'Environment: {get_environment()}')
print(f'Secure cookies: {should_use_secure_cookies()}')
"
# Expected output:
# Environment: development
# Secure cookies: False
```
```bash
# Test production
ENV=production python -c "
from app.core.environment import get_environment, should_use_secure_cookies
print(f'Environment: {get_environment()}')
print(f'Secure cookies: {should_use_secure_cookies()}')
"
# Expected output:
# Environment: production
# Secure cookies: True
```
#### Test Cookie Behavior
**Development:**
```bash
# Start server (development mode)
uvicorn main:app --reload
# Login and check cookie
curl -X POST http://localhost:8000/api/v1/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}' \
-v 2>&1 | grep -i "set-cookie"
# Should see: Set-Cookie: admin_token=...; HttpOnly; SameSite=Lax; Path=/admin
# Should NOT see: Secure flag
```
**Production:**
```bash
# Start server (production mode)
ENV=production uvicorn main:app
# Login and check cookie
curl -X POST https://yourdomain.com/api/v1/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}' \
-v 2>&1 | grep -i "set-cookie"
# Should see: Set-Cookie: admin_token=...; Secure; HttpOnly; SameSite=Lax; Path=/admin
# Should see: Secure flag present
```
### Automated Tests
#### pytest Examples
```python
# tests/test_environment.py
import pytest
import os
from app.core.environment import (
get_environment,
is_development,
is_staging,
is_production,
should_use_secure_cookies
)
@pytest.fixture(autouse=True)
def clear_environment_cache():
"""Clear cached environment before each test."""
import app.core.environment as env_module
env_module._cached_environment = None
yield
env_module._cached_environment = None
class TestEnvironmentDetection:
def test_default_is_development(self):
"""Test that default environment is development."""
# Clear any env vars
os.environ.pop("ENV", None)
os.environ.pop("ENVIRONMENT", None)
assert get_environment() == "development"
assert is_development() == True
assert is_production() == False
assert should_use_secure_cookies() == False
def test_env_variable_production(self, monkeypatch):
"""Test ENV=production detection."""
monkeypatch.setenv("ENV", "production")
assert get_environment() == "production"
assert is_production() == True
assert should_use_secure_cookies() == True
def test_environment_variable_staging(self, monkeypatch):
"""Test ENVIRONMENT=staging detection."""
monkeypatch.setenv("ENVIRONMENT", "staging")
assert get_environment() == "staging"
assert is_staging() == True
assert should_use_secure_cookies() == True
def test_env_takes_priority_over_environment(self, monkeypatch):
"""Test that ENV variable has priority."""
monkeypatch.setenv("ENV", "production")
monkeypatch.setenv("ENVIRONMENT", "staging")
# ENV should win
assert get_environment() == "production"
def test_debug_true_is_development(self, monkeypatch):
"""Test that DEBUG=true results in development."""
monkeypatch.delenv("ENV", raising=False)
monkeypatch.delenv("ENVIRONMENT", raising=False)
monkeypatch.setenv("DEBUG", "true")
assert get_environment() == "development"
class TestCookieSecurity:
def test_secure_cookies_in_production(self, monkeypatch):
"""Test cookies are secure in production."""
monkeypatch.setenv("ENV", "production")
assert should_use_secure_cookies() == True
def test_insecure_cookies_in_development(self):
"""Test cookies are not secure in development."""
os.environ.pop("ENV", None)
assert should_use_secure_cookies() == False
# tests/test_authentication_cookies.py
def test_login_cookie_matches_environment(test_client, monkeypatch):
"""Test that login cookie security matches environment."""
# Test development
monkeypatch.delenv("ENV", raising=False)
response = test_client.post("/api/v1/admin/auth/login", json={
"username": "admin",
"password": "admin123"
})
set_cookie = response.headers.get("set-cookie", "")
assert "Secure" not in set_cookie # No Secure in development
# Test production
monkeypatch.setenv("ENV", "production")
# Clear cache
import app.core.environment as env_module
env_module._cached_environment = None
response = test_client.post("/api/v1/admin/auth/login", json={
"username": "admin",
"password": "admin123"
})
set_cookie = response.headers.get("set-cookie", "")
assert "Secure" in set_cookie # Secure in production
```
---
## Best Practices
### DO ✅
1. **Use the environment utility functions:**
```python
from app.core.environment import should_use_secure_cookies
response.set_cookie(secure=should_use_secure_cookies())
```
2. **Set ENV in production/staging:**
```bash
export ENV=production
```
3. **Use cached version for frequent calls:**
```python
from app.core.environment import get_cached_environment
env = get_cached_environment() # Cached - faster
```
4. **Keep environment logic in environment.py:**
- Add new environment-dependent functions to `environment.py`
- Don't scatter environment checks throughout codebase
5. **Document environment-dependent behavior:**
```python
def send_email(to: str, subject: str):
"""
Send email to recipient.
Environment behavior:
- Development: Logs email to console (no actual send)
- Staging: Sends to test email address
- Production: Sends to actual recipient
"""
if is_development():
logger.info(f"[DEV] Email to {to}: {subject}")
elif is_staging():
actual_to = f"staging+{to}@example.com"
send_via_smtp(actual_to, subject)
else:
send_via_smtp(to, subject)
```
6. **Test with different environments:**
```python
@pytest.mark.parametrize("env", ["development", "staging", "production"])
def test_feature_in_all_environments(env, monkeypatch):
monkeypatch.setenv("ENV", env)
# Clear cache
import app.core.environment as env_module
env_module._cached_environment = None
# Test your feature
```
### DON'T ❌
1. **Don't hardcode environment checks:**
```python
# ❌ Bad
if os.getenv("ENV") == "production":
use_https = True
# ✅ Good
use_https = should_use_secure_cookies()
```
2. **Don't assume environment:**
```python
# ❌ Bad - assumes production
response.set_cookie(secure=True)
# ✅ Good - adapts to environment
response.set_cookie(secure=should_use_secure_cookies())
```
3. **Don't bypass environment detection:**
```python
# ❌ Bad
FORCE_PRODUCTION = True
if FORCE_PRODUCTION:
...
# ✅ Good - use environment variable
# export ENV=production
if is_production():
...
```
4. **Don't mix environment checking methods:**
```python
# ❌ Bad - inconsistent
if os.getenv("ENV") == "prod":
log_level = "WARNING"
elif is_development():
log_level = "DEBUG"
# ✅ Good - consistent
env = get_environment()
if env == "production":
log_level = "WARNING"
elif env == "development":
log_level = "DEBUG"
```
5. **Don't forget to clear cache in tests:**
```python
# ❌ Bad - cache may interfere
def test_production():
os.environ["ENV"] = "production"
assert get_environment() == "production" # May fail if cached
# ✅ Good - clear cache
def test_production():
import app.core.environment as env_module
env_module._cached_environment = None
os.environ["ENV"] = "production"
assert get_environment() == "production"
```
### Security Considerations
1. **Always use HTTPS in production:**
- Environment detection enables `secure=True` for cookies
- But you must configure HTTPS at the server level
2. **Never disable security in production:**
```python
# ❌ NEVER do this
if is_production():
response.set_cookie(secure=False) # Security vulnerability!
```
3. **Validate environment variable values:**
- The system only accepts: "development", "staging", "production"
- Invalid values default to "development" (safe)
4. **Monitor environment in production:**
```python
@app.on_event("startup")
async def check_production_settings():
if is_production():
# Verify production requirements
assert os.getenv("DATABASE_URL"), "DATABASE_URL required in production"
assert os.getenv("SECRET_KEY"), "SECRET_KEY required in production"
logger.info("✅ Production environment verified")
```
---
## Troubleshooting
### Issue: Cookies Not Working
**Symptom:** Authentication cookies not being sent/received
**Check:**
1. **Environment detection:**
```python
from app.core.environment import get_environment, should_use_secure_cookies
print(f"Environment: {get_environment()}")
print(f"Secure cookies: {should_use_secure_cookies()}")
```
2. **Development (HTTP):**
- `should_use_secure_cookies()` should return `False`
- Access via `http://localhost:8000` (not HTTPS)
3. **Production (HTTPS):**
- `should_use_secure_cookies()` should return `True`
- Access via `https://yourdomain.com` (with HTTPS)
- Verify SSL certificate is valid
### Issue: Wrong Environment Detected
**Symptom:** System detects wrong environment
**Solution:**
```bash
# Explicitly set environment
export ENV=production
# Restart application
uvicorn main:app --reload
# Verify
python -c "from app.core.environment import get_environment; print(get_environment())"
```
### Issue: Environment Not Changing
**Symptom:** Environment stuck on old value
**Cause:** Environment is cached
**Solution:**
```python
# Clear cache and re-detect
import app.core.environment as env_module
env_module._cached_environment = None
# Now check again
from app.core.environment import get_environment
print(get_environment())
```
### Issue: Tests Failing Due to Environment
**Symptom:** Tests pass locally but fail in CI/CD
**Solution:** Always clear cache in test fixtures:
```python
@pytest.fixture(autouse=True)
def clear_environment_cache():
"""Clear environment cache before each test."""
import app.core.environment as env_module
env_module._cached_environment = None
yield
env_module._cached_environment = None
```
---
## Summary
### Quick Reference
```python
# Import
from app.core.environment import (
get_environment,
is_development,
is_production,
should_use_secure_cookies
)
# Usage
env = get_environment() # "development" | "staging" | "production"
if is_development():
# Development-only code
pass
if is_production():
# Production-only code
pass
# Cookie security (most common use case)
response.set_cookie(secure=should_use_secure_cookies())
```
### Configuration
| Environment | Set Variable | Cookie Secure | HTTPS Required |
|-------------|--------------|---------------|----------------|
| Development | Not needed (default) | False | No |
| Staging | `ENV=staging` | True | Yes |
| Production | `ENV=production` | True | Yes |
### Key Points
1. ✅ **Development works out of the box** - No configuration needed
2. ✅ **Production requires explicit setting** - Set `ENV=production`
3.**Use utility functions** - Don't check environment directly
4.**HTTPS required in production** - Configure at server level
5.**Test with different environments** - Use monkeypatch in tests
---
## Additional Resources
### Related Documentation
- [Authentication System Documentation](../api/authentication.md)
- [Deployment Guide](../deployment/production.md)
- [Exception Handling](exception-handling.md)
### External References
- [FastAPI Security](https://fastapi.tiangolo.com/tutorial/security/)
- [HTTP Cookies (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
- [12-Factor App: Config](https://12factor.net/config)
---
**Questions?** Contact the backend team or check the main documentation.
**End of Document**