feat: Add security hardening, agentic coding infrastructure, and test framework
- Add SECRET_KEY and ENCRYPTION_KEY validation on startup - Implement security headers middleware (X-Frame-Options, CSP, HSTS) - Add CSRF protection middleware - Create comprehensive GitHub issue templates and PR template - Add Makefile with common development tasks - Configure pre-commit hooks (black, ruff, mypy, bandit, detect-secrets) - Create docs/CODING_PATTERNS.md with best practices - Create docs/ERRORS.md documenting all error codes - Add Architecture Decision Records (ADR) for Celery and Fernet encryption - Create CHANGELOG.md for version tracking - Set up pytest test infrastructure with fixtures and factories - Add sample unit tests for security and config validation - Create CI/CD workflows (test, lint, security) - Add comprehensive TODO.md with milestones and progress tracking Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -92,6 +92,50 @@ class Settings(BaseSettings):
|
||||
if isinstance(v, str):
|
||||
return [i.strip() for i in v.split(",")]
|
||||
return v
|
||||
|
||||
@field_validator("SECRET_KEY")
|
||||
@classmethod
|
||||
def validate_secret_key(cls, v: str) -> str:
|
||||
"""Validate that SECRET_KEY is changed from default and is secure"""
|
||||
default_keys = [
|
||||
"change-this-to-a-secure-random-secret-key-in-production",
|
||||
"secret",
|
||||
"secret-key",
|
||||
"secretkey",
|
||||
]
|
||||
if v.lower() in default_keys:
|
||||
raise ValueError(
|
||||
"SECRET_KEY must be changed from default value! "
|
||||
"Generate a secure key with: python -c 'import secrets; print(secrets.token_urlsafe(32))'"
|
||||
)
|
||||
if len(v) < 32:
|
||||
raise ValueError(
|
||||
f"SECRET_KEY must be at least 32 characters long (current: {len(v)}). "
|
||||
"Generate a secure key with: python -c 'import secrets; print(secrets.token_urlsafe(32))'"
|
||||
)
|
||||
return v
|
||||
|
||||
@field_validator("ENCRYPTION_KEY")
|
||||
@classmethod
|
||||
def validate_encryption_key(cls, v: str) -> str:
|
||||
"""Validate that ENCRYPTION_KEY is changed from default and is secure"""
|
||||
default_keys = [
|
||||
"change-this-to-a-secure-encryption-key",
|
||||
"encryption",
|
||||
"encryption-key",
|
||||
"encryptionkey",
|
||||
]
|
||||
if v.lower() in default_keys:
|
||||
raise ValueError(
|
||||
"ENCRYPTION_KEY must be changed from default value! "
|
||||
"Generate a secure key with: python -c 'import secrets; print(secrets.token_urlsafe(32))'"
|
||||
)
|
||||
if len(v) < 32:
|
||||
raise ValueError(
|
||||
f"ENCRYPTION_KEY must be at least 32 characters long (current: {len(v)}). "
|
||||
"Generate a secure key with: python -c 'import secrets; print(secrets.token_urlsafe(32))'"
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# Global settings instance
|
||||
|
||||
Reference in New Issue
Block a user