fix(sentry): remove hardcoded DSN fallbacks; supply via env in CI

Self-hosted instances no longer inherit the trails.cool flagship Sentry
DSNs. Code paths now read DSN strictly from env — unset = no Sentry
init, no events sent.

Flagship continues to report unchanged: cd-apps.yml and cd-staging.yml
inject the public DSNs as workflow env vars, which feed into:
- runtime via \`infrastructure/app.env\` / \`staging.env\`
  (\`SENTRY_DSN_JOURNAL\` / \`SENTRY_DSN_PLANNER\` → compose env per service)
- build time via docker build-arg \`VITE_SENTRY_DSN\` (journal only;
  planner has no client Sentry init).

Sentry DSNs are public-by-design (transmitted unencrypted from the
client JS bundle), so embedding them as plaintext workflow env vars
is no worse than the runtime exposure. Forks should replace these with
their own DSNs or remove the workflow env lines to ship Sentry-free.

Files changed:
- apps/journal/server.ts: \`process.env.SENTRY_DSN\` only, no fallback
- apps/planner/server.ts: same
- apps/journal/app/lib/sentry.client.ts: \`import.meta.env.VITE_SENTRY_DSN\`
  only; falsy = skip init
- apps/journal/Dockerfile: new \`ARG VITE_SENTRY_DSN\` baked into build
- infrastructure/docker-compose.yml: pass \`SENTRY_DSN\` per service
- infrastructure/docker-compose.staging.yml: same
- .github/workflows/cd-apps.yml: workflow env + build-arg + app.env echo
- .github/workflows/cd-staging.yml: same

Full repo: pnpm typecheck, pnpm lint, pnpm test, journal build all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-05-25 23:07:07 +02:00
parent f239b4adee
commit edb618fe40
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
8 changed files with 55 additions and 21 deletions

View file

@ -53,6 +53,7 @@ services:
SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET must be set}
NODE_ENV: production
PORT: 3000
SENTRY_DSN: ${SENTRY_DSN_JOURNAL:-}
SENTRY_RELEASE: ${SENTRY_RELEASE:-}
SMTP_URL: ""
SMTP_FROM: trails.cool staging <noreply@staging.trails.cool>
@ -89,6 +90,7 @@ services:
DATABASE_URL: postgres://trails:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in SOPS secrets.app.env}@postgres:5432/${STAGING_DATABASE}
NODE_ENV: production
PORT: 3001
SENTRY_DSN: ${SENTRY_DSN_PLANNER:-}
SENTRY_RELEASE: ${SENTRY_RELEASE:-}
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:3001/health || exit 1"]

View file

@ -42,6 +42,11 @@ services:
SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET must be set in SOPS secrets.app.env}
NODE_ENV: production
PORT: 3000
# SENTRY_DSN per service (journal + planner have separate Sentry
# projects on the same org). Empty = no Sentry init (correct
# default for self-hosted instances). See cd-apps.yml for how the
# flagship populates this.
SENTRY_DSN: ${SENTRY_DSN_JOURNAL:-}
SENTRY_RELEASE: ${SENTRY_RELEASE:-}
SMTP_URL: ${SMTP_URL:-}
SMTP_FROM: ${SMTP_FROM:-trails.cool <noreply@trails.cool>}
@ -87,6 +92,7 @@ services:
DATABASE_URL: postgres://trails:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in SOPS secrets.app.env}@postgres:5432/trails
NODE_ENV: production
PORT: 3001
SENTRY_DSN: ${SENTRY_DSN_PLANNER:-}
SENTRY_RELEASE: ${SENTRY_RELEASE:-}
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:3001/health || exit 1"]