fix(canvas): boot-time matched-pair guard for ADMIN_TOKEN env vars (#175) #53

Merged
claude-ceo-assistant merged 2 commits from fix/175-env-matched-pair-guard into main 2026-05-09 02:24:21 +00:00

2 Commits

Author SHA1 Message Date
claude-ceo-assistant
04157f6896 trigger: re-fire sop-tier-check after tier:medium re-label
Some checks failed
sop-tier-check / tier-check (pull_request) Failing after 3s
2026-05-08 19:22:39 -07:00
Hongming Wang
a6477d2b0c fix(canvas): boot-time matched-pair guard for ADMIN_TOKEN env vars (#175)
Closes the post-PR-#174 self-review gap: the matched-pair contract
between ADMIN_TOKEN (server-side bearer gate) and NEXT_PUBLIC_ADMIN_TOKEN
(canvas client-side bearer attach) was descriptive only, living in a
.env file comment. Future agents/devs could re-misconfigure with one
of the two unset and silently 401 — every workspace API call refused
with no actionable diagnostic.

Adds checkAdminTokenPair() to canvas/next.config.ts, run after
loadMonorepoEnv() so it sees the post-load state. Two distinct
warnings (server-set/client-unset and the inverse) so an operator can
tell which half is missing without grep'ing. Empty string is treated
as unset so KEY= and unset KEY produce the same verdict.

Warn-only, not exit — production canvas Docker images bake these vars
at image-build time and a hard exit would turn a recoverable auth
issue into a crashloop. The console.error fires in `next dev`, the
standalone server's stdout, and the canvas Docker container logs —
the three places an operator looks when "everything 401s."

Tests pin exact stderr strings (per feedback_assert_exact_not_substring)
across 6 cases: both unset, both set, ADMIN_TOKEN-only, NEXT_PUBLIC-only,
empty-string-as-unset, and the empty-string-asymmetric mismatch.
Mutation-tested: flipping the if-condition from === to !== fails all 6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:22:39 -07:00