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

Skip to content

feat: use organization-scoped chat models - #27960

Merged
ethanndickson merged 4 commits into
ethan/codagt-709-model-config-apifrom
ethan/codagt-709-model-config-frontend
Aug 24, 2026
Merged

feat: use organization-scoped chat models#27960
ethanndickson merged 4 commits into
ethan/codagt-709-model-config-apifrom
ethan/codagt-709-model-config-frontend

Conversation

@ethanndickson

@ethanndickson ethanndickson commented Aug 10, 2026

Copy link
Copy Markdown
Member

Move chat model settings to /ai/settings/organizations/:organization/models, add an organization switcher, and redirect legacy settings paths. The pages use organization permissions for read, create, update, and delete controls. They use redacted provider descriptors.

Agent creation loads models for the selected organization. Existing chats load models for the chat organization. Chat views warn about unavailable historical models, select a usable local recovery model, and disable generation when none exists. Settings that aggregate organizations retain successful results when one request fails.

Depends on #27959

This pull request description was generated by Coder Agents.

@linear-code

linear-code Bot commented Aug 10, 2026

Copy link
Copy Markdown

CODAGT-709

@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 0505466 to 143f1aa Compare August 10, 2026 06:57
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 143f1aa to 5413373 Compare August 10, 2026 10:43
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 5413373 to 4394a8f Compare August 10, 2026 13:33
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 4394a8f to 8c54edb Compare August 10, 2026 23:52
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch 2 times, most recently from 3a23489 to 6d5cda4 Compare August 11, 2026 00:14
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 6d5cda4 to c05908d Compare August 11, 2026 13:18
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch 2 times, most recently from 65ff6ac to cfd9238 Compare August 18, 2026 06:53
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from cfd9238 to 9cea220 Compare August 18, 2026 08:18

Copy link
Copy Markdown
Member Author

@codex review

Copy link
Copy Markdown
Member Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Chat: Review posted | View chat
Requested: 2026-08-19 18:45 UTC by @ethanndickson

Review history
  • R1 (2026-08-18): 18 reviewers, 15 Nit, 2 Note, 14 P2, 15 P3, 1 P4, REQUEST_CHANGES. Review
  • R2 (2026-08-19), 15 Nit, 2 Note, 14 P2, 15 P3, 1 P4, COMMENT. Review

deep-review v0.9.0 | Round 2 | 05c4973..1f9dbc7

Last posted: Round 2, 47 findings (14 P2, 15 P3, 1 P4, 15 Nit, 2 Note), COMMENT. Review

Finding inventory

