Back to docs hub·docs/ops/32-production-security-checklist.md
Reference document

32 Production Security Checklist

Last updated May 7, 2026

32 Production Security Checklist

Purpose

Comprehensive security checklist derived from December 2024 security audit. This document tracks security requirements for production deployment and paid subscription launch.

Security Audit Summary (Dec 2024)

Overall Assessment: B+ (Very Good)

The app has excellent authentication, authorization, and input validation. Main gaps are operational (CSP, session management, audit logs) rather than fundamental flaws.


Critical (Must Fix Before Any Production Deploy)

✅ 1. HTTPS Enforcement

  • Status: Ready for production
  • Requirements:
    • Set COOKIE_SECURE=true in production environment
    • Set NODE_ENV=production on hosting platform
    • Verify TLS certificate is active
  • Testing: Confirm auth cookies have Secure flag in browser DevTools
  • Render Config: Platform provides auto-SSL, just set env vars

✅ 2. Strong Secret Generation

  • Status: Template updated with instructions
  • Requirements:
    • Generate JWT_ACCESS_SECRET with 48+ bytes entropy
    • Generate JWT_REFRESH_SECRET with 48+ bytes entropy (different from access)
    • Use: openssl rand -base64 48
  • Testing: Secrets should be different and 64+ characters
  • Rotation: Every 90 days or on suspected compromise

✅ 3. Database Connection Security

  • Status: Documentation updated
  • Requirements:
    • Add ?sslmode=require to production DATABASE_URL
    • Verify SSL/TLS enforcement in provider settings
  • Testing: Check Postgres logs for encrypted connections
  • Note: Most managed Postgres (Render, Supabase, etc.) enforce SSL by default

✅ 4. Environment Variable Validation

  • Status: ✅ Complete
  • Requirements:
    • Validate all required env vars on startup
    • Fail fast with clear error messages
    • Check format/type (URLs, ports, etc.)
  • Testing: Start app with missing vars, should exit with helpful error
  • Implementation: EnvValidationService in backend/src/common/config/
  • Completed: Dec 30, 2024

High Priority (Before Public Beta)

✅ 5. Content Security Policy (CSP)

  • Status: ✅ Complete
  • Requirements:
    • Configure CSP headers for frontend pages
    • Allow Next.js runtime and framework scripts
    • Restrict inline scripts and unsafe-eval
    • Block unauthorized external resources
  • Testing: Run Chrome Lighthouse security audit, check browser console for CSP violations
  • Implementation:
    • Frontend: CSP headers configured in next.config.ts
    • Backend: Additional security headers via Helmet.js in app.setup.ts
  • Features:
    • Environment-aware CSP (stricter in production)
    • Whitelists API origin for fetch requests
    • Allows HTTPS images for S3 uploads
    • Blocks framing (X-Frame-Options: DENY)
    • Referrer policy: strict-origin-when-cross-origin
    • Permissions policy: blocks camera, microphone, geolocation
  • Security Headers:
    • Content-Security-Policy - Restricts resource loading
    • X-Frame-Options: DENY - Prevents clickjacking
    • X-Content-Type-Options: nosniff - Prevents MIME-sniffing
    • Referrer-Policy - Controls referrer information
    • Permissions-Policy - Disables unnecessary browser features
    • Strict-Transport-Security (backend) - Enforces HTTPS
  • CSP Directives:
    • default-src 'self' - Only allow same-origin resources
    • script-src - Allows Next.js inline scripts (required for framework)
    • style-src - Allows inline styles (required for CSS-in-JS)
    • img-src - Allows data:, blob:, and https: for uploads
    • connect-src - Whitelists API backend origin
    • frame-ancestors 'none' - Prevents all embedding
    • upgrade-insecure-requests - Auto-upgrades HTTP to HTTPS (production only)
  • Note: Next.js requires 'unsafe-inline' for scripts due to framework architecture. For stricter CSP, consider migrating to nonce-based approach in future.
  • Completed: Dec 30, 2024

