geocrop-platform./apps/nextgen/.env.example

139 lines
7.2 KiB
Plaintext

# ────────────────────────────────────────────────────────────────────────
# Africa Alert PWA — environment configuration template
# ────────────────────────────────────────────────────────────────────────
#
# Copy this file to `.env` at the repo root and fill in real values.
# `.env` is gitignored; never commit secrets.
#
# Dev: `node server/src/index.js` loads `.env` from the server cwd
# automatically (see server/src/index.js for the loader).
# Prod: load .env via your orchestrator (Docker, systemd, k8s secret).
#
# `server/src/config/index.js` is the single source of truth for which
# vars are required. The server exits non-zero on startup if a required
# var is missing in production. See `.harness/docs/conventions.md` for
# the environment contract.
# ─── Node / runtime ────────────────────────────────────────────────────
NODE_ENV=development
PORT=3001
DB_PATH=./data/school.db
# ─── Auth (REQUIRED in production) ─────────────────────────────────────
# HMAC secret for JWT signing/verification.
# Generate with: node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
JWT_SECRET=replace-me-with-64-byte-hex
# Comma-separated CORS allow-list. NO wildcard allowed in production.
ALLOWED_ORIGINS=http://localhost:3000
# When true, /api/auth/login response includes `offline_jwt_secret` so the
# client can mint JWTs while offline. Must be 'true' or 'false'.
ALLOW_CLIENT_OFFLINE_MINT=true
# ─── Paynow (Zimbabwean payment gateway) ────────────────────────────────
# Credentials are issued at https://www.paynow.co.zw after registering an
# integration. PAYNOW_INTEGRATION_KEY signs outbound requests AND inbound
# webhooks — keep it secret.
PAYNOW_INTEGRATION_ID=
PAYNOW_INTEGRATION_KEY=
# Where Paynow should send status updates and where users land after pay.
PAYNOW_RETURN_URL=http://localhost:3000/fees
PAYNOW_BLOCKING_URL=http://localhost:3000/api/payments/webhook
# Set to 'true' ONLY for local dev and Playwright tests that simulate
# Paynow and need to hit the webhook without a real signature. In
# production leave unset — webhook signature verification is enforced.
# PAYNOW_SKIP_VERIFY=false
# ─── Supabase (optional — sync is no-op when empty) ───────────────────
# Server-side credentials. The sync engine skips when SUPABASE_KEY is empty.
SUPABASE_URL=
SUPABASE_KEY=
# Same values exposed to the client bundle. The PWA reads these at build
# time via Vite's import.meta.env (only VITE_-prefixed vars are inlined).
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=
# ─── SMTP (optional — password recovery emails) ────────────────────────
# When SMTP_HOST is unset, EmailService falls back to Ethersoft preview
# mode (dev only). In production set SMTP_HOST to send real mail.
SMTP_HOST=
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=
SMTP_PASS=
SMTP_FROM="NextGen Support <support@nextgen.edu>"
# ─── Sync tuning ───────────────────────────────────────────────────────
# Override the default 30s sync interval (in seconds). Empty = default.
# SYNC_INTERVAL=30
# ─── Port allocation ───────────────────────────────────────────────────
# See PORTS.md for the canonical port plan. Defaults are non-colliding
# so tenant + superadmin can run side-by-side.
#
# Tenant stack:
PORT=3001 # tenant API (server/src/config/index.js)
VITE_PORT=3000 # tenant client Vite (client/vite.config.ts)
VITE_API_TARGET=http://127.0.0.1:3001
VITE_WS_TARGET=ws://127.0.0.1:3001
#
# SuperAdmin stack:
SUPERADMIN_PORT=3002 # SuperAdmin API (superadmin/server/src/index.js)
# SuperAdmin client Vite uses VITE_PORT=3003 — set it in superadmin/client/.env
#
# Tenant → SuperAdmin JWKS (only SuperAdmin exposes JWKS; default is the
# dev-proxy path; override to a full URL for cross-origin in prod).
VITE_SUPERADMIN_JWKS_URL=/api/v1/auth/jwks
# ─── SuperAdmin licensing (ed25519 trust anchor + heartbeat) ──────────────
# Placeholder — replace with the matching SuperAdmin public key.
SUPERADMIN_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAGB9...REPLACE_ME...\n-----END PUBLIC KEY-----
VITE_SUPERADMIN_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAGB9...REPLACE_ME...\n-----END PUBLIC KEY-----
SUPERADMIN_HEARTBEAT_URL=
LICENSE_HEARTBEAT_INTERVAL_MS=300000
LICENSE_CLOCK_DRIFT_MS=300000
# Optional — service auto-detects absence and uses LRU cache only.
REDIS_URL=
# ─── Weekly Government Push (Monday 06:00 server local time) ────────────
# Pushes the weekly Ministry-style aggregate report
# (GET /api/reports/weekly payload) to one or more government endpoints.
# See server/src/services/WeeklyGovPushService.js for the cron logic.
#
# The four values below (URLS, AUTH, HMAC_SECRET, SCHOOL_ID) are
# DEFAULTS. Admins can override them at runtime via
# Settings → API & Integrations → Ministry Reporting, which writes to
# the system_settings table; DB values take precedence when set.
#
# Set to 0 to disable the cron entirely (kill switch); default is enabled.
WEEKLY_GOV_PUSH=1
# Comma-separated target URLs. Replace with real endpoints.
WEEKLY_GOV_PUSH_URLS=https://mopse.gov.zw/api/v1/weekly,https://placeholder.example.gov.zw/api/v1/weekly
# Full Authorization header value (e.g. "Bearer xxx"). If empty, no auth header is sent.
WEEKLY_GOV_PUSH_AUTH=Bearer change-me-to-real-token
# Optional HMAC-SHA256 secret — if set, the body is signed and sent as X-Signature: sha256=<hex>.
WEEKLY_GOV_PUSH_HMAC_SECRET=
# Per-request timeout in ms (default 15000).
WEEKLY_GOV_PUSH_TIMEOUT_MS=15000
# Max attempts including the first try (default 3). Backoff is 1s, 4s, 16s.
WEEKLY_GOV_PUSH_RETRIES=3
# Tick interval in ms (default 60000). The ticker checks every minute whether it's Monday 06:00.
WEEKLY_GOV_PUSH_INTERVAL_MS=60000
# Optional school identifier included in the push envelope so multiple schools can share an endpoint.
WEEKLY_GOV_PUSH_SCHOOL_ID=
# ─── USSD Gateway (Sprint 2) ─────────────────────────────────────────────
# POST /api/ussd/callback receives USSD callbacks from the telecom
# gateway. Plain-text CON/END responses.
#
# Session inactivity timeout in ms (default 180000 = 3 min). The sweep
# runs every 60s; sessions older than this are discarded.
USSD_SESSION_TIMEOUT_MS=180000
# Optional shared secret. When set, the controller rejects requests
# whose X-Gateway-Secret header doesn't match. Leave blank in dev.
USSD_GATEWAY_SECRET=