CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

fix(auth): signup is closed during build-out #5591

MergedXSccantynz wants to mergefix/close-signup-during-buildoutmainopened 1d ago
ccantynzcommented 1d ago

Owner decision 2026-08-30: the platform is in build-out, not open for business, Stripe isn't enabled, and nobody should be able to create an account by walking up to the front door. auth.post("/register") had no gate of any kind.

The security argument was already written here

workflow-exec-policy.ts, in its own words:

"Registration is open (auth.post("/register") has no invite or approval gate), and a push enqueues a run … anybody who can sign up can run arbitrary code inside the production container"

— and it describes its own allowlist as "CONTAINMENT, not a fix."

This closes the first link of that chain rather than narrowing the last one.

Only an exact "true" opens it

A missing flag, "", "1" or "yes" all mean closed. A typo cannot open the platform.

The invite path is not optional politeness

scripts/first-run-journey.mjs registers through this endpoint on purpose — "using exactly the surfaces a person uses" — and it's the only end-to-end check covering register → repo → PAT → push → PR → merge.

Sealing the endpoint would have silently disabled the best monitor in the repo. That's precisely the failure this codebase keeps finding, and the one the Vapron briefing names: a check that cannot tell "broken" from "cannot tell".

So the journey carries the code rather than getting a private back door — a back door would mean it no longer exercises what a human hits, which is the entire value of it. The code comes from the signup_invite_code flag, injected by the task; rotating it in /admin takes effect next tick, no deploy, no .env edit.

If the flag is missing, the journey fails on the register step with the platform's own refusal message. Correct direction: a monitor that cannot run must say so.

Two ways a gate like this is usually got wrong

Both refused, both tested:

  • An unset code must never mean "everything matches" — the classic inversion where locking the door harder unlocks it.
  • An empty field must never walk through an empty flag.

Comparison is constant-time, so the code can't be guessed a character at a time.

Not a breach

The 26 existing accounts were checked: the ten most recent are all journey-*@example.invalid, the platform's own synthetic monitor. No unexpected human signups.

The signup_invite_code flag is already set in production (40 chars, generated on the box), so the door is shut with a working key the moment this deploys.

ccantynzAI Reviewcommented 1d ago

AI Triage

(no summary)

Priority: medium Risk area: mixed

Suggested labels: (no label suggestions) Suggested reviewers: (no reviewer suggestions)

Suggestions only — nothing has been applied. The PR author stays in control.

gluecron[bot]🤖 botAI Reviewcommented 1d ago

AI review unavailable

The platform's AI balance is exhausted, so AI generation is temporarily unavailable. Nothing was lost. You can queue this as a repair for the internal agent from the repository's Health page, or try again once the balance is restored. The PR is otherwise unchanged.

Cross-repo impact

See what breaks downstream if this PR merges.

Analyze →
⮌ Merged

This pull request was merged into main.

c comment · e edit title · m merge · a approve · r request changes · ? shortcuts