This document describes the boilerplate's controls and the deployment responsibilities it cannot solve generically.
- No real credentials are committed.
.envand variant files are ignored;.env.examplecontains development-only placeholders. - With
DJANGO_DEBUG=false, Django refuses to start with the built-in development secret. - Production secrets must come from a managed secret store or runtime environment, not an image, Compose file, frontend variable, or CI log.
- Allowed hosts, CORS origins, and CSRF trusted origins are explicit lists. Do not use wildcard origins with credentialed requests.
- Django session authentication is used because the production SPA and API are same-origin.
- The session cookie is HTTP-only and
SameSite=Lax.Securedefaults on when debug is disabled; local HTTP explicitly disables it. - JavaScript obtains a CSRF token through
/api/v1/auth/csrf/; every unsafe client operation sendsX-CSRFToken. Registration and login are explicitly CSRF-protected as well. - Production should terminate TLS at a trusted proxy, preserve
X-Forwarded-Proto, enable SSL redirect, secure cookies, and HSTS only after the domain is fully HTTPS-ready. - The Nginx image adds nosniff, frame, referrer, and content-security headers. Its CSP permits only the explicitly configured Google Fonts stylesheet/font hosts in addition to same-origin assets. Google Fonts causes clients to contact a third party; self-host the font files when deployment privacy requirements prohibit that request.
- Contact and sync viewsets always begin with
filter(user=request.user); an object owned by another user resolves as 404. - Creation never accepts an owner from client input.
- The synchronization service receives the authenticated user explicitly and matches contacts only inside that owner.
- Database uniqueness is scoped to
(user, lower(email)), so one user's data neither conflicts with nor reveals another user's contact. - Any future provider or bulk operation must preserve both queryset- and service-level ownership checks. Tests should attempt cross-user list, retrieve, mutate, and import behavior.
- DRF serializers validate all API input; passwords use Django's configured validators.
- Contact email addresses are Unicode-normalized, support SMTPUTF8/EAI local parts, and are constrained case-insensitively in PostgreSQL. A future mail sender must itself support SMTPUTF8; this application only stores contact addresses.
- CSV uploads require an approved MIME type and
.csvextension, are limited to 5 MiB and 10,000 rows, reject null bytes and non-UTF-8 content, and cap individual field lengths. - CSV values are parsed with Python's CSV library and written through Django ORM; there is no SQL string concatenation.
- Spreadsheet-formula content is stored as text and never evaluated. A future CSV export must escape formula prefixes to prevent spreadsheet injection.
- A file with any invalid data row creates no contacts. Database failures roll back the entire contact write set.
- Failed synchronization metadata is persisted after rollback without exposing exception text.
- API errors use
{error: {code, message, fields?, details?}}. Unexpected exceptions return a fixed generic message. - Logs are valid JSON lines with timestamp, severity, logger, request ID, route, status, duration, and authenticated user ID. Code intentionally avoids logging passwords, uploaded rows, session/CSRF values, database URLs, query strings, or request bodies.
/metrics/technicaland/metrics/businesscontain aggregate data without user or email labels. Expose them only to a trusted Prometheus network or protect them at the ingress; application-level authentication is intentionally omitted so standard scrapers can use them.
- API and web runtime containers use non-root users. Dependency installation comes from lockfiles.
- pnpm build scripts are allow-listed only for
esbuildandvue-demi. - Healthchecks cover PostgreSQL, Django plus database connectivity, and Nginx.
- CI has read-only repository permissions, validates generated contracts, and builds images without pushing them.
- For a real deployment, pin base images and GitHub Actions to reviewed immutable digests/SHAs, scan images and dependencies, produce an SBOM, sign images, and define a patch cadence.
- Set a high-entropy secret,
DEBUG=false, exact hosts/origins, secure cookies, TLS redirect, and appropriate HSTS. - Use a least-privilege PostgreSQL role, encrypted connections where required, automated backups, restore tests, connection limits, and separate databases per environment.
- Configure reverse-proxy request/body/time limits consistently with Django's 5 MiB file policy.
- Add rate limiting for auth and upload endpoints, email verification, password reset, Prometheus alert rules, an observability backend, audit events, and retention rules before treating this as a complete product.
- Review privacy, data retention, export, and account-deletion obligations for the deployment region.