Two W10 QA findings on the v1.4.42 env-check wave, both tied to the
v1.4.40 AP-2 silent-disable scenario this script was conceived to
catch:
1. SD-H1 — the APNs group in `scripts/env-manifest.json` shipped
without `allOrNone: true`, so the synthetic `<all-or-none>` required
row never fired. An operator setting three of four `APNS_*` vars
and leaving `APNS_KEY` / `APNS_KEY_FILE` empty would see exit 0 and
green-light the deploy — exactly the v1.4.40 paper-cut the wave was
meant to prevent. Adds the flag.
2. CR-H2 — the renderer printed `[OK] APNS_KEY` even when only
`APNS_KEY_FILE` was set. An operator grepping the env block for
`APNS_KEY` would find nothing and file a ghost issue. The
`CheckResult` now carries `satisfiedBy`, populated to the matched
alternative when it differs from the primary; the renderer prints
`[OK] APNS_KEY (satisfied by APNS_KEY_FILE)`.
Tests pin both fixes — the AP-2 scenario synthetic-row trip
(16 → 19 passing), and the `satisfiedBy` branch coverage on the anyOf
match path.
Adds `pnpm check-env` — a CLI tool that reads
`scripts/env-manifest.json` and verifies every required env var is
present + non-empty. Exit code 0 on green, 1 on missing required vars,
2 on a malformed manifest.
Two modes:
pnpm check-env # against process.env
pnpm check-env --file <path> # against a Coolify export / .env.production
The manifest is JSON so it's git-trackable and reviewable. Groups can
be marked `required: true` (boot-blocking) or `required: false`
(silently disable a feature). An `allOrNone: true` group emits a
synthetic <all-or-none> required row when partially populated — this
is the v1.4.40 AP-2 silent-disable pattern (three of four APNS_* set,
.p8 missing) made into a hard failure.
Documents the workflow in docs/ops/env-check.md including the planned
v1.4.43 CI integration. 16 unit tests pin parseEnvFile + checkEnv;
renderResults stays untested as a thin shell over the pure helpers.
This is a CLI tool, not a runtime gate — the app still boots without
this check having run. The point is to make the operator-visible step
between "Coolify env block edited" and "deploy fires" loud about
missing vars before the deploy ships.