Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: make chat model sharing work for sharers without directory access - #28542

Merged
ethanndickson merged 6 commits into
mainfrom
ethan/chat-model-acl-available
Aug 27, 2026
Merged

fix: make chat model sharing work for sharers without directory access#28542
ethanndickson merged 6 commits into
mainfrom
ethan/chat-model-acl-available

Conversation

@ethanndickson

@ethanndickson ethanndickson commented Aug 25, 2026

Copy link
Copy Markdown
Member

Problem

This is a bug fix. Chat model sharing UAT (main @ 3c32408) found two bugs when a delegated "Model Sharer" role holds only chat_model_config:read + chat_model_config:share:

This state is reachable entirely through the UI in a normal least-privilege setup:

  1. An org admin restricts Organization Settings → Workspace Sharing to none or service_accounts.
  2. Under Organization → Roles, they create a custom role with only the advanced permissions chat_model_config:read and chat_model_config:share.
  3. Under Organization → Members, they assign that role to the person responsible for managing model access.
  4. An admin creates a chat model and may initially share it with a group.
  5. The delegated sharer signs in, opens AI Settings → Models → [model] → Share model, where the failures below occur.
  • UAT-05 / UAT-08: with workspace sharing set to none, the sharing dialog errored out entirely ("Resource not found or you do not have access to this resource"). The sharer couldn't view, add, or even remove grants.
  • UAT-04: with workspace sharing set to service_accounts, existing group grants rendered as raw UUIDs, and groups didn't appear in the add-principal search.

Both have the same cause. The ACL GET returned bare UUID→role maps, so to display names (and to power its add-principal search) the dialog called the generic org directory APIs: list organization members and list groups. Those APIs require organization_member:read and group:read, which the sharer role doesn't have. Ordinary members only get them as a side effect of a different feature: OrgMemberPermissions grants member read when the org's workspace sharing mode isn't none (so users can pick coworkers to share a workspace with), and group read only when it's everyone. The chat dialog was silently borrowing those workspace-sharing permissions, so it only worked when that unrelated org setting happened to grant them:

  • none: no member read → dbauthz rejects the member listing → the dialog's query chain 404s and everything blanks (UAT-05/08).
  • service_accounts: member read but no group read → the group listing silently filters to empty → group grants can't be resolved past their UUIDs (UAT-04).

In short: an org setting about who can share workspaces was deciding whether a delegated sharer could manage a chat model ACL.

Fix

Stop borrowing directory permissions entirely; authorize everything through the model's own share permission, using the two patterns the repo already has for ACL editors:

  • Hydrate the ACL GET to return resolved users and groups instead of UUID maps, like workspaceACL and the per-chat ACL already do. Fixes the raw UUIDs.
  • Add GET .../acl/available returning assignable org members and groups for the autocomplete, modeled directly on templateAvailablePermissions (same query semantics, same share-gate-then-system-context lookup that every sibling ACL endpoint uses). Fixes candidate discovery. The new endpoint exists only because the dialog has no permission-safe way to enumerate principals today; it is plumbing for the fix, not a new feature.

This is exactly how template sharing already solves the same problem: templateACL returns hydrated principals, and templateAvailablePermissions gates on the template then does the lookups under a system context because, per its own comment, "the caller might not have permission to read all users". We differ from the template version only where newer conventions exist:

Template This PR
Gate ActionUpdate on the template (predates share) ActionShare on the model, matching the workspace/chat/MCP ACL endpoints
User candidates Site-wide GetUsers Non-system members of the model's org only
Group hydration Full member rosters Member counts, batched in one query

The dialog now runs off the hydrated ACL plus the new endpoint, so all three sharing modes take the same code path, and a discovery failure no longer blanks existing grants. OrgMemberPermissions, the directory APIs, and the PATCH (still a sparse UUID→role delta) are untouched.

Diff breakdown

+1274/−191, but only about a third is product code:

  • Product (~450): the two endpoints and hydration helpers (exp_chats_model_acl.go, ~240), the dialog rework plus a new colocated autocomplete component (~200), and SDK/site API plumbing (~60).
  • Tests (~625): backend tests updated to hydrated shapes plus new tests that reproduce the two failing UAT sharing modes end-to-end (+418), rewritten and new story play tests (+198), and query/mock updates.
  • Generated (~200): swagger, apidocs, typesGenerated.ts, API reference docs.

Depends on #28498 (stacked on the /api/v2 chat API promotion; the new endpoint is registered under both prefixes like its siblings).

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Docs preview

Check off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here.