✅ 6. Optional Redis Rate Limiting Adapter

  • Status: ✅ Complete as an optional adapter; Redis is not required for the no-Redis paid-launch path
  • Requirements:
    • Keep @nestjs/throttler active for global and auth buckets
    • Use the Redis storage adapter only when Redis is intentionally provisioned
    • Fall back to process-local counters when Redis is absent
  • Testing: pnpm --dir backend exec jest src/common/throttler/redis-throttler-storage.spec.ts --runInBand proves the optional adapter's in-memory fallback honors Nest's millisecond TTL contract, and pnpm --dir backend test:e2e -- rate-limits.e2e-spec.ts proves app-layer 429 responses for password reset, checkout creation, and checkout confirmation without live Stripe calls. If Redis is intentionally provisioned later, restart API during a rate limit period and verify limits persist.
  • Staging evidence: After commit 328ae1f deployed on 2026-05-05, a disposable password-reset probe showed auth bucket remaining_auth decrementing from 4 to 0 with reset_auth around 60000 ms, then HTTP 429 with retry_after_auth=60000 on request 6.
  • Implementation: RedisThrottlerStorage in backend/src/common/throttler/
  • Features:
    • Automatic fallback to in-memory when Redis unavailable
    • Reconnection logic with exponential backoff
    • Graceful degradation without service interruption
  • Launch note: App-layer throttles now cover auth and checkout explicitly; provider-edge/WAF proof is recorded in item 6a as a current-provider limitation and MVP owner decision.
  • Completed: Dec 30, 2024

✅ 6a. Provider Edge/WAF Rate-Limit Posture

  • Status: Complete for the single-instance MVP launch path as a documented provider limitation and owner decision.
  • Current provider evidence (2026-05-07):
    • dokodo.app authoritative nameservers are Porkbun (fortaleza.ns.porkbun.com, salvador.ns.porkbun.com, maceio.ns.porkbun.com, curitiba.ns.porkbun.com).
    • api.staging.dokodo.app responses show Render's managed Cloudflare-backed edge (server: cloudflare, x-render-origin-server: Render, rndr-id present), plus app-layer rate-limit headers.
    • render.yaml defines Render web services and custom domains but no WAF or path-based rate-limit rules.
    • Render's public Blueprint/custom-domain documentation exposes managed DDoS protection, custom domains, and inbound IP rules; it does not expose customer-configurable path-based WAF/rate-limit rules for the current starter web-service setup.
  • Launch decision: Do not add a user-managed WAF solely for the MVP paid launch. App-layer throttles, Postgres-backed failed-login lockouts, single API instance semantics, and Render managed DDoS protection are sufficient for launch risk. Kevin Maurer owns this acceptance until the team expands.
  • Hard guardrail: Do not add multiple API instances, autoscaling, or multi-region API routing until one of these is in place: Redis/shared distributed throttler counters, a user-managed WAF/reverse proxy with path-based rate limits, or a new host plan with equivalent customer-configurable controls.
  • Future WAF rule scope: If Cloudflare or another managed WAF is added, configure path-based rules for POST /api/v1/auth/login, POST /api/v1/auth/register, POST /api/v1/auth/password/forgot, POST /api/v1/auth/password/reset, POST /api/v1/auth/2fa/challenge, POST /api/v1/payments/checkout-sessions, and POST /api/v1/payments/checkout-sessions/confirm. Keep /api/v1/payments/webhooks/stripe outside challenge/block rate-limit rules so Stripe retries and signature verification remain reliable.
  • Recommended future thresholds: grouped auth entry paths no looser than 20 requests/minute per IP at the edge; checkout creation/confirmation no looser than 20 requests/minute per IP at the edge, with the app retaining stricter per-route limits.
  • Evidence required if WAF is added later: rule IDs or exported ruleset JSON, screenshot or audit event showing the rule is enabled on api.dokodo.app, safe staging/prod-like 429 or challenge proof, and confirmation Stripe webhooks are excluded.

