Six phases claimed the product runs on SQLite and on Postgres. Nothing had ever run it on Postgres. TEST_DATABASE_URL now points the whole suite at a real server and CI runs both arms. The first run found a bug that would have shipped. better-auth's banned flag is integer 0/1 on SQLite and a real boolean on Postgres, and the code read it as `banned === 1`, so on Postgres an account someone asked us to freeze went on receiving email. Both of those flags are now typed for either dialect and read through isFlagSet. It also found the migration advisory lock being taken on a pool. An advisory lock belongs to the session that took it, so a lock on one pooled connection and an unlock on another leaves it held. Two replicas migrating at once is the ordinary case in k8s and is precisely what it was there to protect. New for the scaled mode: k8s manifests with migrations as an initContainer, one poller in its own worker Deployment rather than one per API replica, and an Ingress that exposes the web app only. The storage drivers finally have tests, S3 included, since scaled mode requires it and it had never been exercised. Two acceptance tests, both checked against a deliberately broken build first: two workers claiming a hundred jobs report 188 claims with SKIP LOCKED removed, and the in-flight request is cut off with the drain wait removed. 340 tests on SQLite, 341 on Postgres, 70 Playwright, rules coverage 100%. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
72 lines
2.8 KiB
Bash
72 lines
2.8 KiB
Bash
# apps/api environment. Copy to .env and adjust. Every variable is validated at boot
|
|
# by src/lib/env.ts, which fails fast with the exact problem.
|
|
|
|
# development | test | production
|
|
NODE_ENV=development
|
|
# Port the Hono server listens on. The web app proxies /api here.
|
|
PORT=4000
|
|
# User facing origin. Used for links in emails, push payloads and Telegram messages.
|
|
# Must name the same port as apps/web/.env PORT, or better-auth rejects the sign in
|
|
# request as a foreign origin.
|
|
APP_PUBLIC_URL=http://localhost:3005
|
|
|
|
# server = serves HTTP. worker = runs the job poller and sweeps, serves only /healthz.
|
|
ROLE=server
|
|
# Run the job poller inside the server process. Set false only when a dedicated
|
|
# worker exists, which requires Postgres (SQLite is single writer).
|
|
JOBS_INLINE=true
|
|
JOBS_POLL_INTERVAL_MS=2000
|
|
# A running job whose lock is older than this returns to pending, for crash recovery.
|
|
JOBS_STALE_MINUTES=10
|
|
|
|
# sqlite:./data/app.db, sqlite::memory: or postgres://user:pass@host:5432/db
|
|
# The dialect is chosen from this scheme. Nothing else selects it.
|
|
DATABASE_URL=sqlite:./data/app.db
|
|
|
|
# Signing key for sessions. At least 32 characters. Generate: openssl rand -base64 32
|
|
BETTER_AUTH_SECRET=change-me-to-at-least-32-characters-long
|
|
# Public origin cookies are issued for. Auth routes are proxied, so this is the web origin.
|
|
# Keep in step with APP_PUBLIC_URL and apps/web/.env PORT.
|
|
BETTER_AUTH_URL=http://localhost:3005
|
|
|
|
# local | s3. local needs one shared volume across replicas; s3 is required to scale out.
|
|
STORAGE_DRIVER=local
|
|
STORAGE_LOCAL_PATH=./data/files
|
|
# Only read when STORAGE_DRIVER=s3. Bucket, region and both keys are then required.
|
|
S3_ENDPOINT=
|
|
S3_REGION=
|
|
S3_BUCKET=
|
|
S3_ACCESS_KEY_ID=
|
|
S3_SECRET_ACCESS_KEY=
|
|
# Needed by MinIO and most non AWS S3 implementations.
|
|
S3_FORCE_PATH_STYLE=true
|
|
|
|
# Optional. Without it, scans with no QR go straight to the manual form instead of OCR.
|
|
ANTHROPIC_API_KEY=
|
|
OCR_MODEL=claude-sonnet-4-6
|
|
|
|
# Postgres connections per process. Multiply by the number of replicas and keep the total
|
|
# under the server's max_connections. Ignored on SQLite.
|
|
DATABASE_POOL_MAX=10
|
|
|
|
# Optional. Web push is hidden in the UI when unset. Generate: npx web-push generate-vapid-keys
|
|
PUSH_VAPID_PUBLIC_KEY=
|
|
PUSH_VAPID_PRIVATE_KEY=
|
|
# Who the push service can contact about this deployment. An https: or mailto: URL, which
|
|
# is what RFC 8292 allows. Defaults to APP_PUBLIC_URL when that is https, then to
|
|
# mailto:SMTP_FROM. With none of the three, push stays off and says so at boot.
|
|
PUSH_VAPID_SUBJECT=
|
|
|
|
# Optional. Without SMTP_HOST, verification codes and emails are logged to stdout.
|
|
SMTP_HOST=
|
|
SMTP_PORT=587
|
|
SMTP_USER=
|
|
SMTP_PASS=
|
|
SMTP_FROM=
|
|
|
|
# Optional. Telegram is hidden as a notification channel when unset.
|
|
TELEGRAM_BOT_TOKEN=
|
|
|
|
# Locale for anonymous requests. Signed in users are served their profiles.locale.
|
|
DEFAULT_LOCALE=es
|