If you discover a security vulnerability, please report it responsibly:
- Do NOT open a public GitHub issue
- Email the maintainer directly or use GitHub's private vulnerability reporting
- Include a description, steps to reproduce, and potential impact
| Version | Supported |
|---|---|
| 0.1.x | Yes |
- Authentication: JWT with refresh tokens (djangorestframework-simplejwt)
- Authorization: RBAC with permission codenames, data scope isolation
- Tenant Isolation: Row-level tenant filtering in the view layer via
apps/core/tenant.py::scope_to_tenant(every ViewSet is pinned to it by the meta-test intests/test_tenant_scoping_contract.py).TenantManagerfilters soft deletes only; it does not isolate tenants. - Audit Trail: All mutations logged via AuditLog signals
- Dependency Scanning:
pip-audit --strict --desc -r requirements.txtandnpm audit --audit-level=highinci.yml; both block, and neither iscontinue-on-error. Neither runs on its own: both workflows areworkflow_dispatch-only (GitHub Actions quota exhausted), andsecurity.yml's weekly cron is off. A scan happens when somebody starts it. - Sentry: Error tracking with PII masking
- Encryption at rest: Fernet for
WebhookConfig.signing_secretandDeathRegistrationRequest.source_payload, keyed byENCRYPTION_KEY. WithDEBUG=Falseand no key the process refuses to start; withDEBUG=Trueand no key it warns and stores both columns in plaintext.
Never commit .env files. Use .env.example as a template.
Required for production (DEBUG=False; config/settings.py refuses to start
without each of these):
SECRET_KEY— Django secret key (min 32 chars)ALLOWED_HOSTS— comma-separated host listDATABASE_URL— PostgreSQL connection string (SQLite is refused)ENCRYPTION_KEY— Fernet key for the encrypted columns above
Optional (missing only produces a warning):
REDIS_URL— Redis connection string (defaults toredis://localhost:6379/0)SENTRY_DSN— Sentry error tracking DSN