Files
joshuaandClaude Opus 5.5 a1ecbb9617 POPIA toolkit part 3: retention, breach register, readiness
- Retention policies (Admin -> Privacy -> Retention) applied by a nightly
  `retention` job: inactive accounts anonymised after 5 years with a
  30-day warning (on by default; never staff roles or people with an
  upcoming registration), form answers, login history, payer details in
  payment notifications, audit/access logs
- User.lastLoginAt (set on login, backfilled) and inactivityWarnedAt
- Breach register (SecurityBreach) with drafts for the people affected
  and the Information Regulator
- Readiness checklist with a score
- Children's/medical flag in the access log; {retention} placeholder in
  the privacy notice
- Unit tests (retention.test.js), e2e (privacy-retention.spec.ts); docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mt6TCv85T9VKRq3cV7rXq
2026-10-23 20:25:58 +02:00

98 lines
6.2 KiB
Bash

# ─── Database ────────────────────────────────────────────────────────────────
DATABASE_URL="postgresql://username:password@localhost:5432/hope_events"
# ─── Auth ─────────────────────────────────────────────────────────────────────
JWT_SECRET=your_jwt_secret_here_minimum_32_characters
# Two-factor authentication is required for admins and supervisors whenever
# email (SMTP) or WhatsApp can deliver a code. Set to false only as an emergency
# switch, e.g. if the mail server is down and admins are locked out.
# TWO_FACTOR_REQUIRED_ROLES=true
# ─── Server ───────────────────────────────────────────────────────────────────
PORT=5000
NODE_ENV=development
# Set this if the app runs behind a reverse proxy (e.g. nginx on a separate
# server) so rate limiting reads the real client IP instead of the proxy's.
# Accepts a hop count ("1"), "true"/"false", or comma-separated IP(s)/CIDR(s)
# of your trusted proxy (e.g. "10.0.0.5" or "10.0.0.0/8"). Leave unset if the
# app is not behind a proxy.
# TRUST_PROXY=1
# ─── CORS ─────────────────────────────────────────────────────────────────────
# Comma-separated list of allowed frontend origins
FRONTEND_URL=http://localhost:3000
# ─── Email (SMTP) — optional fallbacks ───────────────────────────────────────
# Preferred: configure SMTP via Admin → Site Settings (stored AES-256 encrypted).
# These env vars are used as fallbacks if no SMTP settings are saved in the DB.
# EMAIL_HOST=smtp.example.com
# EMAIL_PORT=587
# EMAIL_USER=your_email@example.com
# EMAIL_PASS=your_email_password
# EMAIL_FROM=no-reply@example.com
# ─── Payments (Yoco) — optional fallbacks ─────────────────────────────────────
# Preferred: set the secret key and generate the webhook in Admin → Site Settings →
# Yoco (stored AES-256 encrypted). These are only used if the database has no value.
# YOCO_SECRET_KEY=sk_test_...
# YOCO_WEBHOOK_SECRET=whsec_...
# ─── Payments (PayFast) — optional fallbacks ──────────────────────────────────
# Preferred: Admin → Site Settings → Payments → PayFast. Only used if the database has no value.
# PAYFAST_MERCHANT_ID=
# PAYFAST_MERCHANT_KEY=
# PAYFAST_PASSPHRASE=
# PAYFAST_MODE=sandbox
# PayFast notifications (ITNs) must come from a PayFast address. Behind a reverse proxy, set
# TRUST_PROXY so the real address is seen. Only for testing through a tunnel:
# PAYFAST_SKIP_IP_CHECK=true
# ─── Public URLs ──────────────────────────────────────────────────────────────
# Used to build links in emails (password reset, activation, etc.)
APP_BASE_URL=https://your-frontend-domain.com
# Used to serve ticket PDFs to WhatsApp (must be publicly reachable)
BACKEND_URL=https://your-backend-domain.com
# ─── WhatsApp (WAWP) — optional, preferred stored via Admin → Site Settings ───
# These are env-var fallbacks. Use the admin panel to manage them at runtime.
WAWP_ACCESS_TOKEN=your_wawp_access_token
WAWP_INSTANCE_ID=your_wawp_instance_id
# ─── Background workers ───────────────────────────────────────────────────────
DAILY_SUMMARY_ENABLED=true
SCHEDULED_EMAILS_ENABLED=true
SCHEDULED_EMAILS_INTERVAL_MS=30000
# Daily 09:00 parental-consent job: reminders, and deleting medical details after events
CONSENT_JOBS_ENABLED=true
# Waitlist: expire unclaimed offers and offer freed places (every 10 minutes by default)
WAITLIST_JOB_ENABLED=true
# WAITLIST_JOB_INTERVAL_MS=600000
# Payments: every 15 minutes, look up PayFast checkouts whose notification never arrived
PAYMENT_STATUS_JOB_ENABLED=true
# Privacy (POPIA): daily 08:00 reminder to admins of data requests due within a week
PRIVACY_JOBS_ENABLED=true
# Privacy (POPIA): nightly 03:30 retention job (Admin → Privacy → Retention). Note: inactive
# accounts are anonymised after 5 years by default (with a warning 30 days before).
RETENTION_JOBS_ENABLED=true
# Nightly database backup at 02:00 (requires the `pg_dump` binary on this host).
# Retention count is set via Admin → Site Settings → Backups (default 14).
BACKUP_ENABLED=true
# ─── Error monitoring (Sentry) — optional ─────────────────────────────────────
# Leave unset to disable entirely (a no-op, not an error). Set NEXT_PUBLIC_SENTRY_DSN
# in frontend/.env too if you want frontend errors captured.
# SENTRY_DSN=https://xxxxx@oxxxxxx.ingest.sentry.io/xxxxx
# ─── Note ─────────────────────────────────────────────────────────────────────
# The following are managed via Admin → Site Settings and stored in the database:
# - Organisation name, tagline, contact details, branding colour, logo
# - Registration notification emails
# - SMTP settings (username and password stored AES-256-GCM encrypted, key
# derived from JWT_SECRET — do not change JWT_SECRET after saving SMTP creds)
# - Yoco secret key and webhook secret (encrypted the same way)
# - Legal page content (operator name, Information Officer, website URL, etc.)
# The first-time setup wizard handles initial configuration on fresh deployments.
# You no longer need ORG_NAME, ORG_TAGLINE, EMAIL_HEADER_COLOR, REGISTRATIONS_EMAIL,
# or SMTP vars in this file (they still work as fallbacks if the DB entry is absent).