Finding inventory - PR #27960

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P2 Author fixed (R2, 64c92b5) router.tsx:517 Legacy /ai/settings/models/:modelId silently misdirects to default-org, UpdateModelPage bounces to list R1 Kite P2, Mafuuu P3, Pariston P3, Nami P3, Chopper P3, Meruem P3, Razor P3, Hisoka(NoteChain) Yes
CRF-2 P2 Author fixed (R2, 64c92b5) router.tsx:512 AISettingsModelsRedirect blocks navigation on error even when cached organization data is usable R1 Hisoka P3 (external codex P2 convergent) Yes
CRF-3 P2 Author contested R2 (overrides scoped to default org by product decision) CoderAgentsPage.tsx:38 Deployment-wide overrides silently restrict to default-org models; non-default-org models invisible R1 Pariston P2, Nami P2, Meruem P2, Zoro P2, Razor P3, Kurapika Note Yes
CRF-4 P2 Author fixed (R2, 64c92b5) AISettingsSidebarView.tsx:59 "Models" nav item never highlights because redirect target diverges from href R1 Nami P2, Kite P2 Yes
CRF-5 P2 Author fixed (R2, 64c92b5) useOrganizationChatModels.ts:18 isLoading flips false as soon as first org query returns; consumers publish incomplete lists R1 Komugi P2, Hisoka P3, Chopper Note Yes
CRF-6 P2 Author fixed (R2, 64c92b5) useOrganizationChatModels.ts:5 O(N) per-mount fanout replaces single request; invalidations amplify N-fold across open tabs R1 Kite P2, Pariston P3, Zoro P3, Nami Nit, Meruem Note, Razor Note Yes
CRF-7 P2 Author fixed (R2, 64c92b5) AgentSettingsUserAgentsPageView.tsx:96 Broken banner text, undated release promise, silently hides non-default-org override loss R1 Leorio P2, Chopper P3, Meruem P3, Netero P3, Kite P3, Hisoka Nit, Zoro Nit Yes
CRF-8 P2 Author fixed (R2, 64c92b5) AgentChatPage.tsx:1990 chatRuntimeModels error added to fallthrough gate blocks message viewing on models-endpoint hiccup R1 Chopper P2, Hisoka Nit Yes
CRF-9 P2 Author fixed (R2, has_effective_api_key added) providerStates.ts:55 Bedrock ambient credentials signal dropped; providers with central_api_key_enabled + no stored key become unmanageable R1 Razor P2 Yes
CRF-10 P2 Author fixed (R2, 64c92b5) AgentChatPage.tsx:1393 unavailableModelNotice tells BYOK users to ask admin when they can add their own API key R1 Pariston P2 Yes
CRF-11 P2 Author fixed (R2, 64c92b5) modelOptions.ts:143 nilUUID declaration placed between JSDoc and resolveModelOptionId; docstring orphans onto constant R1 Gon P2 Yes
CRF-12 P2 Author fixed (R2, 64c92b5) OrganizationAutocomplete.tsx:47 Sort-rationale comment paraphrases the code above; category-bearing content is one clause R1 Gon P2 Yes
CRF-13 P2 Author fixed (R2, 64c92b5) useOrganizationChatModels.test.tsx:24 Only tests happy path; error/partialError split (the hook's raison d'etre) never observed R1 Bisky P2, Netero Nit Yes
CRF-14 P2 Author contested R2 (rejects shared abstraction, prefers direct queries) AddModelPage.tsx:45 AddModelPage/UpdateModelPage duplicate paired-query fetch + loadError/refetchError computation verbatim R1 Robin P2, Zoro Nit Yes
CRF-15 P3 Author fixed (R2, 64c92b5; optionsTabbable opt-in) OrganizationAutocomplete.tsx:107 tabIndex={0} added unconditionally on shared component; regresses tab flow in all other consumers R1 Nami P3 Yes
CRF-16 P3 Author fixed (R2, 64c92b5) AgentChatPage.tsx:974 chatRuntimeModels/runtimeModelConfigs invent "runtime" naming not used by API, query builder, or codebase R1 Gon P3 Yes
CRF-17 P3 Author fixed (R2, 64c92b5; renamed to ForOrganization) modelOptions.ts:172 "Local" jargon in getUsableLocalDefaultModelID leaks into user-visible notices R1 Gon P3, Leorio P3 Yes
CRF-18 P3 Author fixed (R2, 64c92b5; shared NIL_UUID) modelDisplayName.ts:4 nilUUID literal duplicated across three files R1 Gon P3, Robin P3 Yes
CRF-19 P3 Author fixed (R2, 1f9dbc7; modelConfigId -> modelId) chats.ts (queries) Mutation names + payload field still say "ModelConfig" after API renamed to "ChatModel" R1 Gon P3 Yes
CRF-20 P3 Author fixed (R2, 64c92b5; docstring added) useOrganizationChatModels.ts:15 error vs partialError on exported hook has subtle semantics with no doc; future callers will misuse R1 Gon P3 Yes
CRF-21 P3 Author fixed (R2, 64c92b5; policy comment restored) AgentChatPage.tsx:1766 Edit-message override policy changed; comment that documented the pre-change rule was removed together R1 Gon P3 Yes
CRF-22 P3 Author fixed (R2, 64c92b5; AISettingsModelsRedirect.test.tsx added) router.tsx:495 AISettingsModelsRedirect has no story or test; three branches ship uncovered R1 Netero P3 Yes
CRF-23 P3 Author fixed (R2, 64c92b5) AgentCreateForm.tsx:393 Effect wipes localStorage.lastModelConfigID whenever the switched-to org lacks the stored id R1 Hisoka P3 Yes
CRF-24 P3 Author fixed (R2, 64c92b5) modelOptions.ts:337 resolveModelSelector doc claims it folds three loading states; body folds two after refactor R1 Leorio P3 Yes
CRF-25 P3 Author fixed (R2, 64c92b5; rationale note restored) modelOptions.ts (removed) Deleted comment explained why two provider-info variants exist; variants remain, rationale gone R1 Leorio P3 Yes
CRF-26 P3 Author fixed (R2, 64c92b5; wording revised) AgentChatPage.tsx:1391 "Unavailable in this organization" banner also fires for models that exist but are toggled off R1 Razor P3 Yes
CRF-27 P3 Author fixed (R2, 64c92b5; resolveSecond deferred promise) useOrganizationChatModels.test.tsx:58 waitFor gate is one query but assertion is two; test flakes on schedulers that split renders R1 Komugi P3 Yes
CRF-28 P3 Author fixed (R2, 4e2db7e/64c92b51fd; accessibleModelOrganizations gate) Navbar.tsx:36 Nav gate uses site-scope canAccessAnyChatModelConfig; per-org grantees hidden from all discovery surfaces R1 Mafuuu P3, Hisoka Note Yes
CRF-29 P3 Author fixed (R2, 64c92b5; collapsed to single query) AgentSettingsUserAgentsPage.tsx:21 Runs availableChatModels and organizationChatModels for the same default org; overlapping data, two states can disagree R1 Zoro P3 Yes
CRF-30 Nit Author fixed (R2, 64c92b5; renamed to candidate) modelOptions.ts:275 getModelOptionsFromConfigs shadows outer config loop variable inside .filter callback R1 Netero Nit Yes
CRF-31 Nit Open (silent R2) testFixtures.ts (removed) Multi-line explanation above mockOrphanedModel deleted; fixture importable without caller-facing constraint R1 Netero Nit Yes
CRF-32 Nit Author fixed (R2, 64c92b5) ModelsPageView.stories.tsx:109 CreateOnlyUserCanAdd redeclares meta default canCreateModel: true R1 Netero Nit Yes
CRF-33 Nit Author fixed (R2, 64c92b5) OrganizationAutocomplete.tsx:50 [...options].sort() should be options.toSorted() per codebase convention R1 Ging-ts Nit Yes
CRF-34 Nit Author fixed (R2, 4e2db7e/64c92b51fd) ModelsPage.tsx:22 .slice().sort() should be .toSorted() per codebase convention R1 Ging-ts Nit Yes
CRF-35 Nit Author fixed (R2, 64c92b5) organizationModels.tsx:55 Context invariant message breaks "useX must be used within Y" convention R1 Leorio Nit, Gon Nit Yes
CRF-36 Nit Author fixed (R2, 64c92b5; doc added) modelOptions.ts:162 isUnavailableHistoricalModelID has no doc; empty and nilUUID special cases non-obvious R1 Leorio Nit Yes
CRF-37 Nit Author fixed (R2, 64c92b5; renamed + doc added) modelOptions.ts:174 getUsableLocalDefaultModelID has no doc; disabled-default silently returns "" R1 Leorio Nit Yes
CRF-38 Nit Open (silent R2) modelOptions.ts:264 getModelOptionsFromConfigs re-filters by organization_id (server invariant); dead defense hides assumption R1 Mafuuu Nit, Razor Note Yes
CRF-39 Nit Author fixed (R2, 1f9dbc7) testFixtures.ts:9 MockOpenAIProviderDescriptor is a local redeclaration of shared MockChatModelProviderDescriptor R1 Robin Nit Yes
CRF-40 Nit Author contested R2 (routes stay explicit because :modelId route needs the named param) router.tsx:803 Three separate route entries render AISettingsModelsRedirect; collapse to models/* R1 Zoro Nit Yes
CRF-41 Nit Author fixed (R2, 64c92b5; getDefaultOrganizationId helper) CoderAgentsPage.tsx:39 organizations.find(is_default)?.id ?? "" duplicated; getDefaultOrganizationId helper missing R1 Zoro Nit Yes
CRF-42 P4 Open (silent R2) chats.ts:2153 chatModelKey and organizationChatModelsKey share prefix depth without discriminator; brittle key shape R1 Nami P4, Kite Nit, Gon Note Yes
CRF-43 Nit Author fixed (R2, 1f9dbc7; renamed to accessibleModelOrganizations) organizations.ts:151 canAccessOrganizationChatModelConfigs includes view-only callers; "manageable" name overpromises R1 Razor Nit Yes
CRF-44 Nit Author fixed (R2, 1f9dbc7) organizationModels.tsx:30 Empty state "Ask an organization administrator" wrong for site-owner/auditor path R1 Razor Nit Yes
CRF-45 Nit Author contested R2 (rejects hyper-specific fallback-chain tests) modelDisplayName.test.ts:5 Test covers three of five branches in getModelDisplayName; fallback chain untested R1 Bisky Nit Yes
CRF-46 Note Author contested R2 (generic label preserves org-local access; avoids leaking metadata) modelDisplayName.ts:19 "Unavailable model" label ambiguous: transient during fetch, cross-org shared chats, missing read grant R1 Mafuuu Note, Pariston Note Yes
CRF-47 Note Open (silent R2) UpdateModelPage.tsx:85 Silently swallows "model not found" via Navigate to modelsPath replace R1 Hisoka Note Yes

Round log

Round 1

Netero-only pre-panel gate: 2 P3, 4 Nit findings. Passed to panel.
Law: advisory split verdict; effective +3128 -1629 in 72 files, single risk domain, atomic backend coupling with #27959.
Panel: 18 reviewers (Bisky, Chopper, Ging-react, Ging-ts, Gon, Hisoka, Kite, Komugi, Kurapika, Leorio, Mafu-san, Mafuuu, Meruem, Nami, Pariston, Razor, Robin, Zoro).
Ging-react and Kurapika found no defects; Kurapika reported multiple Notes as security posture confirmations.
Cross-check surfaced strong convergence on 7 major themes: legacy-redirect bookmark loss, cached-data error handling, CoderAgents default-org narrowing, sidebar highlight, useOrganizationChatModels lifecycle + scale, UserAgents banner + override loss, redundant chatRuntimeModels error gate. All raised to P2 by tiebreak or independent P2 rating.
14 P2, 15 P3, 12 Nit, 1 P4, 2 Note. Zero dropped. Process observations (empty commit bodies, commit fdc9d69 bundling new authz surface, commit 9cea220 same-PR fixup) folded into review body.
Reviewed against 1c366f3..9cea220.

Round 2 update

BLOCKED. Churn guard classified 38 addressed, 5 contested, 4 silent, 0 acknowledged, 0 deferred.
Silent findings: CRF-31 (mockOrphanedModel Nit), CRF-38 (getModelOptionsFromConfigs re-filter Nit), CRF-42 (chatModelKey prefix depth P4), CRF-47 (UpdateModelPage silent Navigate Note).
Contested findings pending panel judgment: CRF-3 (deployment-wide override scope P2), CRF-14 (AddModelPage/UpdateModelPage duplication P2), CRF-40 (three route entries Nit), CRF-45 (modelDisplayName fallback tests Nit), CRF-46 (Unavailable label ambiguity Note).
Author fix commits: aa2e7a9 (feat rewrite), 4e2db7e, d914352, 78d6ef4, 64c92b5, 1f9dbc7. Rebase moved base from 1c366f3 onto 05c4973 (backend #27959 landed).
Base renames observed (not part of author fix chain): AISettingsSidebar extracted from AISettingsSidebarView; AISettingsIndexRedirect and AISettingsModelsRedirect moved to their own files; NoManageableModelOrganizations -> NoAccessibleModelOrganizations; manageableModelOrganizations -> accessibleModelOrganizations.
No panel spawn. No Netero. Reviewed against 05c4973..1f9dbc7.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@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: 9cea2208d6

ℹ️ 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".

Comment thread site/src/router.tsx Outdated
Comment thread site/src/router.tsx Outdated
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 9cea220 to a51bbfa Compare August 18, 2026 08:42

@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: ca70e01502

ℹ️ 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".

Comment on lines +48 to +51
organizations.map((organization) => [
organization.id,
organization.display_name,
]),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fall back to the organization slug in compaction rows

When an organization was created without the optional display_name, this map stores an empty string even though organization.name is available. UserCompactionThresholdSettings treats that empty value as resolved, so it renders no organization subtitle and generates labels ending in for . If multiple organizations expose similarly named models, users cannot tell which organization's threshold they are editing and may save the override for the wrong model; use organization.display_name || organization.name here.

Useful? React with 👍 / 👎.

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: ca70e01502

ℹ️ 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".

Comment thread site/src/pages/AgentsPage/components/AgentCreateForm.tsx
Comment thread site/src/pages/AISettingsPage/ModelsPage/ModelsPageView.tsx
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from ca70e01 to 7142fa4 Compare August 24, 2026 09:05
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 7142fa4 to 2db9e5b Compare August 24, 2026 09:30
@ethanndickson
ethanndickson force-pushed the ethan/codagt-709-model-config-frontend branch from 2db9e5b to 334fbdb Compare August 24, 2026 09:43
@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: 334fbdbd0e

ℹ️ 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".

Comment thread site/src/pages/AISettingsPage/ModelsPage/AddModelPage/AddModelPage.tsx Outdated
@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: 91c4fa41f0

ℹ️ 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".

Comment on lines +46 to +47
const canViewModels =
!canViewAISettings && accessibleModelOrgsQuery.organizations.length > 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route model-only access through existing AI settings

For a member whose model visibility comes only from a model ACL, canAccessAnyModel and the other global AI permissions are false, but a successful organization probe makes canViewModels true while leaving canViewAISettings false. Checked NavbarView and MobileMenu: this combination hides Admin settings and adds Models as a standalone dashboard destination, so these users cannot follow the same commit's documented Admin settings > AI > Models navigation. Include accessible organization models in canViewAISettings and reuse the existing AI settings navigation instead.

AGENTS.md reference: site/AGENTS.md:L9-L9

Useful? React with 👍 / 👎.

@ethanndickson
ethanndickson merged commit 75ad451 into main Aug 24, 2026
29 checks passed
@ethanndickson
ethanndickson deleted the ethan/codagt-709-model-config-frontend branch August 24, 2026 10:20
ethanndickson added a commit that referenced this pull request Aug 24, 2026
Adds audit logging for chat model config creates, updates, deletes, ACL
changes, and automatic default-model transitions. Audit records use the
config display name or ID as the target and are emitted only after
successful transactions.

Depends on #27960.
ethanndickson added a commit that referenced this pull request Aug 24, 2026
## Summary

Repair the Storybook interaction and Pixel failures currently present on
`main`. The failures came from organization-scoped model changes leaving
stories with incomplete providers and query fixtures, product copy and
route changes leaving stale assertions, and several interaction tests
depending on implementation details or teardown timing.

## Broken stories and fixes

### Organization-scoped chat models

PR #27960 introduced organization-scoped chat models and the following
regressions:

- `OrganizationModelsLayout / Switch Organization Preserves Auxiliary
Parameters`, `Invalid Requested Organization Falls Back To Default`,
`Invalid Requested Organization Denies Add`, `Duplicate Display Names
Are Disambiguated`, and `No Readable Organization Is Not Found`: the
stories only populated permission query keys for individual
organizations, while the accessible-organization lookup requests
authorization for all visible organization IDs together. The unmatched
`/api/v2/authcheck` request returned a Storybook proxy 502, so the
layout rendered an error instead of the intended picker, fallback,
denied, disambiguation, or not-found state. Add fixtures for the
combined organization-permission keys, preserve the intentionally denied
permission map, and return an explicit empty authorization result for
the no-readable-organization case.
- `ModelFormProviderConfig / Provider Config Open AI`, `Provider Config
Anthropic`, and `Provider Config Open AI Web Search`: `ModelForm` began
consuming `OrganizationModelsContext`, but these stories were not
wrapped in its provider and rendered the router error boundary. Add the
same organization-model context decorator used by the sibling model form
stories.
- `AgentChatPage / Queued For Capacity After Polling`: the story
retained a manually assembled chat-and-messages fixture after the page
gained organization-model, provider, workspace, prompt, diff, chat-list,
and authorization dependencies. Those missing queries prevented the
polling request from being reached. Replace the partial fixture list
with the shared `buildQueries()` setup.
- `DashboardLayout / Custom Organization Role Can Open Models`,
`DashboardLayout / ACL Readable Member Can Open Models`, and `NavbarView
/ For Member With Model Access`: these stories also landed in #27960 and
inherited Pixel's tablet-and-desktop matrix, but their play functions
exercise the desktop `Models` link. Pixel's 744px tablet viewport
renders that link inside the closed mobile menu, so the desktop query
always failed there. Restrict these authorization-to-navigation stories
to the desktop matrix; mobile Models navigation remains covered by the
dedicated `MobileMenu` story.

### Premium copy and navigation

- `DeploymentSidebarView / Premium Tab Visible` and `Premium Tab
Hidden`: PR #28226 renamed the production navigation item from `Premium`
to `Trial Upgrade`, but added stories that still queried the old name.
Update both the positive and negative assertions so the hidden-state
story cannot pass while the real CTA is present.
- `PremiumPageView / No License`: PR #28226 changed the production
heading to `Start an unlimited 30-day Coder trial` while the story
asserted the previous Premium wording. Update the accessible heading
assertion to the rendered copy.
- `AgentChatPageView / Queued For Capacity Community Admin`: PR #28437
intentionally moved the trial CTA from `https://coder.com/trial` to the
internal `/deployment/premium` route, leaving the story's href assertion
stale. Update the expected route while retaining the link-name and
callout checks.

### MCP server refetch behavior

- `AgentCreateForm / MCP Servers Error Shows Alert And Disables Send`
and `MCP Servers Refetch Error Keeps Send Enabled`: the MCP coverage was
introduced in #27942. PR #28442 later added a second unconditional MCP
`ErrorAlert`, so a background refetch error appeared even when cached
MCP data remained usable. The refetch story also called
`refetchQueries()` without a key, which began refetching unrelated
active model queries as the form's query surface expanded and produced
unmatched API failures. Remove the duplicate unconditional alert,
refetch only the organization's MCP query, and use semantic alert and
heading assertions. Initial-load failures still disable Send, while
background failures with cached data keep Send enabled without replacing
the form with an error.

### Interaction and teardown stability

- `IconField / Open Picker`: PR #27674 changed this story to wait for
the `em-emoji-picker` custom element. That implementation-specific query
races the lazy-loaded picker chunk and violates the component's
observable contract. Keep the button state assertion and wait for the
visible dialog instead.
- `AgentChatPage / Slash Compact Command Submits` and `Slash Compact
Yields To Personal Skill`: the command story added in #27081 waited on
cmdk's `Commands` group heading, which is accessibility-hidden, while
the skill variant queried raw implementation text. Menu placement and
visibility are asynchronous, especially after the positioning changes in
#28411. Wait for the visible selectable options by role before pressing
Enter.
- `AgentChatPageView / Terminal Focus On Tab Switch`: the focus coverage
added in #24677 exposed an xterm teardown race rather than a product
navigation regression. xterm queues its initial viewport
synchronization, but Storybook could synchronously dispose the terminal
first, leaving the queued callback to read a cleared renderer and report
an unhandled error. Clear React state immediately, defer xterm disposal
by one timer turn, query the labeled terminal textbox semantically, and
remove the unnecessary empty WebSocket message fixture.
aslilac pushed a commit that referenced this pull request Aug 24, 2026
Move chat model settings to
`/ai/settings/organizations/:organization/models`, add an organization
switcher, and redirect legacy settings paths. The pages use organization
permissions for read, create, update, and delete controls. They use
redacted provider descriptors.

Agent creation loads models for the selected organization. Existing
chats load models for the chat organization. Chat views warn about
unavailable historical models, select a usable local recovery model, and
disable generation when none exists. Settings that aggregate
organizations retain successful results when one request fails.

Depends on #27959

_This pull request description was generated by Coder Agents._
aslilac pushed a commit that referenced this pull request Aug 24, 2026
Adds audit logging for chat model config creates, updates, deletes, ACL
changes, and automatic default-model transitions. Audit records use the
config display name or ID as the target and are emitted only after
successful transactions.

Depends on #27960.
aslilac pushed a commit that referenced this pull request Aug 24, 2026
## Summary

Repair the Storybook interaction and Pixel failures currently present on
`main`. The failures came from organization-scoped model changes leaving
stories with incomplete providers and query fixtures, product copy and
route changes leaving stale assertions, and several interaction tests
depending on implementation details or teardown timing.

## Broken stories and fixes

### Organization-scoped chat models

PR #27960 introduced organization-scoped chat models and the following
regressions:

- `OrganizationModelsLayout / Switch Organization Preserves Auxiliary
Parameters`, `Invalid Requested Organization Falls Back To Default`,
`Invalid Requested Organization Denies Add`, `Duplicate Display Names
Are Disambiguated`, and `No Readable Organization Is Not Found`: the
stories only populated permission query keys for individual
organizations, while the accessible-organization lookup requests
authorization for all visible organization IDs together. The unmatched
`/api/v2/authcheck` request returned a Storybook proxy 502, so the
layout rendered an error instead of the intended picker, fallback,
denied, disambiguation, or not-found state. Add fixtures for the
combined organization-permission keys, preserve the intentionally denied
permission map, and return an explicit empty authorization result for
the no-readable-organization case.
- `ModelFormProviderConfig / Provider Config Open AI`, `Provider Config
Anthropic`, and `Provider Config Open AI Web Search`: `ModelForm` began
consuming `OrganizationModelsContext`, but these stories were not
wrapped in its provider and rendered the router error boundary. Add the
same organization-model context decorator used by the sibling model form
stories.
- `AgentChatPage / Queued For Capacity After Polling`: the story
retained a manually assembled chat-and-messages fixture after the page
gained organization-model, provider, workspace, prompt, diff, chat-list,
and authorization dependencies. Those missing queries prevented the
polling request from being reached. Replace the partial fixture list
with the shared `buildQueries()` setup.
- `DashboardLayout / Custom Organization Role Can Open Models`,
`DashboardLayout / ACL Readable Member Can Open Models`, and `NavbarView
/ For Member With Model Access`: these stories also landed in #27960 and
inherited Pixel's tablet-and-desktop matrix, but their play functions
exercise the desktop `Models` link. Pixel's 744px tablet viewport
renders that link inside the closed mobile menu, so the desktop query
always failed there. Restrict these authorization-to-navigation stories
to the desktop matrix; mobile Models navigation remains covered by the
dedicated `MobileMenu` story.

### Premium copy and navigation

- `DeploymentSidebarView / Premium Tab Visible` and `Premium Tab
Hidden`: PR #28226 renamed the production navigation item from `Premium`
to `Trial Upgrade`, but added stories that still queried the old name.
Update both the positive and negative assertions so the hidden-state
story cannot pass while the real CTA is present.
- `PremiumPageView / No License`: PR #28226 changed the production
heading to `Start an unlimited 30-day Coder trial` while the story
asserted the previous Premium wording. Update the accessible heading
assertion to the rendered copy.
- `AgentChatPageView / Queued For Capacity Community Admin`: PR #28437
intentionally moved the trial CTA from `https://coder.com/trial` to the
internal `/deployment/premium` route, leaving the story's href assertion
stale. Update the expected route while retaining the link-name and
callout checks.

### MCP server refetch behavior

- `AgentCreateForm / MCP Servers Error Shows Alert And Disables Send`
and `MCP Servers Refetch Error Keeps Send Enabled`: the MCP coverage was
introduced in #27942. PR #28442 later added a second unconditional MCP
`ErrorAlert`, so a background refetch error appeared even when cached
MCP data remained usable. The refetch story also called
`refetchQueries()` without a key, which began refetching unrelated
active model queries as the form's query surface expanded and produced
unmatched API failures. Remove the duplicate unconditional alert,
refetch only the organization's MCP query, and use semantic alert and
heading assertions. Initial-load failures still disable Send, while
background failures with cached data keep Send enabled without replacing
the form with an error.

### Interaction and teardown stability

- `IconField / Open Picker`: PR #27674 changed this story to wait for
the `em-emoji-picker` custom element. That implementation-specific query
races the lazy-loaded picker chunk and violates the component's
observable contract. Keep the button state assertion and wait for the
visible dialog instead.
- `AgentChatPage / Slash Compact Command Submits` and `Slash Compact
Yields To Personal Skill`: the command story added in #27081 waited on
cmdk's `Commands` group heading, which is accessibility-hidden, while
the skill variant queried raw implementation text. Menu placement and
visibility are asynchronous, especially after the positioning changes in
#28411. Wait for the visible selectable options by role before pressing
Enter.
- `AgentChatPageView / Terminal Focus On Tab Switch`: the focus coverage
added in #24677 exposed an xterm teardown race rather than a product
navigation regression. xterm queues its initial viewport
synchronization, but Storybook could synchronously dispose the terminal
first, leaving the queued callback to read a cleared renderer and report
an unhandled error. Clear React state immediately, defer xterm disposal
by one timer turn, query the labeled terminal textbox semantically, and
remove the unnecessary empty WebSocket message fixture.
ibetitsmike pushed a commit that referenced this pull request Aug 27, 2026
Repair the Storybook interaction and Pixel failures currently present on
`main`. The failures came from organization-scoped model changes leaving
stories with incomplete providers and query fixtures, product copy and
route changes leaving stale assertions, and several interaction tests
depending on implementation details or teardown timing.

PR #27960 introduced organization-scoped chat models and the following
regressions:

- `OrganizationModelsLayout / Switch Organization Preserves Auxiliary
Parameters`, `Invalid Requested Organization Falls Back To Default`,
`Invalid Requested Organization Denies Add`, `Duplicate Display Names
Are Disambiguated`, and `No Readable Organization Is Not Found`: the
stories only populated permission query keys for individual
organizations, while the accessible-organization lookup requests
authorization for all visible organization IDs together. The unmatched
`/api/v2/authcheck` request returned a Storybook proxy 502, so the
layout rendered an error instead of the intended picker, fallback,
denied, disambiguation, or not-found state. Add fixtures for the
combined organization-permission keys, preserve the intentionally denied
permission map, and return an explicit empty authorization result for
the no-readable-organization case.
- `ModelFormProviderConfig / Provider Config Open AI`, `Provider Config
Anthropic`, and `Provider Config Open AI Web Search`: `ModelForm` began
consuming `OrganizationModelsContext`, but these stories were not
wrapped in its provider and rendered the router error boundary. Add the
same organization-model context decorator used by the sibling model form
stories.
- `AgentChatPage / Queued For Capacity After Polling`: the story
retained a manually assembled chat-and-messages fixture after the page
gained organization-model, provider, workspace, prompt, diff, chat-list,
and authorization dependencies. Those missing queries prevented the
polling request from being reached. Replace the partial fixture list
with the shared `buildQueries()` setup.
- `DashboardLayout / Custom Organization Role Can Open Models`,
`DashboardLayout / ACL Readable Member Can Open Models`, and `NavbarView
/ For Member With Model Access`: these stories also landed in #27960 and
inherited Pixel's tablet-and-desktop matrix, but their play functions
exercise the desktop `Models` link. Pixel's 744px tablet viewport
renders that link inside the closed mobile menu, so the desktop query
always failed there. Restrict these authorization-to-navigation stories
to the desktop matrix; mobile Models navigation remains covered by the
dedicated `MobileMenu` story.

- `DeploymentSidebarView / Premium Tab Visible` and `Premium Tab
Hidden`: PR #28226 renamed the production navigation item from `Premium`
to `Trial Upgrade`, but added stories that still queried the old name.
Update both the positive and negative assertions so the hidden-state
story cannot pass while the real CTA is present.
- `PremiumPageView / No License`: PR #28226 changed the production
heading to `Start an unlimited 30-day Coder trial` while the story
asserted the previous Premium wording. Update the accessible heading
assertion to the rendered copy.
- `AgentChatPageView / Queued For Capacity Community Admin`: PR #28437
intentionally moved the trial CTA from `https://coder.com/trial` to the
internal `/deployment/premium` route, leaving the story's href assertion
stale. Update the expected route while retaining the link-name and
callout checks.

- `AgentCreateForm / MCP Servers Error Shows Alert And Disables Send`
and `MCP Servers Refetch Error Keeps Send Enabled`: the MCP coverage was
introduced in #27942. PR #28442 later added a second unconditional MCP
`ErrorAlert`, so a background refetch error appeared even when cached
MCP data remained usable. The refetch story also called
`refetchQueries()` without a key, which began refetching unrelated
active model queries as the form's query surface expanded and produced
unmatched API failures. Remove the duplicate unconditional alert,
refetch only the organization's MCP query, and use semantic alert and
heading assertions. Initial-load failures still disable Send, while
background failures with cached data keep Send enabled without replacing
the form with an error.

- `IconField / Open Picker`: PR #27674 changed this story to wait for
the `em-emoji-picker` custom element. That implementation-specific query
races the lazy-loaded picker chunk and violates the component's
observable contract. Keep the button state assertion and wait for the
visible dialog instead.
- `AgentChatPage / Slash Compact Command Submits` and `Slash Compact
Yields To Personal Skill`: the command story added in #27081 waited on
cmdk's `Commands` group heading, which is accessibility-hidden, while
the skill variant queried raw implementation text. Menu placement and
visibility are asynchronous, especially after the positioning changes in
Enter.
- `AgentChatPageView / Terminal Focus On Tab Switch`: the focus coverage
added in #24677 exposed an xterm teardown race rather than a product
navigation regression. xterm queues its initial viewport
synchronization, but Storybook could synchronously dispose the terminal
first, leaving the queued callback to read a cleared renderer and report
an unhandled error. Clear React state immediately, defer xterm disposal
by one timer turn, query the labeled terminal textbox semantically, and
remove the unnecessary empty WebSocket message fixture.

(cherry picked from commit 9b5f47e)
mtojek pushed a commit that referenced this pull request Aug 27, 2026
…n area to release/2.37 (#28673)

Batch backport of @tracyjohnsonux's PRs that merged into `main` after
the `release/2.37` branch point (`c275327f`, #28369) and were not yet on
the release branch.

Commits are `git cherry-pick -x` of the original squash commits in
`main` merge order. Ten are verbatim; the last two carry manual conflict
resolutions, documented below. `pnpm run lint:types` and the affected
Storybook suites (311 tests) pass on the branch.

## Included (12)

| PR | Commit on main | Notes |
|---|---|---|
| #28427 fix(site/src): delete DateTimeRangeFilter and unify on the
picker's time range type | `607a1d06` | verbatim |
| #28481 fix(site/src/pages/AIBridgePage): move AI Sessions docs link
inline into subtitle | `0452ff7e` | verbatim |
| #28477 fix(site/src/pages/AIBridgePage): align token badges with
neighboring badge sizing | `e98e2b9b` | verbatim |
| #28561 fix(site): use robot icon for subagent toggle in chat kebab
menu | `94f312df` | verbatim |
| #28557 fix: use medium badges and shorter shared key label on agent
API keys page | `c07bde80` | verbatim |
| #28560 fix(site/src/pages/AgentsPage): use outlined empty state and
kebab menu for personal skills | `74e5a680` | verbatim |
| #28559 fix(site/src/pages/AgentsPage): add organization filter to
compaction settings | `2eee703e` | verbatim |
| #28527 fix(site/src): use md badges for provisioner tags and network
call pills | `f31b7597` | verbatim |
| #28613 fix(site/src): use default combobox dropdown surface |
`2eb9e4fb` | verbatim |
| #28478 fix(site): match sessions date/time picker icon to search field
icon | `769decbe` | verbatim |
| #28612 fix(site/src): move deployment docs links inline as View docs
text links | `046a532a` | resolved |
| #28564 fix(site/src): reposition org pickers in AI settings models and
MCP pages | `78c65ea5` | resolved, ported |

## Conflict resolutions

- **#28612**: conflicted with #28664 (the backport of #28660) in
`SecuritySettingsPageView.{tsx,stories.tsx}` because the backports
landed in reverse `main` order. Resolved by taking `main`'s content;
since only #28612 and #28660 touched those files on either side, the
resolved files are byte-identical to `main`.
- **#28564**: written on top of #28593 (MCP server sharing), which is
not release material. 24 of 29 files applied verbatim; the 5 conflicting
files were ported by hand against pre-#28593 code: `organizationPicker`
prop threading and the edit-requires-dirty submit gate without the
`canShareServer` context, the form header rebuilt as `main`'s version
minus the share button, and story assertions ported (the #28593 share
stories do not exist on this branch).
`ModelFormProviderConfig.stories.tsx` takes `main`'s version,
deliberately folding in the stories-only decorator fix from #28462
because `release/2.37` already has #27960 and those stories were broken
without the provider wrap. Validated with the full MCPServersPage +
ModelsPage Storybook suites (140/140, matching the original PR) and the
`mcpServerFormLogic` unit tests.

## Excluded

- #28492 (built-in emoji avatar inset): reverted on `main` by #28533, so
it is not backported.
- #28558 (show disabled state on AI provider rows): handled individually
in #28662; blocked only on the #28624 backport (see analysis there).

<details>
<summary>Decision log</summary>

- Branch point of `release/2.37` from `main`:
`c275327fb724dea6c4428263d948e13815041b3e` (2026-08-24, #28369),
computed via `git merge-base`.
- 15 of the author's merged PRs landed on `main` after that point; none
had been backported yet (verified by ancestry, patch-id equivalence, and
`(#NNNN)` references in `release/2.37` history since the branch point).
- Cherry-picks were applied oldest-first in `main` topological order;
conflicting picks were initially skipped, then #28612 and #28564 were
resolved on the same base and appended (no file overlap with the
verbatim picks except `docs/ai-coder/agents/models.md`, which merges
cleanly).
- #28492 was initially included, then rebased out after confirming it
was reverted on `main` by #28533 (`bef6b4c30b`).
- The bot's individual cherry-pick PRs were closed as superseded:
#28661, #28663, #28665, #28667, #28668, #28669, #28671, and after
consolidation #28670 and #28666.
- Validation: `pnpm install`, `pnpm run lint:types` (tsc), Biome on
changed files, `mcpServerFormLogic` unit tests, and the AISettingsPage +
SecuritySettingsPage Storybook suites (311 tests) pass after each
change.

</details>

> Created by Coder Agents on behalf of @tracyjohnsonux.

---------

Co-authored-by: Michael Suchacz <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants