Repository navigation
Require a human check on the chat, and stop absence meaning "off" - #248
Merged
Merged
Conversation
Adam asked for a human check when going to the regular chat, not only the search-page endpoint. The middleware already existed; what did not was any way to tell whether a given deployment was actually using it. `is_captcha_exempt` treated "no CLOUDFLARE_SECRET_KEY" as "no captcha to enforce" and let everything through. So "there is captcha middleware" and "the chat is gated" were different statements, and the gap was silent: beta has been serving an ungated chat, correctly per that rule and invisibly. Now the decision is written down rather than inferred. CHAT_REQUIRES_HUMAN defaults to on, and a deployment that requires a human but has no key refuses to start, with a message saying which of the two things to do. An ungated chat is still available -- beta may want one -- but only by setting CHAT_REQUIRES_HUMAN=0, which someone has to type. Refusing to start rather than serving unprotected is the trade the answer endpoint's verifying key already makes. Losing the feature is the correct failure. Sequencing, because this could otherwise take beta down: the deploy script now checks the env file for a key or an explicit opt-out *before* it stops the running container, the same way it checks the caller-token key. Exercised against beta's current env, where it correctly refuses, and against five variants including an empty value and a mistyped opt-out, both of which fail closed. The keys themselves are Adam's to place. ~/install-beta-captcha-keys.sh prompts for them, hides the secret, keeps 0600 and a backup, and prints neither -- a transcript is a worse home for a credential than the host, the same reasoning that kept the signing key off this machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Committed the previous change with ruff failing: I printed its exit code and then ran git anyway, which is the second time today that shape has caught me. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Your requirement, relayed via the website session: "we need to make sure there is also a human checker when going to the regular chat as well."
The obstacle was not the check
The middleware already existed. What did not exist was any way to tell whether a deployment was using it.
is_captcha_exempttreated noCLOUDFLARE_SECRET_KEYas no captcha to enforce and let everything through. So "there is captcha middleware" and "the chat is gated" were different statements with nothing to distinguish them — and beta has been serving an ungated chat, correctly per that rule and invisibly. I verified it directly:captcha_configured = Falsein the running container.That is the same failure shape I warned the website session about an hour earlier, pointing back at us.
What changed
CHAT_REQUIRES_HUMANdefaults to on. A deployment that requires a human but has no key refuses to start, naming the two ways out. An ungated chat is still available — beta may want one — but only by settingCHAT_REQUIRES_HUMAN=0, which somebody has to type.Refusing to start rather than serving unprotected is the trade the answer endpoint's verifying key already makes. Losing the feature is the correct failure; serving it unprotected is not.
Sequencing, because this could otherwise take beta down
Beta has no keys today, so this change alone would refuse every visitor. The deploy script now checks the env file for a key or an explicit opt-out before it stops the running container, exactly as it checks the caller-token key.
Exercised against beta's real env (correctly refuses) and five variants:
CLOUDFLARE_SECRET_KEY=0xabcCHAT_REQUIRES_HUMAN=0CLOUDFLARE_SECRET_KEY=(empty)CHAT_REQUIRES_HUMAN=nope(typo)A mistyped opt-out failing closed is the case I most wanted to get right.
The keys are yours to place
~/install-beta-captcha-keys.shprompts for them, hides the secret as you type, keeps0600and a timestamped backup, and prints neither value. A transcript is a worse home for a credential than the host — the same reasoning that kept the answer endpoint's signing key off this machine entirely.After running it, redeploy and the chat is gated.
🤖 Generated with Claude Code