Rework cloud org flow: onboarding page + live membership check#234
Merged
RhysSullivan merged 1 commit intomainfrom Apr 13, 2026
Merged
Rework cloud org flow: onboarding page + live membership check#234RhysSullivan merged 1 commit intomainfrom
RhysSullivan merged 1 commit intomainfrom
Conversation
Replace the callback's auto-org-creation with an explicit OnboardingPage
that AuthGate renders when a user has a session but no org. Drops the
duplicated create-org logic, the login-time upsertOrganization calls,
and the '"{name}'s Organization"' default. Users name their own org.
Add resolveOrganization helper that reads the local mirror first and
lazily falls back to WorkOS on miss, so /me and protected API routes
self-heal when the mirror is stale instead of silently returning a null
org (the bug that was routing existing users to onboarding).
Add authorizeOrganization helper that performs a live
listUserMemberships check on every protected request. A user removed
from their active org now loses access on the next request, not up to
~10 minutes later when the JWT access token naturally expires. The
extra WorkOS call is acceptable for now; can be swapped for a local
memberships table fed by the Events API as a follow-up.
Fix silent refresh failure in createOrganization: if refreshSession
returns null or yields a session still scoped to the previous org
(happens when the current session is stale — e.g. the caller was
removed from the org their cookie is pinned to), clear the cookie and
fail loudly so the frontend bounces to login instead of getting stuck
on onboarding with a successful 200 and a cookie that will never
match.
Extract CreateOrganizationForm hook + fields into a shared component
so the shell dialog and the new onboarding page reuse the same state
and styling.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🔵 In progress View logs |
executor-cloud | 551ba87 | Apr 13 2026, 10:03 PM |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | 551ba87 | Commit Preview URL Branch Preview URL |
Apr 13 2026, 10:05 PM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AuthGatenow renders a newOnboardingPagewhen the user has a session but no org. Users name their own org; the callback no longer creates orgs, no longer mirrors on login, and collapses to a linear authenticate → ensureAccount → maybe-rehydrate-from-memberships → setCookie → redirect.resolveOrganizationhelper — local mirror read with lazy WorkOS fallback + writeback. Fixes the bug where existing users were getting routed to onboarding because their session's org wasn't in the local mirror (a latent issue in the old flow too, exposed by removing the login-time upserts).authorizeOrganizationhelper — livelistUserMembershipscheck on every protected request. A user removed from their active org now loses access on their next request instead of up to ~10 minutes later when the JWT access token naturally expires.createOrganization. IfrefreshSessionreturns null or yields a session still scoped to the previous org (happens when the current session is stale — e.g. caller was removed from the org their cookie is pinned to), clear the cookie and fail loudly. The frontend bounces to login, the callback's rehydrate path picks up the new membership, user lands in the new org.CreateOrganizationFormhook + fields into a shared component so the shell dialog and the new onboarding page share the same state, validation, and styling.Known follow-ups (not in this PR)
authorizeOrganizationto read from the table. Events API fits this stack (Cloudflare Workers) better than webhooks.Test plan
/mereturnsorganization: nulland AuthGate routes to onboarding./me,switchOrganization, andorganizationsendpoints all still work with the new helpers.turbo run typecheck --filter=@executor/cloud.