The org-slug column was nullable and the runtime self-healed it: every resolveOrganization (and the SSR gate) lazily minted a slug for any row that lacked one. That left a permanent nullable state and a heal-on-read cost. Move slug generation to the single moment a row is inserted — upsertOrganization mints the slug at INSERT (ON CONFLICT DO NOTHING absorbs the id/slug races, retrying with a fresh candidate) and keeps the existing slug on conflict. The three insert sites (createOrganization, acceptInvitation, the WorkOS-fallback upsert in resolveOrganization) all get a slug for free; resolveOrganization and the SSR gate's organizationDisplay no longer heal. The schema column is now NOT NULL (migration 0004), backfilled once for legacy rows. Deploy order matters and is documented in the backfill script: backfill → deploy this code → apply 0004. The old code inserts a NULL slug then heals, so NOT NULL cannot land while it still serves. Also adds e2e/cloud/auth-routing-flow.test.ts: one browser session walking the whole arc — signed out → /login → hosted-AuthKit sign-in → org-less onboarding → create org → canonical /<slug> dashboard — through the real dev-server SSR gate. The hops are covered piecewise elsewhere; this is the narrative regression guard and the only test pinning the bare-/ → /<slug>/ dashboard canonicalization a fresh login lands on.
Showing the changes to apps/cloud/src/api (1 of 13 files). Show all
Unified · Split
| @@ -50,7 +50,7 @@ const stubUsers = Layer.succeed(UserStoreService)({ · 49 unmodified lines | ||
| 50 | 50 | getAccount: async (id: string) => ({ id, createdAt }), |
| 51 | 51 | upsertOrganization: async (org: { id: string; name: string }) => ({ |
| 52 | 52 | ...org, |
| 53 | − slug: null, | |
| 53 | + slug: `org-slug-${org.id}`, | |
| 54 | 54 | createdAt, |
| 55 | 55 | }), |
| 56 | 56 | getOrganization: async (id: string) => ({ |
| @@ -65,11 +65,6 @@ const stubUsers = Layer.succeed(UserStoreService)({ · 8 unmodified lines | ||
| 65 | 65 | slug, |
| 66 | 66 | createdAt, |
| 67 | 67 | }), |
| 68 | − ensureOrganizationSlug: async (org: { id: string; name: string; slug: string | null }) => ({ | |
| 69 | − ...org, | |
| 70 | − slug: org.slug ?? `org-slug-${org.id}`, | |
| 71 | − createdAt, | |
| 72 | − }), | |
| 73 | 68 | }), |
| 74 | 69 | ), |
| 75 | 70 | }); |