@ethanndickson ethanndickson changed the title feat: hydrate chat model ACL and add ACL available endpoint fix: make chat model sharing work for sharers without directory access Aug 25, 2026
@ethanndickson
ethanndickson marked this pull request as ready for review August 25, 2026 12:20
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 475be16b86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 970041e861

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike force-pushed the ethan/chat-model-acl-available branch from 87f752b to 7da6bf8 Compare August 26, 2026 14:17
@ibetitsmike
ibetitsmike force-pushed the ethan/chat-model-acl-available branch from 7da6bf8 to 73e9d6b Compare August 26, 2026 16:46
Base automatically changed from mike/chat-api-v2-site to main August 26, 2026 17:24
@ibetitsmike
ibetitsmike force-pushed the ethan/chat-model-acl-available branch from 73e9d6b to 19782f1 Compare August 26, 2026 17:25
ibetitsmike added a commit that referenced this pull request Aug 26, 2026
## Summary

Adds the missing user-facing half of MCP server config ACLs: admins can
now share an MCP server with individual users and groups from the UI,
backed by a new permission-safe candidate-discovery endpoint.

## Problem

The MCP server config ACL backend already existed (share RBAC action,
hydrated `GET .../acl`, sparse `PATCH .../acl`), but there was no
frontend for it. There was also no way to populate a sharing
autocomplete without the generic organization member/group APIs, which
require `organization_member:read` and `group:read` and would wrongly
couple MCP sharing to the workspace-sharing mode (the same bug fixed for
chat models in #28542).

## Changes

Backend:

- New v2-only `GET
/api/v2/organizations/{organization}/mcp-servers/{mcpserverconfig}/acl/available`
returning `codersdk.ACLAvailable`; because this API is new, it is not
mounted under the experimental compatibility prefix. Gated on
`ActionShare` for the specific server config; performs bounded
org-scoped member/group lookups via `dbauthz.AsSystemRestricted`;
excludes system users; supports `q`, `limit`, `offset`, and `after_id`
with template/chat-model autocomplete semantics.
- Tests cover authorization (404 without share), search, pagination,
system-user exclusion, org scoping, and a share-only custom role under
all three workspace-sharing modes (`none`, `service_accounts`,
`everyone`).

Frontend:

- `shareMCPServerConfig` permission plumbing; the MCP servers list,
details page, and AI settings sidebar now admit share-only users (share
does not require update; share-only users cannot edit the server form).
- Share-only access follows the established permission contract: a
bare-share role manages sharing through the list and ACL endpoints (the
detail route still requires read, update, or delete, matching the
existing enterprise permission-matrix tests), and the disabled-config
gate now also admits the share permission so a sharer with read access
can open a disabled server. Top-level navigation (Admin settings menu
and the /ai/settings index redirect) discovers organization-level MCP
sharers and surfaces permission lookup failures instead of silently
falling back.
- "Share server" action on the MCP server edit page opening a sharing
dialog: hydrated ACL grants render from the `GET .../acl` response,
adds/removals are saved as sparse `PATCH` deltas (`"read"` / `""`).
- Principal autocomplete backed exclusively by the new `/acl/available`
endpoint; the sharing flow never calls the generic org member/group APIs
(Storybook enforces this by rejecting those API spies). A discovery
error surfaces under the autocomplete without hiding existing grants.
- Storybook interaction coverage for the dialog (hydrated rendering,
add/remove, sparse deltas, error/cancel/reopen paths, autocomplete
exclusion and failure) and share-only access to the page/form.

Dogfood UAT ran remotely against a dev instance and passed, including
verifying via the network log that candidate discovery only hits
`/acl/available`. The share-only custom role UI flow could not be
exercised there (no premium license on the dev instance); it is covered
by the backend permission-matrix tests.

> 🤖 This PR was authored by Xum (an AI coding agent) acting on Mike's
behalf.
@ibetitsmike

Copy link
Copy Markdown
Collaborator

@codex review\n\nPlease review current head .\n\n> Xum acted on Mike'''s behalf.\n

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19782f10f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator

Pushed b390553d to fix the failing pixel storybook: the ChatModelSharingDialog/Empty ACL play function asserted the query-gated empty state with a synchronous getByText, racing the mocked ACL fetch (deterministic capture failure on the last two pixel runs). It now uses await findByText.

@codex review

Please review current head b390553d28bbd0ef0e7596cb27ae52dbb4d96121.

Xum acted on Mike's behalf.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: b390553d28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator

Merged main into this branch to resolve the conflict with #28593, which refactored ChatModelSharingDialog onto the shared ResourceSharingDialog. Resolution: the dialog keeps the shared-component architecture from main and this PR's data model on top of it, mirroring MCPServerSharingDialog: hydrated ChatModelACL for the table (no more organization member/group directory queries) and ChatModelPrincipalAutocomplete backed by acl/available for discovery. All 13 dialog stories, the MCP dialog stories, tsc, and the api/chats unit tests pass on the merged tree.

The merge also carries the /api/v2 MCP ACL path fix for the test-js failure currently on main (semantic conflict between #28593 and #28498); the standalone fix for main is #28659. Once #28659 merges this hunk falls out of the diff.

@codex review

Please review current head 01189c317b5490b639c5cffc1665fb30627bc63e.

Xum acted on Mike's behalf.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 01189c317b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ibetitsmike added a commit that referenced this pull request Aug 27, 2026
## Summary

Adds the missing user-facing half of MCP server config ACLs: admins can
now share an MCP server with individual users and groups from the UI,
backed by a new permission-safe candidate-discovery endpoint.

## Problem

The MCP server config ACL backend already existed (share RBAC action,
hydrated `GET .../acl`, sparse `PATCH .../acl`), but there was no
frontend for it. There was also no way to populate a sharing
autocomplete without the generic organization member/group APIs, which
require `organization_member:read` and `group:read` and would wrongly
couple MCP sharing to the workspace-sharing mode (the same bug fixed for
chat models in #28542).

## Changes

Backend:

- New v2-only `GET
/api/v2/organizations/{organization}/mcp-servers/{mcpserverconfig}/acl/available`
returning `codersdk.ACLAvailable`; because this API is new, it is not
mounted under the experimental compatibility prefix. Gated on
`ActionShare` for the specific server config; performs bounded
org-scoped member/group lookups via `dbauthz.AsSystemRestricted`;
excludes system users; supports `q`, `limit`, `offset`, and `after_id`
with template/chat-model autocomplete semantics.
- Tests cover authorization (404 without share), search, pagination,
system-user exclusion, org scoping, and a share-only custom role under
all three workspace-sharing modes (`none`, `service_accounts`,
`everyone`).

Frontend:

- `shareMCPServerConfig` permission plumbing; the MCP servers list,
details page, and AI settings sidebar now admit share-only users (share
does not require update; share-only users cannot edit the server form).
- Share-only access follows the established permission contract: a
bare-share role manages sharing through the list and ACL endpoints (the
detail route still requires read, update, or delete, matching the
existing enterprise permission-matrix tests), and the disabled-config
gate now also admits the share permission so a sharer with read access
can open a disabled server. Top-level navigation (Admin settings menu
and the /ai/settings index redirect) discovers organization-level MCP
sharers and surfaces permission lookup failures instead of silently
falling back.
- "Share server" action on the MCP server edit page opening a sharing
dialog: hydrated ACL grants render from the `GET .../acl` response,
adds/removals are saved as sparse `PATCH` deltas (`"read"` / `""`).
- Principal autocomplete backed exclusively by the new `/acl/available`
endpoint; the sharing flow never calls the generic org member/group APIs
(Storybook enforces this by rejecting those API spies). A discovery
error surfaces under the autocomplete without hiding existing grants.
- Storybook interaction coverage for the dialog (hydrated rendering,
add/remove, sparse deltas, error/cancel/reopen paths, autocomplete
exclusion and failure) and share-only access to the page/form.

Dogfood UAT ran remotely against a dev instance and passed, including
verifying via the network log that candidate discovery only hits
`/acl/available`. The share-only custom role UI flow could not be
exercised there (no premium license on the dev instance); it is covered
by the backend permission-matrix tests.

> 🤖 This PR was authored by Xum (an AI coding agent) acting on Mike's
behalf.

(cherry picked from commit 35cbca0)
@ethanndickson
ethanndickson force-pushed the ethan/chat-model-acl-available branch from 01189c3 to 4aec269 Compare August 27, 2026 08:57
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 4aec2699bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ethanndickson and others added 6 commits August 27, 2026 09:29
The chat model sharing dialog previously required org member and group
directory reads that a delegated sharer role does not have, blanking
the dialog under restrictive workspace sharing modes and rendering
group grants as raw UUIDs.

Hydrate GET .../chats/models/{model}/acl with resolved users and
groups, and add GET .../chats/models/{model}/acl/available returning
assignable principals, both authorized solely via chat model
config share permission, mirroring templateAvailablePermissions.
The interface is only referenced inside debugPanelUtils.ts, so exporting it causes knip to report an unused export. Match the adjacent file-local view-model types.
@ethanndickson
ethanndickson force-pushed the ethan/chat-model-acl-available branch from 4aec269 to 92597c2 Compare August 27, 2026 09:33
@ethanndickson
ethanndickson merged commit d0e2234 into main Aug 27, 2026
27 checks passed
@ethanndickson
ethanndickson deleted the ethan/chat-model-acl-available branch August 27, 2026 09:49
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants