Implements CR-96 by making Cloudron-injected env vars the sole source of truth for Postgres and SMTP. Drops DATABASE_URL and SMTP_URL from the codebase so staging/production can run with only what Cloudron provides (CLOUDRON_POSTGRESQL_URL, CLOUDRON_MAIL_SMTP_*) plus manually configured vars (SESSION_SECRET, SMTP_FROM, etc.).
Local dev uses the same variable names in .env — only the names change, not the values. Unset mail vars in development still log magic-link URLs to the server console.
Changes
lib/server/env.ts — add getDatabaseUrl() and getSmtpUrl() (assembles Nodemailer transport URL from four Cloudron mail vars); isDatabaseConfigured() reads CLOUDRON_POSTGRESQL_URL
lib/server/mail.ts — all four send paths use getSmtpUrl() instead of SMTP_URL
tests/unit/env.test.ts — unit tests for DB URL resolution, SMTP URL assembly (including credential encoding), and unset cases
How to Test
Update local .env:
Rename DATABASE_URL → CLOUDRON_POSTGRESQL_URL
For Mailhog: CLOUDRON_MAIL_SMTP_SERVER=localhost, CLOUDRON_MAIL_SMTP_PORT=1025
docker compose up -d postgres mailhog
npx prisma migrate dev (or npm run migrate:smoke for ephemeral DB smoke)
npm run dev
Verify:
GET /api/health returns {"ok":true,"database":"connected"}
Magic-link request at /login delivers email to Mailhog (http://localhost:8025) or logs verify URL when mail vars are unset
Automated checks:
npx tsc --noEmit
npx vitest run tests/unit/env.test.ts
npm run migrate:smoke
## Overview
Implements **CR-96** by making Cloudron-injected env vars the sole source of truth for Postgres and SMTP. Drops `DATABASE_URL` and `SMTP_URL` from the codebase so staging/production can run with only what Cloudron provides (`CLOUDRON_POSTGRESQL_URL`, `CLOUDRON_MAIL_SMTP_*`) plus manually configured vars (`SESSION_SECRET`, `SMTP_FROM`, etc.).
Local dev uses the same variable names in `.env` — only the names change, not the values. Unset mail vars in development still log magic-link URLs to the server console.
## Changes
- **`lib/server/env.ts`** — add `getDatabaseUrl()` and `getSmtpUrl()` (assembles Nodemailer transport URL from four Cloudron mail vars); `isDatabaseConfigured()` reads `CLOUDRON_POSTGRESQL_URL`
- **`lib/server/mail.ts`** — all four send paths use `getSmtpUrl()` instead of `SMTP_URL`
- **`lib/server/responses.ts`** — `dbUnavailable()` message references `CLOUDRON_POSTGRESQL_URL`
- **`prisma/schema.prisma`** — datasource URL env name changed to `CLOUDRON_POSTGRESQL_URL`
- **`.env.example`**, **`scripts/migrate-smoke-local.sh`**, **`Dockerfile`** comment — updated for Cloudron var names
- **Docs** — CONTRIBUTING, testing-guide, ops-backend-deploy, backend-roadmap, backend-linear-tickets, template-recommendation-matrix, api-routes.mdc
- **`tests/unit/env.test.ts`** — unit tests for DB URL resolution, SMTP URL assembly (including credential encoding), and unset cases
## How to Test
1. Update local `.env`:
- Rename `DATABASE_URL` → `CLOUDRON_POSTGRESQL_URL`
- For Mailhog: `CLOUDRON_MAIL_SMTP_SERVER=localhost`, `CLOUDRON_MAIL_SMTP_PORT=1025`
2. `docker compose up -d postgres mailhog`
3. `npx prisma migrate dev` (or `npm run migrate:smoke` for ephemeral DB smoke)
4. `npm run dev`
5. Verify:
- `GET /api/health` returns `{"ok":true,"database":"connected"}`
- Magic-link request at `/login` delivers email to Mailhog (`http://localhost:8025`) or logs verify URL when mail vars are unset
6. Automated checks:
```bash
npx tsc --noEmit
npx vitest run tests/unit/env.test.ts
npm run migrate:smoke
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Overview
Implements CR-96 by making Cloudron-injected env vars the sole source of truth for Postgres and SMTP. Drops
DATABASE_URLandSMTP_URLfrom the codebase so staging/production can run with only what Cloudron provides (CLOUDRON_POSTGRESQL_URL,CLOUDRON_MAIL_SMTP_*) plus manually configured vars (SESSION_SECRET,SMTP_FROM, etc.).Local dev uses the same variable names in
.env— only the names change, not the values. Unset mail vars in development still log magic-link URLs to the server console.Changes
lib/server/env.ts— addgetDatabaseUrl()andgetSmtpUrl()(assembles Nodemailer transport URL from four Cloudron mail vars);isDatabaseConfigured()readsCLOUDRON_POSTGRESQL_URLlib/server/mail.ts— all four send paths usegetSmtpUrl()instead ofSMTP_URLlib/server/responses.ts—dbUnavailable()message referencesCLOUDRON_POSTGRESQL_URLprisma/schema.prisma— datasource URL env name changed toCLOUDRON_POSTGRESQL_URL.env.example,scripts/migrate-smoke-local.sh,Dockerfilecomment — updated for Cloudron var namestests/unit/env.test.ts— unit tests for DB URL resolution, SMTP URL assembly (including credential encoding), and unset casesHow to Test
.env:DATABASE_URL→CLOUDRON_POSTGRESQL_URLCLOUDRON_MAIL_SMTP_SERVER=localhost,CLOUDRON_MAIL_SMTP_PORT=1025docker compose up -d postgres mailhognpx prisma migrate dev(ornpm run migrate:smokefor ephemeral DB smoke)npm run devGET /api/healthreturns{"ok":true,"database":"connected"}/logindelivers email to Mailhog (http://localhost:8025) or logs verify URL when mail vars are unset