Introduces a fourth AUTH_MODE, `team`: Better Auth email/password with the
existing organization/member/role/invitation stack, but none of the hosted
SaaS coupling (no Autumn billing, Turnstile, Loops email, Google social
login, onboarding chat, PostHog, disposable-email block, dub referrals).
- auth-mode.ts: add `team`; add isTeamAuthMode / isSessionAuthMode /
isSessionClientAuthMode ("is there a login session?" vs isHostedAuthMode's
"is this the billed product?").
- auth.ts: createAuth() builds a valid instance for `team` — verification
off, self-serve signup disabled, no captcha/Loops/social. hasTeamAuthConfig
(BETTER_AUTH_URL + BETTER_AUTH_SECRET only) + hasSessionAuthConfig.
- ensure-user: resolve.ts routes `team` through resolveHostedContext;
requireHostedSession + selfHostedOAuth callback accept any session mode.
- api/auth/$.ts: mount the Better Auth handler for `team` too.
- Client: route guards, sidebar account menu / sign-out, settings
Organization tab, invitation accept, and error cards switch from
isHostedClientAuthMode to isSessionClientAuthMode where they mean "has a
session". Sign-in goes straight to the email form (no Google button);
sign-up shows an invite-only notice.
- selfhost-preflight: validate `team` (requires BETTER_AUTH_URL +
BETTER_AUTH_SECRET >= 32 chars).
- .env.example: document `team`.
Ships inert: AUTH_MODE stays local_noauth. tsc / oxlint / knip clean;
test suite unchanged (1164 pass, 1 pre-existing Windows-CRLF failure in
samSkills.test.ts).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>