Files
nexu-io__open-design/apps/web/tests/useProjectWorkspaceScope.test.tsx
lefarcen 2671061c47 fix(web): settle project workspace scope when bootstrap arrives late (#6504)
useProjectWorkspaceScope skipped its mount-time scope read whenever the
current render could seed from `initialScope`. That answer is recomputed
every render, but state is seeded only once, in the useState initializer.

App.tsx fills routeProjectSnapshotRef asynchronously, so a route bootstrap
that resolves after ProjectView mounted flips `initialScopeCanSeed` on an
already-running hook. Because it is an effect dependency, the effect re-ran,
aborted the in-flight GET /api/projects/:id/workspace-scope, and returned
without fetching or setting state — pinning `loading: true` forever.

Nothing could recover it: with no resolved scope the workspace invalidation
SSE never subscribes, so no event could bump the revision and retry. The
stuck `loading` reaches ProjectView as `workspaceContextReadOnly`, which
makes `viewerOnly` true and renders the whole workspace as a read-only
shared project — dead composer, disabled create actions — on a project the
user owns.

Key the skip on whether state was actually seeded at mount, which is what
the early return always assumed. A late bootstrap scope is now ignored and
the mount-time read settles normally.
2026-08-06 06:24:19 +00:00

22 KiB