Skip to content

Environment Variable Inventory

Executive Overview — all summaries for decision-makers.

No secrets in this document. Set values only in Render Dashboard / Azure / Cloudflare.

Production — Backend (mqa-backend)

VariableRequiredDescriptionSource
DATABASE_URLPostgreSQL connection stringRender Postgres (auto)
NODE_ENVproductionrender.yaml
PORT3000render.yaml
JWT_SECRETJWT signing (min. 32 characters)Render generate
CORS_ORIGINhttps://portal.mqa.grouprender.yaml
FRONTEND_URLhttps://portal.mqa.grouprender.yaml
CRON_SECRETHeader x-cron-secret for /api/jobs/runRender generate
SKIP_OAUTH_VALIDATIONMust be false in productionrender.yaml
OAUTH_CLIENT_IDAzure App RegistrationAzure Portal
OAUTH_CLIENT_SECRETAzure App SecretAzure Portal
OAUTH_TENANT_IDAzure Tenant IDAzure Portal
OAUTH_REDIRECT_URIhttps://api.mqa.group/api/auth/callbackAzure + Render
ANTHROPIC_API_KEYClaude APIAnthropic Console — see AI-SERVICES
OPENROUTER_API_KEYAlternative LLM routeOpenRouter — see AI-SERVICES
RESEND_API_KEYEmail via ResendResend — see RESEND
MICROSOFT_SENDER_EMAILGraph email senderAzure
R2_ACCOUNT_IDCloudflare R2 accountCloudflare (MQA org)
R2_ACCESS_KEY_IDR2 API keyCloudflare
R2_SECRET_ACCESS_KEYR2 API secretCloudflare
R2_BUCKET_NAMEe.g. mqa-mediaCloudflare
R2_PUBLIC_URLPublic R2 CDN URLCloudflare
ADMIN_MAINTENANCE_SECRET/api/admin/maintenance/*openssl rand
EMAIL_WEBHOOK_SECRET/api/email-tracking/deliveredopenssl rand
OPENSANCTIONS_API_KEYKYC screeningOpenSanctions
HIDE_PORTAL_DEMO_CONTENTHide demo contenttrue in prod

Production — Frontend (mqa-frontend)

VariableRequiredDescription
VITE_API_BASE_URLhttps://api.mqa.group/api
VITE_APP_ENVproduction
VITE_DOCS_URLhttps://docs.mqa.group (external VitePress site)
NODE_VERSION20

Never put secrets under VITE_* — they end up in the browser bundle.

Production — Developer Docs (mqa-docs)

VariableRequiredDescription
DOCS_PASSWORDHTTP Basic Auth password for docs.mqa.group — site is public if unset
DOCS_USERNAMEBasic Auth username (default mqa)
PORTSet by Render automatically
NODE_VERSION20

Service runs apps/docs-site/server.mjs after VitePress build. Share username/password with MANAGEMENT+ / auditors as needed.

Staging (planned)

Same keys as production, different values:

  • CORS_ORIGIN / FRONTEND_URLhttps://staging.portal.mqa.group
  • VITE_API_BASE_URLhttps://staging.api.mqa.group/api
  • Own DATABASE_URL, JWT_SECRET, OAuth app

Local Development

FileGit
backend/.env❌ gitignored
.env.local❌ gitignored
backend/ENV_TEMPLATE.txt✅ template

Rotation

SecretRecommended frequencyTrigger
JWT_SECRET12 monthsInvalidates all sessions
CRON_SECRET12 monthsUpdate Render Cron Job header
R2 keysOn account migrationImmediately
OAuth secret24 months (Azure policy)Azure Portal
ADMIN_MAINTENANCE_SECRETOn team changeManual

See SECURITY-STATUS.