Resolves the slug against the tenant catalog and forwards into the integration detail page's existing add-connection flow. Unknown slugs get a not-found state. Makes the link survive sign-in: reserve connect as an org slug so cloud's callback stops reading it as an org selector, and return self-host's login to the requested path (its gate swaps the page in without ever writing a returnTo).
Showing the changes to packages/core/api/src (2 of 17 files). Show all
Unified · Split
| @@ -57,7 +57,20 @@ describe("isValidOrgSlug", () => { · 56 unmodified lines | ||
| 57 | 57 | }); |
| 58 | 58 | |
| 59 | 59 | it("reserves the segments routing depends on", () => { |
| 60 | − for (const critical of ["api", "mcp", "integrations", "policies", "login", "cdn-cgi"]) { | |
| 60 | + for (const critical of [ | |
| 61 | + "api", | |
| 62 | + "mcp", | |
| 63 | + "integrations", | |
| 64 | + "policies", | |
| 65 | + "login", | |
| 66 | + "cdn-cgi", | |
| 67 | + // The connect deep link's root. Cloud's post-auth callback reads the | |
| 68 | + // first path segment as an org selector, so leaving `connect` claimable | |
| 69 | + // made `/connect/<slug>` look like a request for an org named "connect" | |
| 70 | + // — which suppressed the active-membership fallback and could drop the | |
| 71 | + // deep link into org onboarding after sign-in. | |
| 72 | + "connect", | |
| 73 | + ]) { | |
| 61 | 74 | expect(RESERVED_ORG_SLUGS.has(critical), critical).toBe(true); |
| 62 | 75 | } |
| 63 | 76 | }); |
| @@ -17,8 +17,8 @@ const ORG_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){1,47}$/; · 16 unmodified lines | ||
| 17 | 17 | * predictably will): |
| 18 | 18 | * - App planes: api, mcp, .well-known (cloud `app-paths.ts`, selfhost |
| 19 | 19 | * envelope, cloudflare `run_worker_first`) |
| 20 | − * - Console routes: integrations, policies, secrets, tools, resume, | |
| 21 | − * plugins (the shared contract), plus host extras: | |
| 20 | + * - Console routes: connect, integrations, policies, secrets, tools, | |
| 21 | + * resume, plugins (the shared contract), plus host extras: | |
| 22 | 22 | * api-keys, org, billing, create-org, setup-mcp (cloud), |
| 23 | 23 | * admin, join, docs (selfhost), login (Better Auth |
| 24 | 24 | * `mcp({ loginPage })` + cloud/selfhost login UX) |
| @@ -41,6 +41,7 @@ export const RESERVED_ORG_SLUGS: ReadonlySet<string> = new Set([ · 16 unmodified lines | ||
| 41 | 41 | "mcp", |
| 42 | 42 | ".well-known", |
| 43 | 43 | // console + host routes |
| 44 | + "connect", | |
| 44 | 45 | "integrations", |
| 45 | 46 | "policies", |
| 46 | 47 | "secrets", |