✅ 7. Password Strength Requirements

  • Status: ✅ Complete
  • Requirements:
    • Minimum 10 characters
    • Require mixed case, number, special character
    • Show password strength meter in UI
  • Testing: Try weak passwords, verify rejection with helpful feedback
  • Implementation:
    • Backend: IsStrongPassword validator in backend/src/common/validators/
    • Frontend: Real-time strength meter in registration form
    • Endpoint: POST /auth/password-strength for client-side validation
  • Features:
    • 5-level strength scoring system
    • Pattern detection (sequential, common passwords)
    • Clear visual feedback with checkmarks
    • Progressive disclosure on password field focus
  • Completed: Dec 30, 2024

✅ 8. Session Management UI

  • Status: ✅ Complete (MVP)
  • Requirements:
    • Endpoint to list active refresh tokens
    • Revoke current session
    • UI to view and manage sessions
  • Testing: Login, view sessions page, revoke session
  • Implementation:
    • Backend: SessionService in backend/src/auth/
    • Endpoints: GET /auth/sessions, DELETE /auth/sessions/current, DELETE /auth/sessions/:sessionId
    • Frontend: /dashboard/settings/sessions page
  • Features:
    • List active persisted refresh-token sessions with browser, device, IP hint, and token reference metadata
    • Show issue time, last-used time, and expiration
    • Mark current session
    • Revoke the selected session directly from its row
    • Explicit loading, retryable error, and empty states so session review does not fail silently
  • Future Enhancements:
    • Email notification on new device login
    • Revoke all sessions except current
  • Completed: Dec 30, 2024

