Files
continuum-backend/.env.example
T
octoturge b7792ad335 Refuse to boot without R2 credentials
`?? ""` on the access key and secret meant a deployment with no object
storage configured started happily, and `POST /jobs` handed clients
presigned URLs signed with an empty key. The first sign of trouble was a
403 from R2 - either in the client's uploader or, worse, inside a gateway
that had downloaded R2's XML error document in place of a print. Nothing
in that chain said "R2 is not configured".

Reads both credentials through a `required()` that throws, naming the
variable, mirroring auth/verifier.ts and auth/edge_secret.ts.

The endpoint is read with `||` rather than `??`, because the committed
template ships `R2_ENDPOINT=` empty and `??` only catches null - so an
empty value was taken as a real endpoint and the account-id derivation
never ran. That is the trap auth/edge_secret.ts documents, and it caught
this line too, in the first draft of it. A test covers the derivation.

Each boot-failure test fills every other variable so the one under test
is the only thing missing; otherwise whichever variable is read first
wins and the assertion passes for the wrong reason.

e2e-edge.sh gains dummy values, since it boots the backend. It presigns
nothing, so they only have to exist.
2026-10-18 19:52:22 +00:00

37 lines
1.5 KiB
Bash

PORT=3000
# Postgres, routed through pgCat/PgBouncer
DATABASE_URL=postgres://continuum:continuum@localhost:6432/continuum
DATABASE_POOL_MAX=10
# Valkey (state + streams), NOT Redis - Redis 7.4+ is RSALv2/SSPL and 8.0+
# adds AGPLv3, none of which we can ship commercially. Valkey is BSD-3-Clause
# and wire-compatible. The URL scheme stays `redis://` because that names the
# RESP wire protocol, which is what the client libraries parse - no client
# understands a `valkey://` scheme.
VALKEY_URL=redis://localhost:6379
# Cloudflare R2 (S3-compatible). The two credentials are required and the
# process will not start without them: an empty key signs presigned URLs that
# R2 answers with a 403, which surfaced as a gateway downloading an XML error
# document in place of a print rather than as "R2 is not configured".
#
# Either R2_ENDPOINT or R2_ACCOUNT_ID is needed too - the endpoint is derived
# from the account id the way Cloudflare's own URLs are formed. R2_BUCKET is
# not a credential and defaults to "continuum".
R2_ACCOUNT_ID=
R2_BUCKET=continuum
R2_ENDPOINT=
R2_ACCESS_KEY_ID=
R2_SECRET_ACCESS_KEY=
# Supabase Auth. Access tokens are verified against this project's published
# JWKS (RS256), so no signing secret is needed - or wanted - here.
SUPABASE_URL=
# Signs the edge JWTs minted for continuum-proxy gateways via
# POST /auth/edge-token and verified by /ws/edge/v1. Required - the process
# refuses to start without it, because anything that knows this secret can
# connect as any farm's gateway. Generate one with: openssl rand -hex 32
EDGE_JWT_SECRET=