fix(env): read NEXT_PUBLIC_LOG_TRPC from its own variable, drop dead public env vars (#4035)

* fix(env): read NEXT_PUBLIC_LOG_TRPC from its own variable, drop dead public env

`clientEnv` restates every key by hand because Next.js inlines only the
`process.env.NEXT_PUBLIC_*` references it can see literally. `NEXT_PUBLIC_LOG_TRPC`
named `NEXT_PUBLIC_LOG_TRP`, so it was permanently undefined and the schema default
turned that into `false` with nothing to read.

`NEXT_PUBLIC_CONTENT_DECTECTION_LOCATION` has no consumers anywhere in the
workspace; removed from the schema, the Dockerfile ARG and `.env-example`. Same for
the `NEXT_PUBLIC_MAINTENANCE_MODE` ARG (no such var in either schema) and the
`NEXT_PUBLIC_UI_CATEGORY_VIEWS` / `NEXT_PUBLIC_ADS` lines in `.env-example`.

`NEXT_PUBLIC_IMAGE_LOCATION` keeps its `.default('')` deliberately. Requiring it
would fail builds that legitimately do not pass it, and the dangerous call sites
already refuse a relative URL.

The new test stamps a per-key sentinel into `process.env` and asserts each key read
its own name, so this class of typo fails naming the variable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(env): close the gaps the review found in the client-env guard

Three findings from the adversarial pass, each with the control run rather than
assumed.

The sentinel sweep exempted `NEXT_PUBLIC_DEFAULT_PAYMENT_PROVIDER` — the one key
resolved from an expression, and so the one most able to carry the typo the guard
exists to catch. Dropping the trailing `R` from the read pinned every user to Stripe
with the suite still green. Replaced the blanket skip with assertions on the value,
plus a check that nothing is exempted which is not in the schema.

Making the `NEXT_PUBLIC_LOG_TRPC` read live changes parse behaviour for anything
already setting it: `z.stringbool()` rejects the empty string, and a failed parse
throws out of `~/env/client` at import. A value that was inert before this branch
would have hard-failed after it, so the schema now catches to `false`.

`NEXT_PUBLIC_BASE_URL` falls back to `NEXTAUTH_URL`, which has no `NEXT_PUBLIC_`
prefix and is therefore never inlined into the client bundle — an environment
setting only that one resolves server-side and is `undefined` in the browser. Left
in place rather than removed, since dropping it changes behaviour beyond this
ticket, but pinned by tests so it is visible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(env): treat an empty NEXT_PUBLIC_LOG_TRPC as unset, not as a catch-all

`.catch(false)` swallowed every unparseable value, which is the same plausible-false
failure this branch exists to remove — just moved from the variable name to its
value — and made this the only stringbool in the file that hides a misconfiguration.

Only the empty case needs handling: the read named the wrong variable until this
branch, so a config carrying a valueless key had been inert and would otherwise
start throwing out of `~/env/client`. Anything else unparseable throws, as it does
for every other flag here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Justin Maier
2026-08-17 15:10:06 -06:00
committed by GitHub
parent 960d160027
commit 7cff7ceb4f
4 changed files with 125 additions and 9 deletions
-3
View File
@@ -69,11 +69,8 @@ S3_IMAGE_UPLOAD_OVERRIDE=
# Client env vars
NEXT_PUBLIC_IMAGE_LOCATION=http://localhost:3000
NEXT_PUBLIC_CONTENT_DECTECTION_LOCATION=https://publicstore.civitai.com/content_detection/model.json
NEXT_PUBLIC_CIVITAI_LINK=http://localhost:3000
NEXT_PUBLIC_UI_CATEGORY_VIEWS=false
NEXT_PUBLIC_UI_HOMEPAGE_IMAGES=false
NEXT_PUBLIC_ADS=true
# Clickhouse
CLICKHOUSE_HOST=http://localhost:18123