✅ 9. Audit Logging

  • Status: ✅ Complete
  • Requirements:
    • Log: account deletion, password changes, item deletion, location deletion
    • Include: userId, timestamp, IP, user agent, old/new values
    • Retention: 90 days minimum
    • Storage: Separate audit table (AuditLog)
  • Testing: Trigger each event, verify log entry in database
  • Implementation:
    • Service: AuditLogService in backend/src/common/audit/
    • Database: AuditLog model in Prisma schema
    • Integration: Auth, Items, Locations services
  • Features:
    • Automatic IP extraction (handles X-Forwarded-For, X-Real-IP)
    • Non-blocking audit writes (errors don't fail main operation)
    • Query methods for user/entity audit history
    • Cleanup method for 90-day retention
  • Logged Actions:
    • ACCOUNT_DELETED - User account deletion with email
    • PASSWORD_CHANGED - Password change events
    • ITEM_DELETED - Item deletion with name, location, tags
    • LOCATION_DELETED - Location deletion with name, parent
  • Future Enhancements:
    • Scheduled cron job for automated cleanup (every 30 days)
    • User-facing audit log viewer in settings
    • Export audit logs for compliance requests
    • Failed login attempt tracking
  • Compliance: Satisfies SOC2, GDPR data subject request requirements
  • Completed: Dec 30, 2024

⏳ 10. File Upload Scanning

  • Status: Not implemented
  • Requirements:
    • Integrate malware scanning (ClamAV, AWS Macie, Cloudflare)
    • Scan before confirming upload
    • Quarantine flagged files
    • Alert user on malicious upload attempt
  • Testing: Upload EICAR test file, verify rejection
  • Cost: Evaluate hosted scanning vs self-hosted

Medium Priority (Nice to Have)

11. Request ID Headers

  • Implementation: Add X-Request-ID to response headers
  • Benefit: User support can trace specific requests

✅ 12. Persistent Brute Force Detection

  • Status: ✅ Complete
  • Implementation: Track failed logins per email and IP in Postgres so launch security does not depend on Redis
  • Benefit: Detect distributed attacks across IPs with durable state

✅ 13. Two-Factor Authentication (2FA)

  • Status: ✅ Complete
  • Implementation:
    • Prisma: Added twoFactor* fields on User plus TwoFactorChallenge table for pending logins
    • Service: TwoFactorService (Nest provider) using otplib for TOTP and SHA-256 hashed recovery codes
    • Endpoints: /auth/2fa/setup, /auth/2fa/verify, /auth/2fa/status, /auth/2fa/recovery-codes, /auth/2fa/disable, and /auth/2fa/challenge
    • Frontend: Login flow with challenge UI + settings page for setup, disable, and code regeneration with QR preview
  • Benefit: Required for premium/work accounts; mitigates credential stuffing even after password disclosure
  • Testing:
    • Enrol new user via /settings/security and confirm authenticator + recovery code download
    • Attempt login to ensure challenge is required, verify both TOTP and recovery code paths
    • Disable 2FA using password + code; confirm refresh tokens revoked and audit logs written

14. API Versioning Strategy

  • Documentation: Define deprecation timeline (maintain v1 for 6+ months)
  • Benefit: Safe breaking changes in future

15. Dependency Vulnerability Scanning

  • Implementation: GitHub Dependabot, Snyk, or pnpm audit in CI
  • Benefit: Automated security patch alerts

16. Enhanced Security Headers

  • Implementation: Add X-Frame-Options, Referrer-Policy, Permissions-Policy
  • Benefit: Defense in depth

For Paid Launch (Business Requirements)

✅ 17. Email Verification

  • Status: ✅ Complete
  • Requirements:
    • Send verification link on registration
    • Prevent throwaway accounts
    • Allow login but show banner until verified
  • Implementation:
    • Database: Added emailVerified, verificationToken, verificationTokenExpiry to User model
    • Service: EmailService in backend/src/common/email/
    • Endpoints: POST /auth/verify-email, POST /auth/resend-verification
    • Frontend: Verification page at /auth/verify-email
  • Features:
    • 24-hour token expiry
    • Secure random token generation (32 bytes hex)
    • Email templates with HTML/text versions
    • Resend verification with rate limiting (3/min)
    • Visual banner for unverified users
  • Email Service:
    • Development: Logs to console
    • Production: Ready for SendGrid/Mailgun/AWS SES/Resend integration
    • Configurable via EMAIL_FROM and FRONTEND_URL env vars
  • Testing: Register new account, check logs for verification link, verify token works
  • UX: Users can use app while unverified, banner prompts verification
  • Completed: Dec 30, 2024

✅ 18. Account Takeover Protection

  • Status: ✅ Complete
  • Requirements:
    • Revoke all active sessions on password change
    • Prevent attackers from maintaining access after user secures account
  • Implementation:
    • Database: RefreshToken table with tokenHash, expiresAt, lastUsedAt, ipAddress, userAgent
    • Service: Token validation in refresh flow against database
    • Automatic revocation: All refresh tokens deleted on password change
  • Features:
    • Refresh tokens stored in database (not just JWT)
    • SHA-256 hashing of tokens for secure storage
    • Token validation on every refresh request
    • Automatic cleanup of expired tokens
    • IP address and user agent tracking for sessions
  • Security:
    • After password change, all other devices/browsers logged out
    • Tokens validated against database (can't be used if revoked)
    • Expired tokens automatically deleted on refresh attempt
  • Testing: Change password in one browser, verify other sessions logged out
  • Completed: Dec 30, 2024

19. Payment Integration Security

  • Provider: Stripe or Paddle (PCI DSS compliant)
  • Never Store: Credit card numbers, CVV
  • Required:
    • Webhook signature verification
    • Idempotency keys for charges
    • Subscription state machine
    • Refund audit trail
  • Testing: Test mode transactions, webhook replays
  • Status: To be implemented

20. Legal & Compliance

  • Required Documents:
    • Privacy Policy (GDPR/CCPA compliant)
    • Terms of Service
    • Cookie Policy (EU users)
  • Required Features:
    • Data export (JSON download)
    • Complete account deletion (DB + S3 cleanup)
    • Cookie consent banner (EU)
  • Timeline: Complete before accepting payments

Pre-Deploy Checklist

Environment Setup

  • Generate production JWT secrets (48+ bytes, unique per env)
  • Set NODE_ENV=production
  • Set COOKIE_SECURE=true
  • Configure FRONTEND_ORIGIN with production domain(s)
  • Add ?sslmode=require to DATABASE_URL
  • Verify S3 bucket is private (no public read)
  • Configure proper IAM permissions for S3 access
  • Set up Redis with TLS enabled
  • Add startup validation for all required env vars

Monitoring & Logging

  • Configure error tracking (Sentry, Rollbar, etc.)
  • Set up structured log aggregation (Papertrail, Loggly, CloudWatch)
  • Create uptime monitoring (Pingdom, UptimeRobot)
  • Set up database backups (daily, 30-day retention)
  • Configure alerts for API errors, slow queries, high memory

Security Validation

  • Run pnpm audit in backend and frontend
  • Fix all critical and high vulnerabilities
  • Test CORS with production frontend origin
  • Verify CSRF token exchange works
  • Test file upload with max size limit
  • Confirm rate limiting blocks excessive requests
  • Test authentication flow (register, login, refresh, logout)
  • Verify password hashing with bcrypt cost 12

Staging Environment

  • Deploy to staging with production-like config
  • Run full E2E test suite
  • Manual QA on mobile devices
  • Load test with k6 or Artillery
  • Check browser console for CSP violations
  • Verify analytics events firing correctly

Pre-Paid Launch Checklist

Legal Foundation

  • Privacy policy drafted and reviewed
  • Terms of service drafted and reviewed
  • Cookie consent banner implemented
  • GDPR data subject request process documented

Payment Infrastructure

  • Stripe/Paddle account created
  • Webhook endpoints secured with signature verification
  • Test subscription flow (create, update, cancel)
  • Refund process documented
  • Failed payment retry logic implemented

Enhanced Security

  • Email verification flow complete
  • Password strength requirements enforced
  • Session management UI implemented
  • Audit logging capturing all sensitive actions
  • 2FA available for premium users (optional but recommended)

Data Protection

  • Data export feature tested
  • Account deletion removes all data (DB + S3)
  • Backup restoration tested
  • Encryption at rest verified for database

Ongoing Maintenance Schedule

Weekly

  • Review dependency updates (Dependabot PRs)
  • Check error tracking for new patterns
  • Monitor rate limit violations

Monthly

  • Review audit logs for anomalies
  • Update security documentation
  • Check for new CVEs in dependencies
  • Test backup restoration

Quarterly

  • Rotate JWT secrets in production
  • Review and update privacy policy
  • Penetration testing (self-service or external)
  • Review user feedback for security concerns

Annually

  • External security audit
  • Compliance review (GDPR, CCPA, SOC2 if applicable)
  • Disaster recovery drill

Incident Response Plan

Detection

  • Monitor error tracking for auth failures
  • Alert on unusual login patterns
  • Watch for sudden traffic spikes

Response Steps

  1. Confirm incident (false positive check)
  2. Assess scope (affected users, data exposure)
  3. Contain threat (revoke tokens, block IPs)
  4. Investigate root cause
  5. Remediate vulnerability
  6. Notify affected users (if data breach)
  7. Document lessons learned

Communication Templates

  • User notification email (data breach)
  • Status page update (service disruption)
  • Post-mortem report (internal)

Current Status Summary

Ready for Free/Beta Deploy:

  • Strong foundation with JWT auth, CSRF protection, input validation
  • App-layer auth and checkout throttles are implemented and locally proven
  • Provider-edge/WAF limitation is documented for the current Render/Porkbun stack

Ready for Paid Launch:

  • All High Priority items (5-10) complete
  • Legal documents published
  • Payment integration tested
  • Audit logging operational
  • Remaining launch-hardening evidence is now outside rate limiting: monitoring, support/status routing, backup restore drill, and final hosted billing gaps

Target Timelines:

  • Beta launch: 1-2 weeks (Critical + items 4-6)
  • Paid launch: 4-6 weeks (all High Priority + Legal + Payment)

Decisions (Locked)

  • Use managed hosting (Render) with auto-SSL for initial launch
  • Prioritize session management over 2FA for MVP
  • Start with Stripe for payment processing
  • Maintain audit logs in Postgres for first year (evaluate external service later)
  • Defer CSP to post-beta (track separately)