Skip to content

First signup creates the first tenant; later signups join - #702

Merged
TheGreatAxios merged 5 commits into
mainfrom
cl-7578-first-signup-is-superadmin-first-tenant-not-a-cli
Sep 10, 2026
Merged

First signup creates the first tenant; later signups join#702
TheGreatAxios merged 5 commits into
mainfrom
cl-7578-first-signup-is-superadmin-first-tenant-not-a-cli

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Linear: CL-7578

Summary

0→1 is now first signup, not boot. On an empty hub, the first OAuth/email signup mints the first tenant via native POST /api/tenants and its native owner grant is the superadmin — no Workbench admin table. Every later signup joins that root tenant as a read-only member and never mints a tenant or a Myra.

  • genesisOrJoinHubSignup (packages/onboarding/src/genesis.ts): existing-member → gated join → needs-onboarding → genesis. Slug-conflict 409 re-reads the root and joins. Signup never seeds (seeded: false always).
  • apps/hub/src/signup-tenancy.ts: native join via createPrincipalStore + principalRole (mirrors addWorkbenchMember), idempotent.
  • Join consults the signup gate: closed hubs 403 signup_not_allowed — an operator-removed member cannot self-rejoin. Genesis waives only signup_closed; email-verified and domain rules still bind the first user.
  • Genesis eligibility is "zero tenants", so users>1 && tenants===0 can no longer wedge a hub.
  • Join returns existing-member (with tenant id/slug) so read-only members never land in the owner-only onboarding wizard.
  • Boot is untouched except a test-only skipEnsureDefaultTenant seam on HubConfig: ensureDefaultTenant, runSystemSeed, and the env-credential plant still run — their removal is CL-7580/7576/7579.
  • Empty-hub email signup is allowed while the hub has zero users and zero tenants, even when signup is closed; POST /api/tenants is allowed at zero tenants.
  • Myra/core-workflow install per tenant is CL-7584; member onboarding UX beyond "you're in" is CL-7584.

Test plan

  • bun test packages/onboarding/test/genesis.test.ts packages/onboarding/test/provision.test.ts (23 pass)
  • bun test apps/hub/test/signup-genesis.test.ts (3 pass, real Postgres: genesis 1 user/1 tenant/owner; join 1 tenant/member; removed member 403)
  • bun test scripts/e2e/{smoke-onboarding,greeting-delivery,local-rip}.test.ts (3 pass, real Postgres)
  • bun run check exit 0 (pre-push hook + CI)

@linear-code

linear-code Bot commented Sep 10, 2026

Copy link
Copy Markdown

CL-7578

@TheGreatAxios
TheGreatAxios merged commit 4c88bea into main Sep 10, 2026
24 checks passed
@TheGreatAxios
TheGreatAxios deleted the cl-7578-first-signup-is-superadmin-first-tenant-not-a-cli branch September 10, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant