Relates to #20925
This PR modifies TaskPage to update an outdated workspace instead of
starting it. Before, starting an outdated workspace where the template
required the active version would fail with the error "cannot use
non-active version: rbac: forbidden".
For the case of a dormant workspace, I deemed it safe enough to simply
unset dormancy on an attempted start (ref:
https://github.com/coder/coder/pull/21306). However, automatically
updating a workspace is a more risky option, so I instead elected to
give the user the option of updating their workspace using the existing
tooltip.
**Note:** I made a change to the `WorkspaceOutdatedTooltip` components
to allow it to have children so that the tooltip could trigger over a
wider element instead of just the info icon.
```
<🤖 AI Disclaimer>I got some help from Gemini 3 Flash in "Ask" mode.</🤖 AI Disclaimer>
```
Closes#21052 and is related to #21218
This pull request implements a bunch of changes the team requested to
improve the overall user experience when navigating to the Request Logs
page. Since these are mostly UI changes, screenshots do a much better
job of showing what's different than me trying to explain everything in
words, so I've included them below.
> [!WARNING]
> More globally we've changed how we're rendering `<PaginationHeader
/>`, therefore we've renamed it to `<PaginationAmount />`. This will
effect multiple layouts however its a global improvement we're
intentionally looking to make.
### Preview

### Changes
1. Date formatting set to a standardised way including the month as a
`MMM` (i.e `Dec`)
2. Names and avatars are now rendered larger, furthermore they render
the `.name` field falling back on `.username`.
3. Font-size increased from `text-xs` to `text-sm` to increase overall
legibility globally.
4. Initiator is now rendered inside of a `<Badge />` and gives longer
names a chance to render.
5. Models are now rendered in a `<Badge />` alongside their icons.
6. Input/Output tokens are in a shared `<Badge />`-group alongside
truncation (when necessary).
7. Badge from `5` is rendered with the proper name being visible on
hover (for use if truncated).
8. Move globally the `Showing X of X` counts to the bottom of the tables
(effects other components outside of AI Bridge).
9. Icons are now included within the dropdown for the `Provider` filter.
10. Truncation of elements is now handled so larger prompts don't cause
the table to require further scrolling.
11. New merged Input/Output `<dt>` element with the badge
| Position | Pull-request |
| -------- | ------------ |
| ✅ | [fix: improve AI Bridge request logs
UI/UX](https://github.com/coder/coder/pull/21252) |
| | [feat: add AI Bridge request logs model
filter](https://github.com/coder/coder/pull/21259) |
| | [chore!: promote AIBridge from
`ExperimentalHandler`](https://github.com/coder/coder/pull/21278) |
| | [feat: implement request log collapsing prompt (`<RequestLogsPrompt
/>`)](https://github.com/coder/coder/pull/21313) |
---------
Co-authored-by: ケイラ <mckayla@hey.com>
This PR separate the data retrieval for workspace sharing ACL into a
custom hook and creates a separate form component. This is in
preparation for reusing the workspace sharing form from a new share
button on the workspace page.
Closes#21217
This pull-request traverses the `token_usages.metadata[...]` fields and
merges them into a single consumable object so that we're able discern
information about the metadata within the token usages at a glance. Its
not the be-all end-all implementation of this feature but its a stepping
stone in order to render more useful data to the frontend.
These are currently mergable because they only contain `number` based
fields. When it encounters something within the object that can't be
merged (minus empty objects `{}`) it will simply return them as an
array.
### Preview
<img width="2682" height="1360" alt="CleanShot 2025-11-28 at 15 30
09@2x"
src="https://github.com/user-attachments/assets/e07e6515-4b8e-4169-841c-38fd83c434f9"
/>
### Logic breakdown
<img width="914" height="1016" alt="CleanShot 2025-11-28 at 15 11 13@2x"
src="https://github.com/user-attachments/assets/34b78fe1-3b58-4b78-a552-028ea5a88dc4"
/>
This removes the deprecated AITaskPromptParameterName constant and all
backward compatibility code that was added for v2.28.
- Remove AITaskPromptParameterName constant from codersdk/aitasks.go
- Remove backward compatibility code in coderd/aitasks.go that populated
the "AI Prompt" parameter for templates that defined it
- Remove the backward compatibility test (OK AIPromptBackCompat)
- Update dbfake to no longer set the AI Prompt parameter
- Remove AITaskPromptParameterName from frontend TypeScript types
- Remove preset prompt read-only feature from TaskPrompt component
- Update docs to reflect that pre-2.28 definition is no longer supported
Task prompts are now exclusively stored in the tasks.prompt database
column, as introduced in the migration that added the tasks table.
**Breaking Change:** Existing oauth apps might now use PKCE. If an
unknown IdP type was being used, and it does not support PKCE, it will
break.
To fix, set the PKCE methods on the external auth to `none`
```
export CODER_EXTERNAL_AUTH_1_PKCE_METHODS=none
```
Provisioner steps broken into smaller granular actions.
Changes:
- `ExtractArchive` moved to `init` request (was in `configure`)
- Writing `tfstate` moved to `plan` (was in `configure`)
- Moved most plan/apply outputs to `GraphComplete`
closes: https://github.com/coder/internal/issues/858
Similar to https://github.com/coder/coder/pull/19375, this one uses
system permissions for fetching actual user and group data.
Modifies the `workspaces_expanded` view to fetch the required data; this way it's made available to all code paths that make use of it.
Also fixes a bug in a test helper function that can result in `null` being saved to the DB for `user_acl` or `group_acl` and break tests; a defensive check constraint that prevents this is worth a PR, e.g:
`ALTER TABLE workspaces
ADD CONSTRAINT group_acl_is_object CHECK (jsonb_typeof(group_acl) = 'object');`
Also adds missing `OwnerName` in `ConvertWorkspaceRows`.
closes#19974
This PR replaces all remaining MUI tooltips with our shadcn tooltip
component, and uncomments the linter restriction on importing the MUI
tooltip
Closes#20399
To summarize the original commit messages:
- Do not log stats to the database.
- Return errors on the insight endpoints.
- Update the frontend to show those errors.
- Also fixes an issue with getting the user status count via codersdk,
since I added a test to ensure it was not disabled by this flag and it
was sending the wrong payload.
for #19974
`ShareIcon`, which returns a MUI tooltip, had these problems:
1. There was no Storybook story which rendered the "Open external URL"
tooltip
2. `AppLink` renders a button. If it has tooltip text, this button is
also a Radix `TooltipTrigger`. Since `ShareIcon` is rendered as a child
of the `AppLink` button, `ShareIcon`'s tooltip (a nested tooltip) was
never appearing. I did try turning `ShareIcon` into a Radix tooltip as
well, but I still couldn't get the nested tooltip's text to appear, and
nested tooltips are not very accessible. AFAIK there's no way to focus a
child element of a button.
I've deleted the separate `ShareIcon` component and moved `ShareIcon`'s
tooltip text to the bottom of `AppLink`'s tooltip:
## before
<img width="175" height="121" alt="image"
src="https://github.com/user-attachments/assets/ad17927e-c3d1-499b-83f8-a5832b777305"
/>
^The `UsersIcon` on the right is a MUI tooltip trigger, but it can't
receive focus. It's supposed to show the text "Shared with all
authenticated users" when focused
## after
<img width="228" height="121" alt="image"
src="https://github.com/user-attachments/assets/adc202c1-57cd-4a80-8f94-f7f32897d286"
/>
for #19974
The MUI tooltip inside `PaginationNavButton` was a controlled component.
This + the stateful logic inside `PaginationNavButtonCore` meant that
`showDisabledMessage` would never be set to true. I.e., the "You are
already on the first page" tooltip if on the first page and the "You are
already on the last page" tooltip if on the last page would never show
up.
The `PaginationNavButton`s gets disabled if we're at either the
first/last page, and disabled buttons can't receive focus, so there's no
way to open the MUI tooltips with keyboard navigation.
Removing the MUI tooltip + related props from `PaginationNavButton` has
no effect on my screen reader UX with macOS VoiceOver; it's entirely
unchanged
## Summary
This adds configurable overload protection to the AI Bridge daemon to
prevent the server from being overwhelmed during periods of high load.
Partially addresses coder/internal#1153 (rate limits and concurrency
control; circuit breakers are deferred to a follow-up).
## New Configuration Options
| Option | Environment Variable | Description | Default |
|--------|---------------------|-------------|---------|
| `--aibridge-max-concurrency` | `CODER_AIBRIDGE_MAX_CONCURRENCY` |
Maximum number of concurrent AI Bridge requests. Set to 0 to disable
(unlimited). | `0` |
| `--aibridge-rate-limit` | `CODER_AIBRIDGE_RATE_LIMIT` | Maximum number
of AI Bridge requests per second. Set to 0 to disable rate limiting. |
`0` |
## Behavior
When limits are exceeded:
- **Concurrency limit**: Returns HTTP `503 Service Unavailable` with
message "AI Bridge is currently at capacity. Please try again later."
- **Rate limit**: Returns HTTP `429 Too Many Requests` with
`Retry-After` header.
Both protections are optional and disabled by default (0 values).
## Implementation
The overload protection is implemented as reusable middleware in
`coderd/httpmw/ratelimit.go`:
1. **`RateLimitByAuthToken`**: Per-user rate limiting that uses
`APITokenFromRequest` to extract the authentication token, with fallback
to `X-Api-Key` header for AI provider compatibility (e.g., Anthropic).
Falls back to IP-based rate limiting if no token is present. Includes
`Retry-After` header for backpressure signaling.
2. **`ConcurrencyLimit`**: Uses an atomic counter to track in-flight
requests and reject when at capacity.
The middleware is applied in `enterprise/coderd/aibridge.go` via
`r.Group` in the following order:
1. Concurrency check (faster rejection for load shedding)
2. Rate limit check
**Note**: Rate limiting currently applies to all AI Bridge requests,
including pass-through requests. Ideally only actual interceptions
should count, but this would require changes in the aibridge library.
## Testing
Added comprehensive tests for:
- Rate limiting by auth token (Bearer token, X-Api-Key, no token
fallback to IP)
- Different tokens not rate limited against each other
- Disabled when limit is zero
- Retry-After header is set on 429 responses
- Concurrency limiting (allows within limit, rejects over limit,
disabled when zero)
Implements cmd+enter (Mac) / ctrl+enter (Windows/Linux) keyboard
shortcut for submitting tasks on the tasks page. Regular enter key still
creates new lines as expected.
Fixes#21179🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Added specific icons for common file types in the template file tree:
- **.sh files**: TerminalIcon (terminal/shell scripts)
- **.json files**: BracesIcon (JSON data files)
- **.yaml/.yml files**: FileCodeIcon (YAML configuration files)
<img width="260" height="290" alt="image"
src="https://github.com/user-attachments/assets/a470f4bc-fc2c-4e2d-8067-a9fbbfe32e42"
/>
These icons help users quickly identify file types at a glance in the
template editor.
Fixes#21145
The browser tab title for tasks was showing the machine-readable name
(e.g., `kyle/my-workspace.main`) instead of the user-friendly display
name (e.g., `Create Documentation`).
Changed `site/src/pages/TaskPage/TaskPage.tsx` to use
`task.display_name` for the page title. The `display_name` field is
always set by the backend (NOT NULL constraint, auto-generated if
empty), so no fallback is needed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
for #19974
Continuing the train of thought from
https://github.com/coder/coder/pull/20849#issuecomment-3560666271: it's
probably better to do away with a custom tooltip component that's only
used in `ResourcesChart`/`ScriptsChart`/`StagesChart` and only slightly
differs from our base tooltip
## Summary
Fixes folder icons in the template editor file tree.
## Changes
- Import `FolderIcon` instead of `TextAlignStartIcon` from lucide-react
- Use `FolderIcon` for folder entries in the file tree
_Generated with `mux`_
Adds `--disable-workspace-sharing` option.
Workspace sharing is disabled by not including user and group ACLs in
the workspace RBAC object, which prevents ACL-based authz.
Closes https://github.com/coder/internal/issues/1072
The commit also adds saving of workspace user/group ACLs in the test DB
data generator.
Closes#19984
As part of this, I refactored the error template to take in a slice of
actions rather than using individual booleans and strings to control the
behavior.
We decided a link resolves the issue for now so that is what I added,
although we may want to consider a way to start the workspace and follow
the logs dynamically on that page and then show the app when finished
(similar to the tasks page), or at least make the link automatically
start the workspace instead of only taking you to the dashboard where
you have to then start the workspace.
Adds deprecation markers for MUI components and the custom Stack
component to guide migration to shadcn/ui and Tailwind CSS.
Changes:
- Added JSDoc @deprecated tags to Stack component and type definitions
- Added deprecation comments to MUI imports in theme files
- Expanded Biome noRestrictedImports rules to flag all MUI component
imports
---------
Co-authored-by: Claude <noreply@anthropic.com>
### Description
This pull-request ensures that we're using the right colors (and
themeing things within the actual coder brand) on the `error.html` page.
Furthermore, I went ahead and cleaned up the CSS Variables and converted
all `px` units to a standard `rem` unit (16px base).
### Preview
<img width="3516" height="2388" alt="CleanShot 2025-12-02 at 11 09
55@2x"
src="https://github.com/user-attachments/assets/781623ea-a487-4a2e-a08e-bec86d6de6f5"
/>
Converts from Emotion to Tailwind CSS, based on the tasks batch delete
dialog implementation.
Also propagates simplifications back to the tasks dialog:
- Use `border-border` instead of hardcoded color variants
- Use `max-h-48` instead of specific `max-h-[184px]`
- Add cancel button to workspaces dialog
Refs #20905
Reduce from 3 confirmation stages to 2 by removing the redundant
"resources" stage. The final button now shows "Delete N tasks and M
workspaces" directly, so users still see what will be deleted.
Also add a Cancel button to match the single task delete dialog UX.
Refs #20905
Replace hardcoded 7-day retention for workspace agent logs with
configurable retention from deployment settings. Defaults to 7d to
preserve existing behavior.
Depends on #21038
Updates #20743
Add `RetentionConfig` with server flags for configuring data retention:
- `--audit-logs-retention`: retention for audit log entries
- `--connection-logs-retention`: retention for connection logs
- `--api-keys-retention`: retention for expired API keys (default 7d)
Updates #20743
> [!CAUTION]
> In whichever release this lands, we've removed the ability to provide
keys via a YAML file (specifically on `openai_key`, `anthropic_key`,
`bedrock_access_key` and finally `bedrock_access_key_secret`). This will
need to be described in the release notes as to not break peoples AI
Bridge integrations upgrading from older versions.
This pull-request ensures that we can see the overview of the settings
of the `AI Bridge` feature within the `/deployment/observability` route.
This set of options only render when the `aibridge` feature flag is
enabled.
### Preview
