You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(devx): re-pin the publish smoke to the declared first-run contract (#14255)
The packed-tarball smoke asserted that the first POST /auth/sign-up/email
after `objectstack dev --fresh` returns 200 — an expectation authored
before #11739/#11767 made `invite_only` the default audience posture.
It is not the first account that reaches that probe. `--fresh` seeds a dev
admin in-process at boot through the real signUpEmail pipeline, and THAT
creation is the zero-user one the bootstrap bypass admits. The smoke's own
sign-up is the SECOND self-serve account, which invite_only refuses with
SELF_REGISTRATION_CLOSED + 403 — correctly. The release candidate had
therefore never once passed this gate with the posture default aboard.
Per the maintainer-approved ruling (option A, director batch #23):
- assert the seeded admin can SIGN IN, which is the packed install's
proof that the bootstrap bypass really fired;
- assert the uninvited second self-serve sign-up is REFUSED, pinning
both the 403 and the envelope code so an accidental widening of the
unauthenticated surface reds the RC instead of shipping;
- obtain the non-admin probe user through the operator path (the
invitation carve-out) before the existing session/CRUD probes.
Behaviour only — no vendor-internal symbol is pinned, and no auth or
audience runtime code is touched.
The posture is READ from the artifact's own public /auth/config rather
than hard-coded, because the two smoke modes install different products:
`registry` smokes the last PUBLISHED release, and plugin-auth 17.2.0
(2026-08-23) predates #11767 (2026-08-25). In `pack` mode the advertised
posture must BE invite_only; in both modes enforcement must match what
the artifact advertises.
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
Co-authored-by: Claude <noreply@anthropic.com>
# ⛔ The RC's own default is not negotiable and not read from the RC's opinion
834
+
# of itself: `invite_only` is what #11739/#11767 declare, so anything else here
835
+
# is a widening of the unauthenticated surface and the release candidate must
836
+
# go red for it — BEFORE the behaviour probes, which would otherwise report the
837
+
# widening as a cheerful 200.
838
+
if [ "$SMOKE_MODE"="pack" ] && [ "$AUDIENCE_POSTURE"!="invite_only" ];then
839
+
fail "the release candidate advertises audience posture '$AUDIENCE_POSTURE', but the declared default is invite_only (#11739/#11767). Either the default was widened — in which case this refusal is the point of the gate — or the posture is no longer advertised on /auth/config and this probe has stopped measuring anything."
840
+
fi
841
+
842
+
# ── the seeded admin signs in ───────────────────────────────────────────────
843
+
# This is the packed install's proof that the BOOTSTRAP BYPASS fired. Under the
844
+
# default `invite_only` posture the only self-registration the audience gate
845
+
# admits is the very first account on a zero-user database, and
846
+
# `objectstack dev --fresh` spends exactly that carve-out on the in-process
847
+
# dev-admin seed (`maybeSeedDevAdmin` → the real `signUpEmail` pipeline, which
848
+
# passes through the same gate). An account that can sign in HERE is an account
849
+
# that gate admitted — nothing else could have created it. When the bypass
850
+
# genuinely fails to fire (the #11767 defect: the bootstrap probe threw and the
851
+
# outer `catch` read the rejection as "not bootstrap"), the seed never lands and
852
+
# this probe fails, naming the real defect instead of leaving it to be inferred
853
+
# from a sign-up refusal further down.
854
+
probe "POST /auth/sign-in/email (seeded dev admin — proves the bootstrap bypass fired)" 200 \
"the uninvited self-serve sign-up was refused, but NOT by the audience posture — a 403 whose code is not SELF_REGISTRATION_CLOSED means some other guard answered, and this probe has stopped measuring the closed-by-default posture"
884
+
885
+
# ── the operator path admits the probe user ───────────────────────────────
886
+
# How a real operator adds a teammate on a fresh install: `invite_only` means
887
+
# BY INVITATION, and a self-serve sign-up whose address holds a pending,
888
+
# unexpired `sys_invitation` row is admitted under every posture (the
889
+
# invitation carve-out). The route runs as the signed-in admin against the
890
+
# default organization their session carries — ADR-0081 bootstraps that org
891
+
# precisely so this path exists on a single-org install.
892
+
#
893
+
# Chosen over `POST /auth/admin/create-user` — the other operator path named
894
+
# in the ruling — because that route needs better-auth's `admin` plugin,
895
+
# which a scaffolded project does NOT get by default
896
+
# (`admin: pluginConfig.admin ?? scimEffective`, auth-manager.ts), so it
897
+
# would answer 501 NOT_IMPLEMENTED on the very artifact under test. The
898
+
# organization plugin IS on by default
899
+
# (`organization: pluginConfig.organization ?? true`), so the invitation
900
+
# carve-out is the operator path a fresh install actually ships.
901
+
log "Operator path (invitation carve-out) — how a fresh install adds its second user"
902
+
probe "POST /auth/organization/invite-member (as the seeded admin)" 200 \
0 commit comments