From 29bda614a404005b2996810168b9ea27b9381320 Mon Sep 17 00:00:00 2001 From: metatroncubeswdev Date: Wed, 9 Sep 2026 14:19:28 -0400 Subject: [PATCH] Fix team-mode first-run: /setup no longer bounces to /sign-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _auth.setup.tsx: the "owner already exists?" check ran in beforeLoad, which executes during SSR where fetchTeamSetupStatus's relative fetch to /api/team-setup fails — so it always concluded an owner existed and redirected to /sign-in, making the create-owner screen unreachable. Move the check into a client-side effect with a loading state. - setup-status.ts: add BETTER_AUTH_URL to CHECK_ENV_VARS so /api/health stops falsely reporting "team mode requires BETTER_AUTH_URL" when it is set (the Docker preflight already saw it; only the runtime health check's env allowlist was missing it). Verified locally end to end against a D1 build in AUTH_MODE=team: owner bootstrap, self-disable + 409 on repeat, Better Auth sign-in issues a session cookie, and get-session resolves the shared organization. Co-Authored-By: Claude Sonnet 5 --- src/routes/_auth.setup.tsx | 41 +++++++++++++++++++++++++--------- src/server/lib/setup-status.ts | 1 + 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/routes/_auth.setup.tsx b/src/routes/_auth.setup.tsx index 6f0fd06..74a8024 100644 --- a/src/routes/_auth.setup.tsx +++ b/src/routes/_auth.setup.tsx @@ -1,5 +1,5 @@ -import { createFileRoute, redirect, useNavigate } from "@tanstack/react-router"; -import { useState } from "react"; +import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { useEffect, useState } from "react"; import { AuthPageCard } from "@/client/features/auth/AuthPage"; import { bootstrapTeamOwner, @@ -7,27 +7,38 @@ import { } from "@/client/features/auth/teamSetup"; import { authClient } from "@/lib/auth-client"; -// First-run screen for `team` mode: creates the single owner account. It -// redirects to /sign-in the moment an owner exists, so it can't be used to add -// more users. +// First-run screen for `team` mode: creates the single owner account. The +// "already has an owner?" check runs client-side (it needs a DB round trip via +// /api/team-setup, which a server-side beforeLoad can't reach with a relative +// URL) and redirects to /sign-in once an owner exists. export const Route = createFileRoute("/_auth/setup")({ - beforeLoad: async () => { - const status = await fetchTeamSetupStatus(); - if (!status.needsOwner) { - throw redirect({ to: "/sign-in", search: {} }); - } - }, component: SetupPage, }); function SetupPage() { const navigate = useNavigate(); + const [checking, setChecking] = useState(true); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); + useEffect(() => { + let cancelled = false; + void fetchTeamSetupStatus().then((status) => { + if (cancelled) return; + if (!status.needsOwner) { + void navigate({ to: "/sign-in", search: {} }); + return; + } + setChecking(false); + }); + return () => { + cancelled = true; + }; + }, [navigate]); + async function handleSubmit(event: React.FormEvent) { event.preventDefault(); setError(null); @@ -57,6 +68,14 @@ function SetupPage() { } } + if (checking) { + return ( +
+ +
+ ); + } + return (