Skip to content

Commit 5f808e2

Browse files
committed
fix(desktop): audit workspace routes too, and cover the three that bypass the chrome
Greptile was right that the blanket `workspace/` exclusion was load-bearing in the wrong direction. It assumed every workspace route reaches the lane through `WorkspaceChrome`, and three do not: the workspace landing route, the access-denied early return, and the workflow error boundary. The exclusion is gone, so workspace files are audited like everything else and `WorkspaceChrome` joins the lane-aware shells — the normal route passes through its layout, and the three exceptions had to be dealt with on their merits: - the landing route (status card and spinner) and access-denied now reserve the lane; - the error boundary is allowlisted, verified: it renders `<Sidebar>`, which already owns the workspace lane and its drag region, so padding that root would double it. Their content was centred, so the lights were never covering text — the real gap was that none of them rendered a drag strip, leaving the window immovable on those screens. The guard's granularity is per file, not per JSX root: `workspace/page.tsx` holds two full-viewport roots and still passes if only one reserves the lane. Verified by mutation and documented rather than papered over — catching it needs an AST pass, and the check's job is to stop a whole surface being forgotten, which is how every instance of this bug has actually shipped.
1 parent 8035a14 commit 5f808e2

3 files changed

Lines changed: 20 additions & 6 deletions

File tree

apps/sim/app/_shell/desktop-title-bar-surfaces.test.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,22 @@ describe('desktop title-bar surface audit', () => {
172172
*
173173
* So the check enumerates instead of listing what to look at: any new full-viewport root
174174
* fails here until it either composes `.desktop-title-bar-page` or is added below with a
175-
* reason. Reaching for this allowlist should feel like a claim you have to defend.
175+
* reason. Reaching for this allowlist should feel like a claim you have to defend — the
176+
* entry that read "marketing chrome, not reachable in the desktop shell" was false, and
177+
* hid four live surfaces behind one unverified sentence.
178+
*
179+
* Granularity is per FILE, not per JSX root: a file holding two full-viewport roots still
180+
* passes if only one reserves the lane. Catching that needs an AST pass, which is not
181+
* worth the weight here — the check's job is to stop a whole surface being forgotten,
182+
* which is how every instance of this bug actually shipped.
176183
*/
177184
const LANE_EXEMPT: Record<string, string> = {
178185
'app/(landing)/components/landing-shell/landing-shell.tsx':
179186
'Marketing chrome. Verified: every consumer lives under app/(landing)/, and the desktop shell boots to /login or a workspace with no path to those routes.',
180187
'app/playground/page.tsx':
181188
'Verified dev-only: the page calls notFound() unless NEXT_PUBLIC_ENABLE_PLAYGROUND is set.',
189+
'app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx':
190+
'Renders <Sidebar>, which owns the workspace lane and its drag region (sidebar.tsx). Padding this root too would double the reservation.',
182191
}
183192

184193
/**
@@ -188,13 +197,13 @@ const LANE_EXEMPT: Record<string, string> = {
188197
* shell's own definition file mentioning its name, would otherwise self-certify as
189198
* covered. Both mistakes were in the first draft of this check and made it unfailable.
190199
*/
191-
const LANE_AWARE_SHELL_USAGE = /<(AuthShell|LogoShell)\b/
200+
const LANE_AWARE_SHELL_USAGE = /<(AuthShell|LogoShell|WorkspaceChrome)\b/
192201

193202
describe('desktop traffic-light lane coverage', () => {
194203
it('leaves no full-viewport root outside workspace chrome unaccounted for', () => {
195204
const appDir = new URL('../', import.meta.url)
196205
const files = readdirSync(appDir, { recursive: true, encoding: 'utf8' })
197-
.filter((f) => f.endsWith('.tsx') && !f.startsWith('workspace/'))
206+
.filter((f) => f.endsWith('.tsx'))
198207
.map((f) => `app/${f}`)
199208

200209
const unaccounted = files.filter((file) => {

apps/sim/app/workspace/[workspaceId]/components/workspace-access-denied.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { ChipLink } from '@sim/emcn'
22
import { CircleAlert } from '@sim/emcn/icons'
3+
import { DesktopTitleBarLane } from '@/app/_shell/desktop-title-bar'
34

45
export function WorkspaceAccessDenied() {
56
return (
6-
<main className='flex min-h-screen items-center justify-center bg-[var(--surface-1)] p-6'>
7+
<main className='desktop-title-bar-page flex items-center justify-center bg-[var(--surface-1)] p-6'>
8+
<DesktopTitleBarLane />
79
<div className='flex max-w-md flex-col items-center gap-3 text-center'>
810
<div className='flex size-10 items-center justify-center rounded-full bg-[var(--surface-3)]'>
911
<CircleAlert className='size-[18px] text-[var(--text-icon)]' aria-hidden />

apps/sim/app/workspace/page.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { createWorkspaceContract } from '@/lib/api/contracts/workspaces'
1212
import { useSession } from '@/lib/auth/auth-client'
1313
import { recoverFromStaleSession } from '@/lib/auth/stale-session-recovery'
1414
import { WorkspaceRecencyStorage } from '@/lib/core/utils/browser-storage'
15+
import { DesktopTitleBarLane } from '@/app/_shell/desktop-title-bar'
1516
import { useWorkspacesWithMetadata } from '@/hooks/queries/workspace'
1617

1718
const logger = createLogger('WorkspacePage')
@@ -44,7 +45,8 @@ function WorkspaceStatusCard({
4445
onPrimary,
4546
}: WorkspaceStatusCardProps) {
4647
return (
47-
<main className='flex h-screen w-full items-center justify-center bg-[var(--surface-1)] p-6'>
48+
<main className='desktop-title-bar-page flex w-full items-center justify-center bg-[var(--surface-1)] p-6'>
49+
<DesktopTitleBarLane />
4850
<div className='flex max-w-md flex-col items-center gap-3 text-center'>
4951
<div className='flex size-10 items-center justify-center rounded-full bg-[var(--surface-3)]'>
5052
<CircleAlert className='size-[18px] text-[var(--text-icon)]' aria-hidden />
@@ -201,7 +203,8 @@ export default function WorkspacePage() {
201203
}
202204

203205
return (
204-
<div className='flex h-screen w-full items-center justify-center'>
206+
<div className='desktop-title-bar-page flex w-full items-center justify-center'>
207+
<DesktopTitleBarLane />
205208
<div
206209
className='size-[18px] animate-spin rounded-full'
207210
style={{

0 commit comments

Comments
 (0)