mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
Fixes first-send 403s for multi-org users who lack `chat:create` in the deployment default organization (CODAGT-892). Two frontend defects combined to send chat creation to the wrong organization: 1. The Agents create form initialized its organization selection permission-blind to the default org and only corrected it when the `permittedOrganizations` authcheck result *transitioned*, so a fast first send raced the check, and on warm-query-cache remounts the correction never ran at all: the wrong org stayed selected permanently while the org picker was hidden. 2. The permitted-organizations authcheck itself sent no `owner_id`, so roles that grant `chat:create` at member (owner) scope, such as `agents-access` (Coder Agents User, the exact role in the customer report), were denied in every organization and the form always fell back to the default org. This part was split out and already landed on main via #28076; after rebasing, this PR relies on that fix and keeps its stricter regression stories around it. ## Changes - Derive the effective organization at render time: keep the user's explicit pick only while it is still permitted, otherwise fall back to the permitted default org, then the first permitted org, then the dashboard default. Replaces the transition-based reconciliation, which could not fire when the query cache was already warm on mount. - Keep user-driven org cleanup (workspace selection, attachments) in the picker/dialog event handlers; permission-driven changes are handled by render-time state adjustments and the attachment hook's post-commit adoption effect. - Disable Send until the permitted-organizations check settles and the attachment hook has adopted the effective org; hide the org picker and disable the workspace picker until the check settles (their pre-settlement options come from the unfiltered dashboard fallback, so a pick could persist a foreign-org workspace). - Scope persisted attachments to their organization in `useFileAttachments`: restoration defers until a permitted org is known, permission-driven org changes replace attachment state post-commit, in-flight uploads are invalidated by an adoption epoch (including A-to-B-to-A round trips), and no render exposes another org's file IDs, including when authorization resolves to no org at all. - Revalidate org-scoped state on permission refetches: a revoked explicit selection clears instead of lying latent, a settled effective-org change drops the stored workspace, and the org-change confirmation dialog closes (and re-checks on confirm) when its pending org is revoked. - Rebase reconciliation with #28076: the stories use its `permittedOrganizationsKey` helper and retain its `MemberScopedPermissionsShowOrgPicker` regression story alongside this PR's stricter member-scope stories. The backend RBAC rejection was correct; this is frontend-only. ## Testing - Red-green: every guard above was verified by reverting it and confirming exactly its guarding story or unit test fails (whole-file runs). - `pnpm -C site check`, `pnpm -C site lint`, `pnpm -C site lint:types`, full `AgentCreateForm.stories.tsx` (42 pass), `useFileAttachments.test.tsx` (8 pass), re-run after the rebase onto main. - Dogfood UAT on a licensed multi-org dev deployment at this branch: a restricted user with `agents-access` only in a non-default org sends first and warm-remount messages successfully (201, payload carries the permitted org, no 403); admin picker, workspace filtering, and attachment org-change dialog verified. Round 2 of UAT caught the missing `owner_id` (now landed via #28076); round 3 re-verified end to end. > Mux created this PR on Mike's behalf.