diff --git a/.changeset/remove-legacy-register-flow.md b/.changeset/remove-legacy-register-flow.md
new file mode 100644
index 00000000000..7d03565fe72
--- /dev/null
+++ b/.changeset/remove-legacy-register-flow.md
@@ -0,0 +1,5 @@
+---
+"dashboard": patch
+---
+
+Removed the legacy session-aware `/register` compatibility flow. Stale links now redirect directly to `/sign-up`.
diff --git a/client/dashboard/src/components/page-templates/centered-page.tsx b/client/dashboard/src/components/page-templates/centered-page.tsx
index 430e51d3dd8..50dac89d678 100644
--- a/client/dashboard/src/components/page-templates/centered-page.tsx
+++ b/client/dashboard/src/components/page-templates/centered-page.tsx
@@ -1,6 +1,6 @@
/**
* CenteredPage — the shell for full-viewport, standalone pages rendered outside
- * the main app layout: auth (login/register/signup), demo redirects, access
+ * the main app layout: auth (login/signup), demo redirects, access
* requests, not-found, policy acknowledgements.
*
* These already share two shells; this names them as the canonical choice so a
diff --git a/client/dashboard/src/pages/login/Register.test.tsx b/client/dashboard/src/pages/login/Register.test.tsx
deleted file mode 100644
index caffeea86f0..00000000000
--- a/client/dashboard/src/pages/login/Register.test.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { cleanup, render, screen } from "@testing-library/react";
-import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
-
-import Register from "./Register";
-
-const mocks = vi.hoisted(() => ({
- useSearchParams: vi.fn(),
- useSession: vi.fn(),
-}));
-
-vi.mock("@/contexts/Auth", () => ({ useSession: mocks.useSession }));
-vi.mock("react-router", () => ({
- Navigate: ({ to }: { to: string }) => (
-
- ),
- useSearchParams: mocks.useSearchParams,
-}));
-function renderAt(path: string) {
- const [, search = ""] = path.split("?");
- mocks.useSearchParams.mockReturnValue([new URLSearchParams(search), vi.fn()]);
- render();
-}
-
-let originalLocation: Location | undefined;
-
-beforeEach(() => {
- originalLocation = window.location;
- // @ts-expect-error test-only location replacement for same-origin URL parsing
- delete window.location;
- Object.defineProperty(window, "location", {
- configurable: true,
- value: { origin: "https://app.example" },
- });
-});
-
-afterEach(() => {
- cleanup();
- if (originalLocation) {
- Object.defineProperty(window, "location", {
- configurable: true,
- value: originalLocation,
- });
- }
- vi.clearAllMocks();
-});
-
-describe("Register", () => {
- it("redirects logged-out /register traffic to /sign-up", () => {
- mocks.useSession.mockReturnValue({ session: "", activeOrganizationId: "" });
-
- renderAt("/register?redirect=%2Fcli%2Fcallback");
-
- expect(screen.getByTestId("navigate").getAttribute("data-to")).toBe(
- "/sign-up?redirect=https%3A%2F%2Fapp.example%2Fcli%2Fcallback",
- );
- });
-
- it("preserves assistants disposition", () => {
- mocks.useSession.mockReturnValue({ session: "", activeOrganizationId: "" });
-
- renderAt("/register?disposition=assistants");
-
- expect(screen.getByTestId("navigate").getAttribute("data-to")).toBe(
- "/login?disposition=assistants",
- );
- });
-
- it("drops an external legacy redirect", () => {
- mocks.useSession.mockReturnValue({ session: "", activeOrganizationId: "" });
-
- renderAt("/register?redirect=https%3A%2F%2Fevil.example");
-
- expect(screen.getByTestId("navigate").getAttribute("data-to")).toBe(
- "/sign-up",
- );
- });
-
- it("redirects an authenticated session with an organization to the root", () => {
- mocks.useSession.mockReturnValue({
- session: "",
- activeOrganizationId: "",
- });
-
- renderAt("/register");
-
- expect(screen.getByTestId("navigate").getAttribute("data-to")).toBe("/");
- expect(screen.queryByTestId("register-panel")).toBeNull();
- });
-
- it("preserves the path, search, and hash for an authenticated redirect", () => {
- mocks.useSession.mockReturnValue({
- session: "",
- activeOrganizationId: "",
- });
-
- renderAt(
- "/register?redirect=https%3A%2F%2Fapp.example%2Fprojects%2Fdefault%3Ftab%3Dtools%23details",
- );
-
- expect(screen.getByTestId("navigate").getAttribute("data-to")).toBe(
- "/projects/default?tab=tools#details",
- );
- });
-});
diff --git a/client/dashboard/src/pages/login/Register.tsx b/client/dashboard/src/pages/login/Register.tsx
deleted file mode 100644
index 019cd0d2e3b..00000000000
--- a/client/dashboard/src/pages/login/Register.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { useSession } from "@/contexts/Auth";
-import { safeSameOriginPath, safeSameOriginUrl } from "@/lib/safe-external-url";
-import { Navigate, useSearchParams } from "react-router";
-
-export default function Register(): JSX.Element {
- const session = useSession();
- const [searchParams] = useSearchParams();
-
- const disposition = searchParams.get("disposition");
- if (disposition === "assistants") {
- return (
-
- );
- }
-
- const rawRedirect = searchParams.get("redirect");
- const redirect = safeSameOriginUrl(rawRedirect);
- const signUpTarget = redirect
- ? "/sign-up?redirect=" + encodeURIComponent(redirect)
- : "/sign-up";
-
- if (session.session === "" || session.activeOrganizationId === "") {
- return ;
- }
-
- return ;
-}
diff --git a/client/dashboard/src/pages/login/components/terms-footer.tsx b/client/dashboard/src/pages/login/components/terms-footer.tsx
index b167602edad..e15fc620e09 100644
--- a/client/dashboard/src/pages/login/components/terms-footer.tsx
+++ b/client/dashboard/src/pages/login/components/terms-footer.tsx
@@ -1,6 +1,6 @@
import { cn } from "@/lib/utils";
-// Legal footer shared by every auth surface (login/register shell and the
+// Legal footer shared by every auth surface (login/signup shell and the
// demo-gate AuthLayout) so the links and copy stay in one place.
export function TermsFooter({
className,
diff --git a/client/dashboard/src/routes.tsx b/client/dashboard/src/routes.tsx
index 5b1807fe5e4..83f3e8ae898 100644
--- a/client/dashboard/src/routes.tsx
+++ b/client/dashboard/src/routes.tsx
@@ -1,7 +1,7 @@
import { Icon, IconProps } from "@/components/ui/Icon";
import { IconName } from "@/components/ui/Icon/names";
import React, { useMemo } from "react";
-import { Link, useLocation, useNavigate } from "react-router";
+import { Link, Navigate, useLocation, useNavigate } from "react-router";
import { ReleaseStage } from "./components/release-stage-badge";
import { useSlugs } from "./contexts/Sdk";
import { cn } from "./lib/utils";
@@ -42,7 +42,6 @@ import Home from "./pages/home/Home";
import { ProjectGuidePage } from "./components/project-guide/ProjectGuidePage";
import Integrations from "./pages/integrations/Integrations";
import Login from "./pages/login/Login";
-import Register from "./pages/login/Register";
import ExploreDemo from "./pages/demo/ExploreDemo";
import SignUp from "./pages/login/SignUp";
import { LogsRoot } from "./pages/logs/Logs";
@@ -236,7 +235,7 @@ const ROUTE_STRUCTURE = {
register: {
title: "Register",
url: "/register",
- component: Register,
+ component: () => ,
unauthenticated: true,
},
exploreDemo: {