[FE fix] demo workspace banner issues#4475
Conversation
Two independent bugs surfaced in #bugs as the "demo workspace banner
issue":
1. URL pollution (Mahmoud's investigation). projectAtom derived
workspaceId from selectedOrgAtom, which lags /projects/ by one
/organizations/{id} fetch. During the gap, pickPreferredProject
ran with workspaceId=null and hit the cross-org
`projects.find(p => p.is_default_project)` fallback. For users
with is_demo=true membership, that returned the Demo Workspace's
default project. WorkspaceRedirect then router.replace'd to
/p/<demo-project>, pinning the URL and rendering the banner in
the wrong workspace.
Fix: projectAtom falls back to selectedOrgIdAtom (URL-derived,
resolves on first render) so workspaceId is always populated.
projectMatchesWorkspace already accepts either workspace_id or
organization_id, so the URL-derived org UUID filters correctly.
2. Banner-missing-on-reload race. Two parallel "session exists"
atoms existed — @agenta/shared/state's sessionAtom (entity
packages) and oss/state/session's sessionExistsAtom. The eager
init in appState/atoms.ts set the shared one; the oss one
waited for SessionListener's React effect. projectsQueryAtom
gated on the oss atom AND on profileQueryAtom.data.id, which
forced /projects/ to wait for /profile/ sequentially. On cold
reload the demo banner couldn't render until ~2 RTTs +
1 effect tick later.
Fix: consolidate to a single source of truth — sessionExistsAtom
is now a re-export of @agenta/shared/state's sessionAtom. The
~14 callers keep their imports unchanged. SessionListener and
useSession drop their manual dual-write code. projectsQueryAtom
drops the redundant profile.data.id gate (fetchAllProjects uses
session cookies, not user.id). Cold-reload banner now appears
after one network RTT, with the same speedup applying to every
other query gated on sessionExistsAtom (access, observability,
selectedOrg, profile).
Includes a vitest regression spec for pickPreferredProject behavior
(workspaceId=null returns cross-org demo; workspaceId scoped to own
org returns own project). web/oss has no vitest runner yet, so
*.test.ts is added to tsconfig exclude — the spec runs once vitest
is wired.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR consolidates session state to use the shared session atom across OSS, updates projects query gating to depend on session existence rather than profile data, fixes a workspaceId null fallback in project selection, and adds Vitest regression tests for pickPreferredProject. ChangesSession Consolidation and Project Selection
🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 951adb22-12e5-4c22-95c7-2a97a1a7a154
📒 Files selected for processing (7)
web/oss/src/hooks/useSession.tsweb/oss/src/state/appState/atoms.tsweb/oss/src/state/project/selectors/project.tsweb/oss/src/state/project/selectors/projectAtom.race.test.tsweb/oss/src/state/session/atoms.tsweb/oss/src/state/session/hooks.tsweb/oss/tsconfig.json
Railway Preview Environment
Updated at 2026-05-28T13:18:02.738Z |
The own-org "Default" project had is_default_project: true in the fixture, which made `projects.find(p => p.is_default_project)` (the cross-org fallback inside pickPreferredProject when workspaceId is null) return the OWN project first — not the demo one. That contradicted the "with workspaceId=null, returns demo project" assertion and meant the test wasn't locking the bug it claimed to. Mirror Mahmoud's actual /projects/ response from the investigation: own-org "Default" is_default_project=false, Demo Workspace "Default" is_default_project=true. With that ordering, the find lands on the demo project — exactly the path that pollutes the URL on cold reload.
|
Actionable comments posted: 0 |
Summary
...tba
fixes the issue reported here
Testing
QA follow-up
test the branch on staging / testing.
Checklist
Contributor Resources