fix(web): send the selected project/org on API calls, not just page loads - #30
Open
marcorivm wants to merge 1 commit into
Open
fix(web): send the selected project/org on API calls, not just page loads#30marcorivm wants to merge 1 commit into
marcorivm wants to merge 1 commit into
Conversation
…oads
Found by testing: after switching project, creating an agent put it in the
DEFAULT project, and the switcher reverted to the default until a reload.
Root cause: `proxy.ts` turns the scope cookies into X-Project-Id /
X-Organization-Id, but its matcher deliberately EXCLUDES `v1`, so the
middleware never runs on API calls. Page requests carried the selection;
every client-side call to /v1/* did not. The API's `resolveProjectId`, seeing
no header, silently fell back to the caller's default project — so writes
landed in the wrong place while the page around them looked correct.
`getProjectId()` / `getOrganizationId()` in api-fetch.ts existed for exactly
this and were `undefined` stubs (the EE build aliases the module). They now
read the cookies, and `apiFetch` attaches the headers. An explicit header from
the caller still wins, so `projects.list({ organizationId })` keeps its
account-route override.
Guarded on `document`: `getProjectId` is called from `queryKeys`' `scope()`
during render, which also runs server-side, where the answer must come from
the request headers the proxy already set.
Second bug, same symptom: both switchers read the cookie in a MOUNT effect,
which does not re-run when they write a new one — `router.refresh()` re-renders
server components but leaves client state alone. They now hold the pending
selection so the trigger updates immediately.
Side effect worth noting: with `getProjectId()` returning a real value,
`queryKeys`' `scope()` finally re-keys per project, so cached agents/secrets/
policy can no longer bleed across a switch. The `queryClient.clear()` in the
switchers is now belt-and-braces rather than the only thing preventing it —
comments corrected, since they claimed the opposite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes two bugs found in local testing. 3 files, ~60 lines. Stacked on #28.
The bug that matters
After switching project, creating an agent put it in the default project.
proxy.tsturns the scope cookies intoX-Project-Id/X-Organization-Id— but its matcher deliberately excludesv1:So the middleware never runs on API calls. Page requests carried the selection; every client-side call to
/v1/*did not.resolveProjectId, seeing no header, silently fell back tofindUserDefaultProject— so writes landed in the wrong project while the page around them looked correct. That's the worst shape for this kind of bug: no error, no visible inconsistency until you go looking for the agent.This is a hole in #23's design. I assumed the proxy covered API calls; it doesn't.
getProjectId()/getOrganizationId()inapi-fetch.tsexist for exactly this purpose and wereundefinedstubs (the EE build aliases the module away). They now read the cookies, andapiFetchattaches the headers. An explicit header from the caller still wins, soprojects.list({ organizationId })keeps its account-route override.Guarded on
typeof document—getProjectIdis called fromqueryKeys'scope()during render, which also runs server-side, where scope must come from the request headers the proxy already set.The bug that was visible
The switcher reverted to the default until a reload. Both switchers read the cookie in a mount effect, which doesn't re-run when they write a new one —
router.refresh()re-renders server components but leaves client state alone. They now hold the pending selection, so the trigger updates immediately.A comment I had backwards
With
getProjectId()returning a real value,queryKeys'scope()finally re-keys per project, so cached agents/secrets/policy can't bleed across a switch. ThequeryClient.clear()calls in both switchers are now belt-and-braces rather than the only thing preventing it — I corrected the comments, which claimed the opposite.Verification
Manual: switch project → trigger updates immediately; create an agent → lands in the selected project; reload → still selected.
Not fixed here
The
/v1/approvals/pending401 is unrelated and not a code bug — see the PR discussion. The org switcher hiding is expected when you belong to only one org.