You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Workspace: the rail's Info body renders a failed agent-page fetch as an empty agent #2597
Found during the /review pass on the ent#547 + #2580 branch. Pre-existing (it was true of the Agent-details panel too), but ent#547 widens the exposure, so it is filed rather than fixed in that PR.
What happens
src/frontend/src/components/portal/PortalAgentDetails.vue:207 destructures only what it renders:
usePortalAgentPage also returns error and loaded, and neither is read. The component's only failure surfaces (LoadFailed, InlineError) belong to the Reports section, which is a different fetch.
So when GET /api/enterprise/client-portal/agents/{name}/page fails, the Info body renders a plausible-looking agent instead of saying so:
identity falls back to the slug, description blank;
"This agent hasn't published anything it can do yet" — a positive statement the client has no evidence for;
"Your chats" still works (it is a slice of the shell's thread list, not this fetch), which makes the rest read as loaded.
Why ent#547 widens it
It was one panel about the active agent, whose band sat right beside it and does render InlineError for the same failed fetch. The band is now a separate mount with its own load(), so it can succeed while a body fails.
PortalRailInfo renders one body per participant in a room. Each issues its own /page call, so N independent chances to fail silently — including for a participant that is in the room but off the viewer's roster, where _require_roster returns a uniform 404 by design.
Suggested fix
Read error (and loaded) in PortalAgentDetails and render the existing LoadFailed / InlineError primitive with the composable's reload, per the ent#253 rule the band already follows: a failed refresh keeps the data it has and says so beside it; a failed first load says it failed rather than rendering an empty agent. Gate on the loaded verdict, not on loading (#2540/#1927 — and the loadingGateRatchet counts bare loading gates).
Not a security issue
The 404 discloses nothing: the participant name is already visible in the room header, and client_portal/router.py::_require_roster is access-first with a uniform 404. This is honest-status only.
Activity
fix(workspace): the band's failure arm is a sibling of the stat row, …
fix(workspace): the band's failure is an arm inside the row, keeping …
fix(workspace): a failed agent-page fetch says so instead of renderin…