⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
scripts/gen-selfhost-env-reference.ts recognizes computed env[X] access only via a literal
string, the envString(env, "X") helper, or a helper call whose name argument is a literal at the
call site (see the sibling issue filed alongside this one for that specific blind spot). It has no
case at all for a name that comes from iterating a local array of literal strings.
src/selfhost/preflight.ts:113-119 declares:
const CRITICAL_SECRET_VARS = ["GITHUB_WEBHOOK_SECRET", "LOOPOVER_API_TOKEN", "LOOPOVER_MCP_TOKEN", "INTERNAL_JOB_TOKEN", "SELFHOST_SETUP_TOKEN"];
and checkCriticalSecrets (lines 137-138) reads them via
for (const name of CRITICAL_SECRET_VARS) { const value = nonBlank(env[name]); ... }.
Four of these five vars (SELFHOST_SETUP_TOKEN is separately read literally elsewhere, at line 201,
so it's already covered) are read only inside this loop, nowhere else in the scanned source roots.
Confirmed empirically: grep -n "GITHUB_WEBHOOK_SECRET\|LOOPOVER_API_TOKEN\|LOOPOVER_MCP_TOKEN\|INTERNAL_JOB_TOKEN" apps/loopover-ui/src/lib/selfhost-env-reference.ts returns zero hits.
That generated file renders verbatim into the public self-hosting docs page
(apps/loopover-ui/content/docs/self-hosting-configuration.mdx:227). preflight.ts's own comment
(lines 83-84) calls these exact 4 tokens out as critical secrets that bypass real checks "silently,
with no error" if left weak or reused across environments — and those are precisely the ones
missing from the operator-facing env-var reference table meant to warn operators about exactly this
class of secret.
Requirements
- Extend
gen-selfhost-env-reference.ts's scan logic to recognize a for (const name of ARRAY_OF_LITERALS) { ... env[name] ... } pattern — where ARRAY_OF_LITERALS is a locally-declared
const array of string literals used as the loop variable, and the loop body reads env[name] (or
passes name into an already-recognized helper).
- The fix should generalize to any locally-declared literal-string array used this way, not just
special-case CRITICAL_SECRET_VARS by name.
Deliverables
All three Deliverables are required in the same PR.
Test Coverage Requirements
scripts/** generator logic and its test file are measured by codecov/patch (99%+ target). The
new test must exercise the new array-loop-detection code path directly, not just re-assert
already-covered helper patterns.
Expected Outcome
The 4 critical secret env vars this repo's own preflight check calls out as high-risk are correctly
surfaced in the operator-facing self-host env reference, and the generator's scan logic now
generalizes to array-loop-driven env reads, closing this blind-spot category.
Links & Resources
Context
scripts/gen-selfhost-env-reference.tsrecognizes computedenv[X]access only via a literalstring, the
envString(env, "X")helper, or a helper call whose name argument is a literal at thecall site (see the sibling issue filed alongside this one for that specific blind spot). It has no
case at all for a name that comes from iterating a local array of literal strings.
src/selfhost/preflight.ts:113-119declares:and
checkCriticalSecrets(lines 137-138) reads them viafor (const name of CRITICAL_SECRET_VARS) { const value = nonBlank(env[name]); ... }.Four of these five vars (
SELFHOST_SETUP_TOKENis separately read literally elsewhere, at line 201,so it's already covered) are read only inside this loop, nowhere else in the scanned source roots.
Confirmed empirically:
grep -n "GITHUB_WEBHOOK_SECRET\|LOOPOVER_API_TOKEN\|LOOPOVER_MCP_TOKEN\|INTERNAL_JOB_TOKEN" apps/loopover-ui/src/lib/selfhost-env-reference.tsreturns zero hits.That generated file renders verbatim into the public self-hosting docs page
(
apps/loopover-ui/content/docs/self-hosting-configuration.mdx:227).preflight.ts's own comment(lines 83-84) calls these exact 4 tokens out as critical secrets that bypass real checks "silently,
with no error" if left weak or reused across environments — and those are precisely the ones
missing from the operator-facing env-var reference table meant to warn operators about exactly this
class of secret.
Requirements
gen-selfhost-env-reference.ts's scan logic to recognize afor (const name of ARRAY_OF_LITERALS) { ... env[name] ... }pattern — whereARRAY_OF_LITERALSis a locally-declaredconstarray of string literals used as the loop variable, and the loop body readsenv[name](orpasses
nameinto an already-recognized helper).special-case
CRITICAL_SECRET_VARSby name.Deliverables
collectSelfHostEnvVars()includesGITHUB_WEBHOOK_SECRET,LOOPOVER_API_TOKEN,LOOPOVER_MCP_TOKEN, andINTERNAL_JOB_TOKEN(currently absent).apps/loopover-ui/src/lib/selfhost-env-reference.tsis regenerated andcommitted with all 4 new entries present.
test/unit/selfhost-env-reference-script.test.ts, using the existing fixturepattern, proving a
for (const name of LOCAL_ARRAY) { env[name] }shape is now detected, witha fixture array of 2+ literal names.
All three Deliverables are required in the same PR.
Test Coverage Requirements
scripts/**generator logic and its test file are measured bycodecov/patch(99%+ target). Thenew test must exercise the new array-loop-detection code path directly, not just re-assert
already-covered helper patterns.
Expected Outcome
The 4 critical secret env vars this repo's own preflight check calls out as high-risk are correctly
surfaced in the operator-facing self-host env reference, and the generator's scan logic now
generalizes to array-loop-driven env reads, closing this blind-spot category.
Links & Resources
scripts/gen-selfhost-env-reference.ts(scan logic to extend)src/selfhost/preflight.ts:83-84(the risk this reference table exists to communicate),:113-119(CRITICAL_SECRET_VARS),:137-138(checkCriticalSecrets)apps/loopover-ui/content/docs/self-hosting-configuration.mdx:227(where the generated tablerenders)
test/unit/selfhost-env-reference-script.test.ts(existing fixture pattern to extend)sibling same-file-wrapper-helper issue filed alongside this one)