Closes the smallest of the three production gaps the README's "Before deploying to production" block calls out:
"If you put a TrustClaw instance on the public internet for strangers to sign up to, any user can drain your Composio + AI Gateway credits indefinitely. Before opening signups to anyone but yourself / a trusted handful of people, add at least: ... Billing or invite-only signup if you want to recoup costs"
Adds opt-in invite-only signup: a new ALLOW_OPEN_SIGNUP env flag (default true, so existing deploys are unaffected), an InviteCode Prisma model, a Better Auth databaseHooks.user.create.before hook that claims a code atomically at signup, and a minimal /dashboard/admin/invites page guarded by ADMIN_USER_EMAIL for minting and revoking codes.
ALLOW_OPEN_SIGNUP=true (default): identical to today's behavior. No migration-required redeploy.ALLOW_OPEN_SIGNUP=false + ADMIN_USER_EMAIL set: signup rejected without a valid invite code. Login form surfaces an "Invite code" field with a clear error message on rejection.prisma.inviteCode.updateMany with WHERE usedAt IS NULL AND (expiresAt IS NULL OR expiresAt > now). Concurrent signups can't reuse the same code.prisma/schema.prisma + new migration: InviteCode table (code, createdAt, createdBy, expiresAt, usedAt, usedByUser, note).src/env.ts: ALLOW_OPEN_SIGNUP (boolean, default true) and ADMIN_USER_EMAIL (optional email).src/server/auth.ts: databaseHooks.user.create.before hook; throws APIError on missing/invalid/expired code.src/server/api/trpc.ts: new adminProcedure (session.user.email must match ADMIN_USER_EMAIL).src/server/api/routers/trustclaw/admin/: createInviteCode, listInviteCodes, revokeInviteCode procedures + schemas.src/app/(authenticated)/dashboard/admin/invites/: page + invite-list + create-invite-form shadcn components.src/app/login/_components/login-page.tsx: invite-code field rendered when NEXT_PUBLIC_ALLOW_OPEN_SIGNUP=false..env.example + README updates documenting the new flag.pnpm typecheck passes.pnpm lint shows the same Prisma "type could not be resolved" warnings that exist on main (affects src/server/clients/db.ts, src/server/api/routers/trustclaw/updateSettings.ts, etc.) - pre-existing ESLint module-resolution issue, not introduced by this diff.updateMany + WHERE clause that includes usedAt: null.AI was used for assistance.