From 2865e9cf24f84a0f8740a9ecfdb95d4e531e790d Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 30 Jul 2026 16:05:28 -0700 Subject: [PATCH 01/12] fix(desktop): clear the traffic lights on every auth-shell surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only /login reserved the macOS traffic-light lane, so signup drew its logo underneath the lights — and so did reset-password, sso, verify, the CLI auth handoff, and the invite pages. The pre-paint script marks the lane on every desktop route, so any surface that did not reserve it overlapped. Ownership moves to `AuthShell`, which is the single source of truth for the frame all of these wear, and it now reserves unconditionally. Per-route gating was the wrong shape rather than merely incomplete: `/invite/[id]` is a dynamic segment, so no route list could have covered it. `supportsDesktopTitleBar` therefore drops its pathname argument — the caller mounting the controller is the signal, and only `AuthShell` mounts it. Workspace routes never render it and keep their existing `WorkspaceChrome`-owned listener, so the two never contend for the attribute. Off the desktop shell `--desktop-title-bar-height` is `0px`, so the reservation and the drag strip collapse to nothing and `.desktop-title-bar-page` is exactly the `min-h-screen` these surfaces had before — web is unchanged. With the prop gone the client auth layout was a bare passthrough, so the route layout renders the shell directly and the passthrough is deleted. Measured in the Electron renderer over CDP across /signup, /login, /reset-password and /cli/auth: lane 40px, logo top 56px, zero overflow on each. /invite/[id] redirects to login when signed out and was not measured directly. The surface audit gains a `stripComments` helper that every negative assertion runs through. These files document the shapes they avoid, so a bare `not.toContain` was matching the prose explaining the fix and failing on correct code. --- apps/sim/app/(auth)/auth-layout-client.tsx | 16 -------- apps/sim/app/(auth)/components/auth-shell.tsx | 26 ++++++------- apps/sim/app/(auth)/layout.tsx | 4 +- .../_shell/desktop-title-bar-surfaces.test.ts | 38 ++++++++++++------- apps/sim/app/_shell/desktop-title-bar.test.ts | 13 +++---- apps/sim/app/_shell/desktop-title-bar.tsx | 32 +++++++++------- 6 files changed, 63 insertions(+), 66 deletions(-) delete mode 100644 apps/sim/app/(auth)/auth-layout-client.tsx diff --git a/apps/sim/app/(auth)/auth-layout-client.tsx b/apps/sim/app/(auth)/auth-layout-client.tsx deleted file mode 100644 index 57c83fa152b..00000000000 --- a/apps/sim/app/(auth)/auth-layout-client.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client' - -import { usePathname } from 'next/navigation' -import { DesktopTitleBarController } from '@/app/_shell/desktop-title-bar' -import { AuthShell } from '@/app/(auth)/components' - -export default function AuthLayoutClient({ children }: { children: React.ReactNode }) { - const isLogin = usePathname() === '/login' - - return ( - <> - {isLogin && } - {children} - - ) -} diff --git a/apps/sim/app/(auth)/components/auth-shell.tsx b/apps/sim/app/(auth)/components/auth-shell.tsx index d4dd4f06521..17d237bca59 100644 --- a/apps/sim/app/(auth)/components/auth-shell.tsx +++ b/apps/sim/app/(auth)/components/auth-shell.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from 'react' -import { cn } from '@sim/emcn' import Link from 'next/link' +import { DesktopTitleBarController } from '@/app/_shell/desktop-title-bar' import { LogoMark, SimWordmark } from '@/app/(landing)/components/navbar/components' interface AuthShellProps { @@ -8,8 +8,6 @@ interface AuthShellProps { children: ReactNode /** Optional element pinned to the bottom of the shell (e.g. the support footer). */ footer?: ReactNode - /** Reserve the native macOS title-bar lane for the desktop login route. */ - reserveDesktopTitleBar?: boolean } /** @@ -21,18 +19,20 @@ interface AuthShellProps { * the canvas/`--text-primary` surface, and renders a logo-only header that reuses * the landing {@link LogoMark} + {@link SimWordmark} at the same nav gutters. The * single content column is centered and capped for a calm single-form layout. + * + * The shell also owns the macOS traffic-light lane, unconditionally — every surface that + * wears it (the `(auth)` routes, the CLI auth handoff, the invite pages) sits outside + * workspace chrome and draws its logo where the lights are. Gating this per route left + * whichever surface was overlooked drawing underneath them, and a route list could not + * cover a dynamic segment like `/invite/[id]` anyway. Off the desktop shell + * `--desktop-title-bar-height` is `0px`, so the reservation and the drag strip both + * collapse to nothing and `.desktop-title-bar-page` is exactly `min-h-screen`. */ -export function AuthShell({ children, footer, reserveDesktopTitleBar = false }: AuthShellProps) { +export function AuthShell({ children, footer }: AuthShellProps) { return ( -
- {reserveDesktopTitleBar && ( -
- )} +
+ +
}> + Loading…
} + > ) diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index dfd0428f30b..de337cc5c3e 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -490,7 +490,9 @@ export default function SignupPage({ emailSignupEnabled, }: SignupFormProps) { return ( - Loading…
}> + Loading…
} + > { expect(resourceHeader).not.toMatch(/py-\[8\.5px\]/) }) }) + +/** + * Every full-viewport page root outside workspace chrome, and why it is safe. + * + * A root that fills the viewport and is NOT lane-aware draws its top chrome underneath + * the macOS traffic lights, because the pre-paint script marks the lane on every desktop + * route whether or not the page reserves it. That is one bug that has now surfaced four + * separate times — workspace headers, signup, the CLI handoff, the OAuth error page — + * each found by a person hitting it rather than by a check. + * + * So the check enumerates instead of listing what to look at: any new full-viewport root + * fails here until it either composes `.desktop-title-bar-page` or is added below with a + * reason. Reaching for this allowlist should feel like a claim you have to defend. + */ +const LANE_EXEMPT: Record = { + 'app/(landing)/components/landing-shell/landing-shell.tsx': + 'Marketing chrome. The desktop shell boots straight to /login or a workspace and has no path to the landing routes.', + 'app/(landing)/components/logo-shell/logo-shell.tsx': + 'Marketing chrome, same reasoning as landing-shell.', + 'app/playground/page.tsx': 'Dev-only scratch route, not shipped in the desktop shell.', + 'app/(interfaces)/resume/[workflowId]/[executionId]/loading.tsx': + 'Embedded interface surface rendered inside a host page, never as the desktop window root.', +} + +describe('desktop traffic-light lane coverage', () => { + it('leaves no full-viewport root outside workspace chrome unaccounted for', () => { + const appDir = new URL('../', import.meta.url) + const files = readdirSync(appDir, { recursive: true, encoding: 'utf8' }) + .filter((f) => f.endsWith('.tsx') && !f.startsWith('workspace/')) + .map((f) => `app/${f}`) + + const unaccounted = files.filter((file) => { + const source = stripComments(read(`../${file.slice('app/'.length)}`)) + const fillsViewport = /\b(min-h-screen|h-screen)\b/.test(source) + if (!fillsViewport) return false + const laneAware = source.includes('desktop-title-bar-page') || source.includes('AuthShell') + return !laneAware && !(file in LANE_EXEMPT) + }) + + expect(unaccounted).toEqual([]) + }) +}) diff --git a/apps/sim/app/f/[token]/public-file-view.tsx b/apps/sim/app/f/[token]/public-file-view.tsx index 5d1db37b68e..7151becddd9 100644 --- a/apps/sim/app/f/[token]/public-file-view.tsx +++ b/apps/sim/app/f/[token]/public-file-view.tsx @@ -65,7 +65,7 @@ export function PublicFileView({ ) return ( -
+
{!brand.logoUrl && ( diff --git a/apps/sim/app/oauth-error/page.tsx b/apps/sim/app/oauth-error/page.tsx index 8b85f0bab51..82dc55057fb 100644 --- a/apps/sim/app/oauth-error/page.tsx +++ b/apps/sim/app/oauth-error/page.tsx @@ -36,7 +36,7 @@ export default async function OAuthErrorPage({ searchParams }: OAuthErrorPagePro const code = typeof params.error === 'string' ? params.error : undefined return ( -
+

Couldn’t complete that

{messageForError(code)}

From ff3e09758b51f647eb8a51e23c784f7eea53f4e4 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 30 Jul 2026 16:20:43 -0700 Subject: [PATCH 03/12] fix(desktop): cover the shells behind the allowlist, and make the guard fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Greptile was right on both counts, and the first one is worse than reported. `LogoShell` was allowlisted as "marketing chrome, not reachable in the desktop shell". That claim was simply false: it is the frame for `not-found`, the interfaces shell, the desktop handoff shell, and the public-file access gates — so the password, email, and SSO gates for `/f/[token]` all still drew under the traffic lights. The allowlist existed to make risk visible and instead hid four surfaces behind one unverified sentence. It now carries two entries, both checked: the landing shell (every consumer lives under `app/(landing)/`) and the playground (calls `notFound()` unless `NEXT_PUBLIC_ENABLE_PLAYGROUND` is set). The lane's two halves also travelled separately, so `/oauth-error` and the public-file view reserved the space without the drag strip — clearing the lights but leaving the window with no title bar on those pages. `DesktopTitleBarLane` now ships both together and the audit enforces the pairing. Both new checks were unfailable when first written, and mutation testing is the only reason that surfaced: - the pairing check matched `DesktopTitleBarLane` anywhere in the file, so the import line satisfied it after the JSX was deleted; - the coverage check matched `LogoShell` anywhere, so a shell's own definition file self-certified as covered. Both now match JSX usage (`/ - -
+