Commit Graph
14781 Commits
Author SHA1 Message Date
Cian Johnston a4c867f11b fix: backfill legacy Bedrock AI provider rows and stale model config strings (#26155)
Fixes CODAGT-548

Adds two idempotent startup backfills run after `newAPI():

- `BackfillBedrockProviderType`: promotes `ai_providers` rows from
`type=anthropic` with Bedrock settings to `type=bedrock`.
- `BackfillChatModelConfigProviderStrings`: fixes stale
`chat_model_configs.provider = "anthropic"` strings on rows whose linked
provider was just promoted.
- `UpdateAIProvider` query now also writes the `type` column, so the
fix persists on any subsequent PATCH.


> 🤖 Generated by Claude with oversight from a human.
2026-06-11 15:31:31 +01:00
Eric Paulsen b6033aee03 fix(coderd): reject suspended user during OIDC and GitHub OAuth login (#24996)
Previously, a suspended user authenticating via OIDC or GitHub OAuth was
silently issued a session cookie and redirected to the dashboard. The
very next API call (`/api/v2/users/me`) failed with `401` from the
suspended-user check in `httpmw.ExtractAPIKey`, the SPA treated the 401
as "signed out", and bounced the user back to `/login` with no
indication of why. The password login path does not have this bug
because `loginRequest` rejects suspended users *before* creating an API
key.

The shared `oauthLogin` handler in `coderd/userauth.go` only
special-cased the `dormant` status. Add a parallel check for `suspended`
that returns an `idpsync.HTTPError` with `RenderStaticPage: true`, so
the OIDC and GitHub callback handlers render an explanatory error page.
The GitHub device flow already clears `RenderStaticPage` for
`idpsync.HTTPError` responses, so it returns the same fields as JSON.
Returning from inside `db.InTx` rolls the transaction back, so no link
insert/update or IDP sync side-effects are persisted for a rejected
suspended user.

Closing https://github.com/coder/coder/issues/24614

<details>
<summary>Investigation notes</summary>

### Trace through the bug on `main`

1. `userOIDC` callback in `coderd/userauth.go` enters `oauthLogin`.
2. Inside the `db.InTx` closure, only `user.Status ==
database.UserStatusDormant` is special-cased (auto-activates). A
`suspended` user falls through and the transaction commits as-is.
3. `oauthLogin` then calls `api.createAPIKey(...)` and the session
cookie is set.
4. The handler issues `http.Redirect(rw, r, redirect,
http.StatusTemporaryRedirect)` to the post-login URL.
5. The SPA loads and calls `GET /api/v2/users/me`.
`httpmw.ExtractAPIKey` returns `401 "User is not active (status =
\"suspended\"). Contact an admin to reactivate your account."`
(`coderd/httpmw/apikey.go:685`).
6. `site/src/contexts/auth/RequireAuth.tsx` treats any `401` from
`/users/me` as "signed out" and redirects to `/login` without surfacing
the message body.

Verified by reverting the fix and re-running the new test: the OIDC
callback returns `307` (the bug) instead of the expected `403`.

### Why this placement

The new check is placed alongside the existing `Dormant` branch:

- It runs after the new-user creation block, so first-login signup is
unaffected (new users are always created `active`).
- Returning an `*idpsync.HTTPError` from inside `db.InTx` rolls the
transaction back, so no `user_links` insert/update or IDP sync is
persisted.
- `idpsync.HTTPError` with `RenderStaticPage: true` is already the
convention used by the OIDC and GitHub callbacks for "Email not
verified" and "Signups disabled" via `idpsync.IsHTTPError(err) ->
httpErr.Write(rw, r)`.
- `oauthLogin` is shared between OIDC and GitHub OAuth, so a single
change fixes both flows. The GitHub device-flow branch in
`userOAuth2Github` already clears `RenderStaticPage` for
`idpsync.HTTPError` and returns JSON, so device clients get the same
`403` with `Msg`/`Detail` fields.

### Test

`TestUserOIDC/OIDCSuspended` mirrors the existing `OIDCDormancy` test:

- Pre-seed a `database.User` with `LoginType: LoginTypeOIDC` and
`Status: UserStatusSuspended`.
- Drive the OIDC callback via `oidctest.FakeIDP.AttemptLogin`.
- Assert HTTP `403`, response body contains `"suspended"`, and the
user's DB status is unchanged.

### Out of scope

The issue mentions allowing admins to customize the suspension message
as an extra step. Not included; that would be a separate feature.

</details>

---

*This PR was created on behalf of @ericpaulsen by the Coder Agents AI
assistant.*
2026-06-11 14:39:21 +01:00
Danielle Maywood ba51ee8f98 refactor(site/src/pages/AgentsPage): centralize setup notice rendering (#26134) 2026-06-11 12:43:53 +01:00
Danielle Maywood f865281177 refactor(site): remove CSSProperties assertions (#26234) 2026-06-11 11:21:34 +01:00
Danielle Maywood e440771b3e fix(site): allow single-line diff comments (#26241) 2026-06-11 10:34:05 +01:00
Danielle Maywood 68efed86fa fix(site/src/pages/AgentsPage/components): gate transcript copy actions and keep live thinking row in flow (#26214) 2026-06-11 10:08:10 +01:00
Jaayden Halko 5ab25b3ff6 fix(site): add a custom copy/paste menu to the web terminal (#26015)
## Summary

Fixes [CODAGT-415](https://linear.app/codercom/issue/CODAGT-415).

Right-clicking selected text in the web terminal on Windows (and Linux)
showed
the browser's image actions ("Copy image", "Save image as") instead of
copy/paste. The terminal uses xterm.js with the canvas/WebGL renderer,
so the
underlying element is a `<canvas>`, which Chromium and Firefox treat as
an
image. xterm.js tries to retarget the menu by moving a hidden textarea
under
the cursor, but on Windows and Linux the browser's own non-native
context menu
locks onto the canvas before that workaround lands.

## Change

Wrap the terminal in the shared Radix `ContextMenu` so right-click shows
a
custom **Copy** / **Paste** menu instead of the browser default:

- **Copy** reuses the existing copy-on-select clipboard path
(`getSelection()`
  + `copyToClipboard`). It is disabled when there is no selection.
- **Paste** reads the clipboard and uses xterm's `paste()`, which
respects
  bracketed-paste mode.
- The menu is gated to non-macOS (`disabled={isMac()}` on the trigger).
macOS
renders native context menus that already expose working copy/paste
across
  Chrome, Firefox, and Safari, so its default is left untouched.

## Platform scope

| Platform | Behavior |
| --- | --- |
| Windows (Chromium / Firefox) | Custom Copy/Paste menu (fixes the bug)
|
| Linux (Chromium / Firefox) | Custom Copy/Paste menu |
| macOS (Chrome / Firefox / Safari) | Native menu preserved (already
works) |

## Testing

- `TerminalPage.test.tsx`: on non-macOS, right-click suppresses the
native menu
  and shows the Copy/Paste menu; on macOS the native menu is preserved.
- `TerminalPage.stories.tsx`: new `RightClickMenu` story opens the menu
via a
  `play` function for real-browser and visual coverage.
- `tsc`, `biome`, and `make pre-commit` (gen/fmt/lint/build) pass
locally.

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

- The issue was originally reported as Windows-only. Hands-on testing
confirmed
macOS is not affected: Chrome, Firefox, and Safari on macOS all show a
working
copy/paste menu. The difference is the menu implementation: macOS uses
native
  OS context menus (which pick up xterm's repositioned textarea), while
Chromium/Firefox on Windows and Linux draw their own menu that targets
the
  `<canvas>` directly.
- Root cause is the canvas/WebGL renderer plus the unreliability of
xterm's
textarea-repositioning workaround on non-native menus, not the operating
  system itself.
- A custom menu (rather than just `preventDefault`) was chosen so users
keep an
  explicit copy/paste affordance on the affected platforms. A bare
  `preventDefault` removes the menu entirely.
- Scope is gated to non-macOS to avoid regressing the working native
menu on
macOS. Rejected alternatives: suppressing/replacing on all platforms
(regresses
macOS), and Windows-only (misses Linux, which shares the same non-native
menu).

</details>

---

Generated by Coder Agents on behalf of @jaaydenh.
2026-06-11 09:12:15 +01:00
Danny Kopping 78a6ec293e revert: "fix: avoid an errant license warning banner on new deployments that d…" (#26240)
Reverts coder/coder#26239

We cannot disable a feature which was previously enabled; this is a BC
break.
This is also using `AIGatewayRoutingEnabled` which will be removed in
the next release.
2026-06-11 08:07:32 +00:00
Sas Swart d0e9c5eda5 fix: avoid an errant license warning banner on new deployments that d… (#26239)
Problem: CODER_AI_GATEWAY_ENABLED defaulted to true, which both started
the in-memory gateway and enabled the licensed FeatureAIBridge. As a
result, deployments that never configured AI Gateway saw a spurious "AI
Governance add-on is required" warning whenever they had an older
(non-add-on) Premium license, since the feature was enabled-and-entitled
by default.

Fix: Decouple "external AI Gateway API enabled" from "in-memory daemon
running," so the external/licensed surface is off by default while Coder
Agents retain access by default.
2026-06-11 09:17:26 +02:00
Ethan f3c25de7aa fix(coderd/x/chatd): stabilize dial timeout recovery test (#26153)
Fixes a scheduler-dependent flake in chatd's dial-timeout recovery path.

The dial timeout now uses the server's quartz clock, and
`dialWithLazyValidation` also uses that clock for its validation-delay
timer. If a dial result races with a canceled parent context, the
cancellation now wins instead of treating the cancellation-produced dial
error as a fast failure that triggers eager validation.

The recovery-threshold test now traps and advances the mock clock, which
keeps strict DB expectations without depending on wall time or goroutine
scheduling.

Closes https://github.com/coder/internal/issues/1569
Closes ENG-2838
2026-06-11 16:08:32 +10:00
Ethan 2e47d33c2c fix(site/src/modules/resources): restore log auto-expand on script failure (#26237)
#26124 introduced a regression on `main`: `AgentRow ›
NonStartupScriptError` fails because the refactor replaced
`hasAgentIssues` (which covered both connectivity and script issues)
with `hasConnectivityIssues` only in the `showLogs` condition. For a
`ready` agent with a failed script but no connectivity issues,
`showLogs` becomes false, logs never load, and the failed script tab
never renders. The PR's own behavior table said logs should still
auto-open in this case — it was an implementation oversight, not an
intentional change.

Fix by including `hasScriptIssues` in the `showLogs` condition alongside
`hasConnectivityIssues`, restoring the auto-expand behavior from #25442
without touching connectivity badge styling.

> **Note:** This reached `main` undetected because `test-js` in CI only
runs `--project=unit`; the Storybook interaction tests
(`--project=storybook`) that caught this are not a required check. When
Chromatic is switched off, `--project=storybook` should be added to the
required gate.

Refs #26124, #25442
2026-06-11 05:45:59 +00:00
Atif Ali 9e1c502ece fix(site): delink agent health from script failures (#26124) 2026-06-11 09:30:15 +05:00
Ethan 7326480173 fix(site/src/pages/AgentsPage/components/ChatsSidebar): pin timestamp masks (#26163)
## Summary

Pin chat relative timestamp Chromatic ignore masks to the established
`inline-block w-7 text-right` box so changing text like `46m` to `now`
does not shrink the ignored bounding rect and expose slivers of diff.

This applies the fix to the search dialog result rows and restores the
same mask on sidebar chat rows after the sidebar extraction dropped it.

## Flaky stories

- `pages/AgentsPage/ChatsSidebar: Search Dialog Keyboard Shortcut`,
opens the search dialog with recent chats visible, which renders
relative timestamps in `ChatSearchResults`.
- `pages/AgentsPage/ChatsSidebar: Section Headers Collapse`, and other
`ChatsSidebar` snapshots that render sidebar chat rows, can hit the same
timestamp mask-width drift through `ChatTreeNode`.
2026-06-11 13:36:22 +10:00
Callum StyanandMux 4e2c9f9cae fix: allow lifecycle code path to retry failed stop jobs (#26203)
Co-authored-by: Mux <mux@coder.com>
2026-06-10 16:29:00 -07:00
George K 0b99e67ce7 fix(coderd/workspaceapps): verify workspace owner matches app username (#26085)
fix(coderd/workspaceapps): verify workspace owner matches app username

When resolving a workspace app by workspace UUID, the URL's username
segment was never reconciled against the resolved workspace's owner.
A user could serve their own workspace app from a hostname embedding
another user's username, so the parsed origin username belonged to the
victim.  Combined with the username-equality CORS check, this allowed
credentialed cross-origin reads of the victim's app responses.

Reject the request with a 404 when the resolved workspace's owner does
not match the user named in the request.

Refs: https://linear.app/codercom/issue/PLAT-260
2026-06-10 16:26:45 -07:00
Rowan Smith 77522c3945 feat: cli: add support for supplying ephemeral parameters at workspace creation (#26012)
Resolves the issue of `--prompt-ephemeral-parameters` and
`--ephemeral-parameter` not being available for use in the `coder
create` workspace creation command (they are only available in `coder
start` command). Back when they were [added
originally](https://github.com/coder/coder/pull/15030) it seems to have
been an oversight that they were left out.

The problem this solves:

```
coder create --parameter my_ephemeral_parameter=foo
error: prepare build: ephemeral parameter "my_ephemeral_parameter" can be used only with --prompt-ephemeral-parameters or --ephemeral-parameter flag
```

```
coder create my-test-ws -t general --ephemeral-parameter my_ephemeral_parameter=foo
parsing flags ([create my-test-ws -t general --ephemeral-parameter my_ephemeral_parameter=foo]) for "coder create": unknown flag: --ephemeral-parameter
```

Tested on a template with the following:

```
data "coder_parameter" "my_ephemeral_parameter" {
  name         = "my_ephemeral_parameter"
  type         = "bool"
  description  = "true or false?"
  mutable      = true
  default      = false
  ephemeral    = true
}

resource "coder_env" "debug_ephemeral" {
  agent_id = coder_agent.main.id
  name     = "EPHEMERAL_TEST"
  value    = data.coder_parameter.my_ephemeral_parameter.value
}
```

By running:

```
➜  coder git:(rowan/coder-create-5495) ✗ go run cmd/coder/main.go create --ephemeral-parameter my_ephemeral_parameter=true
> Specify a name for your workspace: ws4
Select a template below to preview the provisioned infrastructure:
?  kasmvnc-ubuntu-coder-dev used by 1 active developer
Select a preset below:
?  Small (2 CPU / 4 GB)
....
...
The ws4 workspace has been created at Jun  3 12:36:38!

➜  coder git:(rowan/coder-create-5495) ✗ coder ssh ws4               
workspace-ws4-5d6994756f-qlwnl% echo $EPHEMERAL_TEST
true
workspace-ws4-5d6994756f-qlwnl% exit
```
2026-06-11 09:06:07 +10:00
dependabot[bot] 341285cdc7 chore: bump @pierre/diffs from 1.2.4 to 1.2.7 in /site (#25961)
Bumps @pierre/diffs from 1.2.4 to 1.2.7.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-10 21:43:35 +00:00
Danielle Maywood 00d1f1c596 chore(site): upgrade @pierre/diffs and restore diff file tree (#25879) 2026-06-10 22:31:47 +01:00
Kyle Carberry dab1d3c81e fix(cli): sort external auth env vars by numeric index (#26230) 2026-06-10 14:21:54 -07:00
Zach 4198358402 fix: stabilize TestExecutorAutostopAIAgentActivity (#26004)
`TestExecutorAutostopAIAgentActivity` flaked when the test clock and the
database clock straddled a minute boundary, leaving the executor's
minute-aligned tick on the wrong side of the bumped deadline. Anchor
tick times to the deadline the database wrote after the bump.
2026-06-10 14:00:19 -06:00
Nick Vigilante cfb03f52db fix: update stale docs URLs across non-TS files (#25750)
Closes [DOCS-256](https://linear.app/coder/issue/DOCS-256). Sibling to
[DOCS-253](https://linear.app/coder/issue/DOCS-253) (#25740).

Updates docs URL references across the non-TypeScript surface of
`coder/coder` to match the current docs site structure. Source-of-truth
for redirects is `coder/coder.com/redirects.json` (parent ticket
[DOCS-209](https://linear.app/coder/issue/DOCS-209)).

## What changed

| Area | Files | URL mapping |
|---|---|---|
| Top-level README | `README.md` | `/docs/workspaces` ->
`/docs/user-guides/workspace-management`, `/docs/templates` ->
`/docs/admin/templates`, `/docs/ides` ->
`/docs/user-guides/workspace-access` |
| Docs source | `docs/admin/security/0001_user_apikeys_invalidation.md`
| `/docs/admin/audit-logs` -> `/docs/admin/security/audit-logs` |
| Docs source | `docs/install/cloud/azure-vm.md` |
`/docs/coder-oss/latest/install` -> `/docs/install` |
| Dogfood | `dogfood/coder/guide.md` | `/docs/ides` ->
`/docs/user-guides/workspace-access` |
| Helm | `helm/coder/values.yaml` | `/docs/admin/workspace-proxies` ->
`/docs/admin/networking/workspace-proxies` |
| Enterprise coderd | `enterprise/coderd/coderd.go` |
`/docs/admin/encryption` -> `/docs/admin/security/database-encryption`
(error message) |
| Release tooling | `scripts/release/main_internal_test.go` |
`/docs/admin/upgrade` -> `/docs/install/upgrade` (test fixture, matches
`generate_release_notes.sh`) |
| AI bridge | `aibridge/client.go` | repinned to current `main` SHA on
renamed `docs/ai-coder/ai-gateway/monitoring.md`, line range `#L47-L57`
|
| Example templates | 12 `examples/templates/*/README.md`,
`examples/parameters/*`,
`examples/parameters-dynamic-options/README.md`,
`examples/workspace-tags/README.md`, `examples/parameters/main.tf`,
`examples/examples.gen.json` (regenerated) | `/docs/workspaces` ->
`/docs/user-guides/workspace-management`, `/docs/templates/parameters`
-> `/docs/admin/templates/extending-templates/parameters`,
`/docs/templates/dev-containers` ->
`/docs/admin/integrations/devcontainers`, `/docs/dotfiles` ->
`/docs/user-guides/workspace-dotfiles`,
`/docs/about/architecture#agents` ->
`/docs/admin/infrastructure/architecture#agents` |
| Live notification templates (DB) | New migration
`000510_fix_dormancy_notification_docs_urls.up.sql` and `.down.sql` plus
the four regenerated SMTP/webhook goldens under
`coderd/notifications/testdata/rendered-templates/` |
`/docs/templates/schedule#dormancy-threshold-enterprise` ->
`/docs/admin/templates/managing-templates/schedule#dormancy-threshold`,
`/docs/templates/schedule#dormancy-auto-deletion-enterprise` ->
`/docs/admin/templates/managing-templates/schedule#dormancy-auto-deletion`
|

The migration uses `REPLACE(body_template, ...)` scoped by template id
and `LIKE '%/docs/templates/schedule%'`, so it works regardless of which
intermediate state (`000232`, `000262`, `000305`, or `000311`) is
currently in the row.

## What did not change

Historical SQL migrations `000232`, `000262`, `000305`, and `000311` are
not modified because migrations are immutable history. The 18 remaining
stale URL references in those files are superseded at runtime by
migration `000510`. This decision matches the pattern used in the A1
sister PR (#25740).

## Verification

- `go test ./coderd/database/migrations/... -count=1` (UP+DOWN)
- `go test ./coderd/notifications/ -run TestNotificationTemplates_Golden
-update -count=1` to regenerate the four `.golden` files
- `go test ./scripts/release/ -run Test_removeMainlineBlurb -count=1`
- `make pre-commit` (gen + fmt + lint + slim build) ran clean as part of
the commit hook

I also fixed a pre-existing emdash on line 35 of
`examples/templates/azure-linux/README.md` that the lint flagged once
the file entered my diff. The line was already in `main`, but `make gen`
rewrites `examples/examples.gen.json` whenever a `README.md` changes, so
the line came back as a `+` in the diff against `origin/main` and the
`lint/emdash` step refused it.

<details>
<summary>Pre-mortem</summary>

| Risk | Mitigation |
|---|---|
| Migration overwrites future template edits | Used `REPLACE` instead of
full body overwrite. `WHERE id IN (...) AND body_template LIKE
'%/docs/templates/schedule%'` further scopes the write |
| Goldens drift from migrated body | Regenerated goldens via `-update`
after the migration was in place, so the goldens reflect the
post-migration state |
| Down migration leaves stale URLs | Down migration reverses the REPLACE
so a rollback restores the prior URLs |
| Fragment loss when redirect strips fragment | Verified the destination
`schedule.md` contains `## Dormancy threshold` and `## Dormancy
auto-deletion` anchors |
| Terraform parse breakage in `examples/parameters/main.tf` | Only
comments changed; Terraform parser is unaffected |
| Test fixtures in `scripts/release` diverging from
`generate_release_notes.sh` | Updated to match the script, which already
emits `/docs/install/upgrade` |

</details>

---

Generated by Coder Agent on behalf of @nickvigilante.
2026-06-10 13:40:50 -04:00
McKayla はな d830582b5e chore(coderd/idpsync): remove stale TODO (#26198) 2026-06-10 10:20:18 -06:00
Cian JohnstonandCopilot Autofix powered by AI a26c46a3bf fix!: validate HostnameSuffix and SSHConfigOptions' (#26154)
- Adds server-side and client-side validation for
CODER_CONFIGSSH_HOSTNAME_SUFFIX and CODER_SSH_CONFIG_OPTIONS.
- **Server-side breaking change:** invalid values for either of these will cause `coderd` to exit with an error.
- Client-side: `coder config-ssh` will exit with an error if it detects invalid config.
- Adds tests for the above

Local smoke-testing: ran `develop.sh --env-file <path to an env file
containing badness>`. Validated that server startup failed as expected.

> 🤖 Generated by Coder Agents with supervision from a human.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-10 15:48:02 +01:00
Nick Vigilante 1dc12f8ae7 fix: rename bundled rstudio.svg to rproject.svg, add real RStudio icon (#26216)
The bundled `/icon/rstudio.svg` rendered the R language logo (gray oval,
blue R), not the RStudio IDE logo, so templates using the `rstudio`
`coder_app` and the bundled URL got the wrong artwork
([#26211](https://github.com/coder/coder/issues/26211), PRODUCT-383).

This PR:

- Renames the existing `rstudio.svg` (R language logo) to `rproject.svg`
so the artwork stays available for templates that want it.
- Adds a new `rstudio.svg` containing the actual RStudio R-ball logo,
extracted from the [Wikimedia
source](https://upload.wikimedia.org/wikipedia/commons/d/d0/RStudio_logo_flat.svg)
and normalized to `viewBox="0 0 256 256"` to match the rest of the icon
set.
- Adds `rproject.svg` to `site/src/theme/icons.json` so it appears in
the icon picker and gallery alongside `rstudio.svg`.
- Switches the `coder_app "rstudio"` example in
`docs/admin/templates/extending-templates/web-ides.md` to reference
`/icon/rstudio.svg` (and corrects `display_name` to `"RStudio"`),
matching every other example on that page.

| Path | Before | After |
| --- | --- | --- |
| `/icon/rstudio.svg` | R language logo | RStudio R-ball |
| `/icon/rproject.svg` | (did not exist) | R language logo |

<table>
<tr>
<th>Old <code>rstudio.svg</code> &rarr; new
<code>rproject.svg</code></th>
<th>New <code>rstudio.svg</code></th>
</tr>
<tr>
<td align="center"><img
src="https://raw.githubusercontent.com/coder/coder/vigilante/product-383-bundled-iconrstudiosvg-appears-to-show-r-language-logo/site/static/icon/rproject.svg"
width="128" height="128"></td>
<td align="center"><img
src="https://raw.githubusercontent.com/coder/coder/vigilante/product-383-bundled-iconrstudiosvg-appears-to-show-r-language-logo/site/static/icon/rstudio.svg"
width="128" height="128"></td>
</tr>
</table>

**Breaking-change note.** Templates that referenced `/icon/rstudio.svg`
expecting the R language oval will now render the RStudio R-ball.
Templates that want the R language logo should switch to
`/icon/rproject.svg`. The Linear issue acknowledges this tradeoff.

**Client cache caveat.** `site/site.go` serves everything under `/icon/`
with `Cache-Control: public, max-age=31536000, immutable`, so any
browser that already loaded the old artwork at `/icon/rstudio.svg` can
keep displaying it for up to a year before revalidating. A hard refresh
(Ctrl/Cmd+Shift+R) clears it immediately. Cache-busting (hashed icon
URLs) is out of scope for this fix and tracked as a possible follow-up
against PRODUCT-383.

<details>
<summary>Implementation notes</summary>

- Verified geometric fidelity by rendering the new SVG and a
high-resolution crop of the Wikimedia source at 256x256 and computing
the RMS pixel difference: 1.268/255 (~0.5%, essentially antialiasing
noise).
- Picked `viewBox="0 0 256 256"` because 139 of 142 SVGs in
`site/static/icon/` already use that viewBox.
- Searched the repo for `rstudio.svg` references: the only direct one is
`site/src/theme/icons.json`. The docs file references the `rstudio`
`coder_app` slug, not the icon path, so the rename does not break any
callsite.
- R-ball geometry: source circle at (318.7, 312.9) radius 309.8 in the
original `viewBox 0 0 1784.1 625.9`. Translating by (-8.9, -3.1) and
scaling by 256/619.6 maps its bounding box onto `0 0 256 256`. Path
coordinates are pre-computed so the file ships with no transform layer.
- Pre-commit hooks passed locally, including `lint/site-icons`.

</details>

Fixes #26211
Fixes PRODUCT-383

---

_Generated by Coder Agents on behalf of @nickvigilante._
2026-06-10 14:06:21 +00:00
Yevhenii Shcherbina 1cada0649c feat(coderd): resolve effective user AI budget (#26142)
Closes
https://linear.app/codercom/issue/AIGOV-287/add-effective-group-resolution

Implements the effective AI budget resolution from the AI Governance
cost-controls RFC: for a given user, a `user_ai_budget_overrides` row
wins if present, otherwise the deployment budget policy (`highest`)
picks the largest group budget across the user's groups, ties broken
alphabetically.

For now, I keep the logic under `coderd/aibridge/budget`, but that may
change during the implementation of budget enforcement.
2026-06-10 14:01:20 +00:00
Cian Johnston f9dfa18c46 fix(coderd/x/chatd): retry quota 429s (#26200)
Fixes CODAGT-495

Provider 429 responses that mention quota or billing were classified as
non-retryable usage limits before the rate-limit rule could run, which
suppressed retries for Gemini and Azure OpenAI rate limits.

- Treats broad quota and billing prose as rate-limit retryable when the provider returns HTTP 429.
- Preserves `insufficient_quota` as a terminal usage-limit signal for OpenAI billing exhaustion.
- Includes structured provider details in usage-limit matching so response-body error codes are classified consistently.

Generated by Coder Agents on behalf of @johnstcn.
2026-06-10 11:01:33 +01:00
Jaayden Halko c1731722af fix(site): stop sidebar scrollbar hit-area from covering chat row controls (#26209)
The Agents chat list scrollbar swallowed clicks on the per-row controls
(the actions menu, timestamp, and unread/shared indicators). PR #26016
added a 24px invisible hit-target to the shared `ScrollArea` thumb,
anchored to the thumb's right edge and extending left. On this sidebar
the visible scrollbar is only ~6px wide (`w-1.5`), so the hit-target
reached ~18px left of it, on top of the controls just inside the edge.

This adds an optional, default-preserving `scrollThumbClassName` prop to
the shared `ScrollArea`, threaded through `ScrollBar` to the thumb the
same way `scrollBarClassName` already is. When the prop is omitted the
output is byte-for-byte unchanged, so every other scrollbar keeps the
24px target. The Agents chat list passes `before:hidden` to drop only
the expanded hit-target: the visible 6px thumb stays draggable and the
scrollbar looks identical, so there is no visible change while the
controls beside it become clickable again.

A new `ScrollArea` story (`ThumbHitAreaOverride`) uses `type="always"`
so the thumb is guaranteed to render, then asserts the default keeps the
24px `::before` target while the override sets `display: none`.

Refs #26016
2026-06-10 10:06:33 +01:00
Danny Kopping 4e87fdb20c fix(aibridge/intercept/messages): record user prompt before trailing system message (#26195)
_Disclosure: produced using Opus 4.8_

I've noticed recently that some prompts are not displaying correctly.

<img width="1388" height="509" alt="image"
src="https://github.com/user-attachments/assets/fad3812f-e42d-4398-a16c-a0e7f924455d"
/>

The cause is the `mid-conversation-system-2026-04-07` beta. When
enabled, the client appends a trailing `role: "system"` message after
the user's text (e.g. an injected skills list):

```json
"messages": [
  { "role": "user",   "content": [ "hey how are ya" ] },
  { "role": "system", "content": "The following skills are available..." }
]
```

Our prompt detection algo was being subverted since we only check the
last message if role=user.
2026-06-10 10:47:13 +02:00
Jon Ayers 35a7dc8ab9 fix: use a random value for a simulated hash for built-in users (#26205) 2026-06-10 02:18:44 -05:00
Kyle Carberry cc9f10fbf2 fix(agent/agentcontext): canonicalize scan root in symlink boundary check (#26175) 2026-06-09 19:21:55 -07:00
Ethan deb6eec68b fix: forward attached filenames to Anthropic chat models (#26051)
Previously, fantasy's Anthropic provider adapter accepted PDF and text
FileParts but dropped the filename on the floor, so Claude (direct or
via Bedrock) saw the document bytes without any handle and could not
answer questions like "what's in foo.pdf". Other providers (OpenAI,
Gemini, OpenRouter, Vercel) already forwarded filenames.

Bumps `coder/fantasy` past
[coder/fantasy#38](https://github.com/coder/fantasy/pull/38), which
sanitizes `FilePart.Filename` and sets it as the Anthropic
`DocumentBlockParam.Title` for both `application/pdf` and `text/*`
attachments, and emits a `CallWarning` for unsupported `FilePart` media
types instead of silently dropping them.

On this side, plumbs the resolved filename through `partsToMessageParts`
so the `FilePart` literal carries it into the provider. The existing
`TestModelFromConfig_AnthropicPDFFilePartReachesProvider` regression
test is extended to assert the outbound Anthropic request includes the
sanitized title (`quarterly_report.v1.pdf` becomes `quarterly report v1
pdf`).

Closes CODAGT-545
2026-06-10 11:37:33 +10:00
Yevhenii Shcherbina 360611ea15 feat: audit user AI budget override mutations (#25745)
Relates to
https://linear.app/codercom/issue/AIGOV-285/add-user-budget-overrides-table-and-crud-api

Adds audit-log support for `user_ai_budget_override` mutations. Without
it, an admin could quietly change a user's per-user spend cap (e.g. from
`$500` to `$50`), reassign it to a different group, or delete it
entirely with no record of who did it.

Both write (`create-or-update`) and delete actions now generate audit
log entries. Unlike group AI budgets, which only track `spend_limit`,
overrides also track `group_name`: an override can be reassigned to a
different attributed group, so that change needs to show up in the diff.
The raw `spend_limit_micros`, IDs, and timestamps are ignored in favor
of the human-readable `spend_limit` and `group_name`.

Depends on #25439.

## Screenshot

<img width="1343" height="514" alt="image"
src="https://github.com/user-attachments/assets/aee30f58-6e81-435e-9bca-5bc98f49d8d3"
/>
2026-06-10 00:29:06 +00:00
Susana Ferreira f95f5e6f86 docs: rename "AI Bridge" to "AI Gateway" (#26165)
Updates hand-written documentation to use "AI Gateway" instead of "AI
Bridge" as a follow-up to the UI rename in
https://github.com/coder/coder/pull/26161#issuecomment-4660014072.

Changed files:
- `docs/ai-coder/ai-gateway/clients/codex.md` — display name and config
key (`aibridge` to `ai_gateway`) in TOML config examples
- `docs/ai-coder/ai-gateway/clients/factory.md` — display names in JSON
config examples and prose
- `docs/ai-coder/ai-gateway/monitoring.md` — structured logging
description
- `docs/ai-coder/ai-gateway/ai-gateway-proxy/setup.md` — CA cert example
filenames (`coder-aibridge-proxy-ca.pem` to
`coder-ai-gateway-proxy-ca.pem`)
- `docs/ai-coder/ai-gateway/clients/copilot.md` — CA cert example
filenames
- `docs/ai-coder/ai-gateway/clients/index.md` — CA cert example filename

Generated reference docs (`docs/reference/cli/`, `docs/reference/api/`)
and `docs/manifest.json` are generated from Go code and will update
automatically via `make gen` in the context of AIGOV-230 (API swagger
tags) and AIGOV-231 (CLI help).

Refs https://linear.app/codercom/issue/AIGOV-233

> Generated by Coder Agents on behalf of @ssncferreira
2026-06-09 20:23:18 +01:00
Danielle Maywood 909f6f4e1a fix(site/src/pages/AgentsPage): improve live tool activity (#26147) 2026-06-09 19:50:29 +01:00
Paweł Banaszewski 0d2c9f904a fix: check user user is active in aibridge auth (#26173)
Adds check that user is active when authenticating request in AI
Gateway.
2026-06-09 19:01:23 +02:00
Paweł BanaszewskiandDanny Kopping aba94072fe fix: add max bytes request limit to aibridge (#26164)
Adds limit of 32MiB limit to request body in all aibridge endpoints.

---------

Co-authored-by: Danny Kopping <danny@coder.com>
2026-06-09 16:25:13 +00:00
coder-tasks[bot]anddoc-check[bot] ace1a5a910 docs(install/releases): update latest branch releases (#26167)
Update release calendar with this week's latest branch releases:

- v2.34.0 → v2.34.1 (Mainline/ESR)
- v2.33.6 → v2.33.7 (Stable)
- v2.32.5 → v2.32.6 (Security Support)

Also updates the ESR version link in the prose to point to v2.34.1.

Fixes: https://linear.app/codercom/issue/PLAT-321

> Generated by Coder Agents (session: plat-321-update-release-docs)

Co-authored-by: doc-check[bot] <doc-check[bot]@users.noreply.github.com>
2026-06-09 11:10:28 -04:00
Ethan 6d5b2921f7 fix(site/src/pages/AgentsPage): keep terminal tabs rightmost (#26166)
This updates the agents right-panel tab model so Desktop is included in
the normal tab list instead of being rendered separately by
`SidebarTabView`. Desktop now appears before terminal tabs, which keeps
the built-in terminal and any newly opened terminal tabs at the right
edge. `SidebarTabView` no longer needs a Desktop-specific prop or render
path because it simply renders the ordered tabs it receives.
2026-06-09 15:06:48 +00:00
J. Scott Miller 1ed5c6f9df fix(dogfood/coder): install libx11-xcb1 for desktop Chrome (#26149)
## Problem

Launching the system Google Chrome from the portabledesktop/VNC session
in dogfood workspaces crashes immediately (SIGTRAP, exit 133). Headless
Chrome and Playwright's bundled Chromium are unaffected, so it only
shows up when a user opens Chrome in the desktop.

Root cause traced via `strace`: Chrome `dlopen`s `libX11-xcb.so.1` when
it initializes the X11 GUI path and `IMMEDIATE_CRASH()`es when the
library is missing:

```
openat(... "/usr/lib/x86_64-linux-gnu/libX11-xcb.so.1" ...) = -1 ENOENT
... --- SIGTRAP {si_signo=SIGTRAP, si_code=SI_KERNEL} ---
```

The Google Chrome `.deb` declares `libx11-6` and `libxcb1` but **not**
`libx11-xcb1`, so apt never installs it.

## Why it regressed (~2 weeks ago)

`libx11-xcb1` used to be pulled in transitively by the build-time step:

```
pnpm dlx playwright@1.47.0 install --with-deps chromium
```

`--with-deps` makes Playwright `apt-get install` Chromium's full
system-library set, which on Ubuntu includes `libx11-xcb1`.

#25448 ("refactor: build dogfood image as base + mise oci layers")
removed that build step from both Ubuntu Dockerfiles and moved the
install to the workspace-start `install-deps` script, which runs
`playwright install chromium` / `playwright-core install --no-shell
chromium` **without** `--with-deps`. Those download only the browser
binaries, not the apt system libraries, so `libx11-xcb1` disappeared
from the image.

## Fix

Install `libx11-xcb1` explicitly in both `ubuntu-22.04` and
`ubuntu-26.04` `Dockerfile.base` apt lists, decoupling desktop Chrome's
X libraries from the Playwright install so it can't silently regress
again.

## Testing

Reproduced and verified on a running dogfood workspace (Ubuntu 22.04):
before the fix, `DISPLAY=:1 google-chrome` crashed with SIGTRAP on the
missing `libX11-xcb.so.1`; after `apt-get install -y libx11-xcb1`, a
vanilla `google-chrome` launch (as the desktop menu invokes it) starts
and stays running with a renderer process. Remaining EGL/GPU warnings
are expected (software rendering under VNC) and non-fatal.

<details>
<summary>Investigation notes</summary>

- headless Chrome and `--screenshot` worked, isolating the failure to
the X11/Ozone GUI path.
- The earlier `crashpad ... format error / Unknown ptrace scope`
messages were a red herring; the real crash was the missing-library
`dlopen`.
- `portabledesktop` ships a self-contained Xvnc server + WM runtime (its
own glibc closure) and does not provide libraries to system apps like
Chrome, so the fix belongs in the dogfood image.

</details>

---
Generated with Coder Agents.
2026-06-09 09:29:49 -05:00
Susana Ferreira 777ac44226 refactor: rename "AI Bridge" to "AI Gateway" in the UI (#26161)
Renames all user-visible "AI Bridge" strings to "AI Gateway" in the
browser UI as part of the AI Bridge to AI Gateway rebrand (AIGOV-233).

Changes:
- Page titles and headings ("AI Bridge Logs" to "AI Gateway Logs",
`pageTitle` calls)
- Help popover title, description, and doc link
- Setup alert title, description, and doc link
- Back-link tooltip on session threads page
- AI add-on help popover text
- License entitlement warning shown in the dashboard banner

Doc links updated from `/ai-coder/ai-bridge` to `/ai-coder/ai-gateway`
(directory already exists).

This PR intentionally does not rename internal identifiers,
file/directory names, API endpoints, routes, CLI help, deployment config
options, or generated types. Those will be tracked separately.

Related to: https://linear.app/codercom/issue/AIGOV-233

> Generated by Coder Agents on behalf of @ssncferreira
2026-06-09 15:11:27 +01:00
Ethan db00007605 feat: support multiple terminal tabs on the agents right panel (#26089)
- Adds a dynamic terminal tab model to the Coder Agents right panel so
users can open, switch between, and close multiple Web Terminal sessions
for the same agent.
- Each terminal tab generates its own UUID reconnect token and is
persisted per agent in local storage, so tabs and their PTY sessions
survive reloads.
- New terminal tabs are auto-labelled (`Terminal 2`, `Terminal 3`, ...),
filling the lowest free number.
- The built-in Terminal tab is now closeable; closing it hides it and
persists that choice per agent, and it can be restored from the add-tab
control.
- Only the active terminal (and a tab that is mid-activation) mounts the
expensive xterm/WebSocket/PTY resources; a freshly hidden terminal stays
warm for 30s to keep quick tab toggles instant, then detaches to bound
resource usage instead of capping the tab count.
- Inactive terminals stay laid out but hidden, and a newly opened
terminal is not activated until it reports ready (or 100ms), avoiding
the narrow refit and blank-frame flicker when switching between terminal
canvases.
- The right-panel tab bar scrolls horizontally with chevron controls
when tabs overflow, keeping everything on a single row.
- Per-agent right-panel tab and hidden-terminal state is cleared from
local storage when a chat is archived or deleted.
- Adds unit tests for the tab utilities, persistence helpers, and the
warm/detach lifecycle hook, plus Storybook play-function coverage for
the tab and terminal components.

Relates to CODAGT-346
2026-06-10 00:08:01 +10:00
dependabot[bot] 9408b9d89b chore: bump github.com/gohugoio/hugo from 0.162.0 to 0.163.0 (#26157)
Bumps [github.com/gohugoio/hugo](https://github.com/gohugoio/hugo) from
0.162.0 to 0.163.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gohugoio/hugo/releases">github.com/gohugoio/hugo's
releases</a>.</em></p>
<blockquote>
<h2>v0.163.0</h2>
<p>The main topic in this release is improvements to the AVIF image
handling that we introduced in <code>v0.162.0</code>. See <a
href="https://gohugo.io/configuration/imaging/#avif">the docs</a> for
details, but:</p>
<ul>
<li>We have turned down the default <code>quality</code> for AVIF to 60.
Turns out, JPEG/WebP with quality 75 is comparable to AVIF with quality
60. You can now also set quality per image format in your project config
(and also per image processed if needed).</li>
<li>We have added a <code>hint</code> to the AVIF with the same values
as for <code>WEBP</code>. For <code>lossy</code> compression, the
photo/picture hints (and the default) encodes with YUV420 chroma
subsampling instead of YUV444, keeping 444 for text/icon/drawing. This
greatly reduces the memory needed to encode these images.</li>
</ul>
<h2>Improvements</h2>
<ul>
<li>resources/jsconfig: Remove deprecated baseUrl setting ff2903a9 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14991">#14991</a>
<a
href="https://redirect.github.com/gohugoio/hugo/issues/14996">#14996</a></li>
<li>all: Adjust tests for deprecated link and image render hook settings
ca68936d <a
href="https://github.com/jmooring"><code>@​jmooring</code></a></li>
<li>all: Run go fix ./... 781fabf4 <a
href="https://github.com/bep"><code>@​bep</code></a></li>
<li>pagesfromdata: Use relative path for content adapter template
metrics 1d018ef8 <a
href="https://github.com/anupamojha-eng"><code>@​anupamojha-eng</code></a>
<a
href="https://redirect.github.com/gohugoio/hugo/issues/14999">#14999</a></li>
<li>ci: Re-add macos-latest to the test matrix 121bc6ce <a
href="https://github.com/bep"><code>@​bep</code></a></li>
<li>images: Deprecate Imaging.Compression and move it down to webp and
avif configs cf18b827 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14998">#14998</a></li>
<li>Only support the latest Go version 98ad9b3c <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14997">#14997</a></li>
<li>page: Add IsBranch and deprecate IsNode b89e7fe6 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/11574">#11574</a></li>
<li>images: Force cache invalidation for AVIF target e8fefc83 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14990">#14990</a></li>
<li>images: Add a per-format AVIF hint setting a043d3ec <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14992">#14992</a></li>
<li>images: Make AVIF chroma subsampling content-aware via the hint
341f575d <a href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14987">#14987</a></li>
<li>Cap AVIF lossy quality at 99 248241b6 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14981">#14981</a></li>
<li>config: Deprecate the glogal imaging quality setting 4e47d95d <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14979">#14979</a></li>
<li>images: Make 60 the default quality for AVIF 03b4b542 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14979">#14979</a></li>
<li>livereload: Disconnect from websocket server on pageswap 79be0532 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14983">#14983</a></li>
<li>tpl/tplimpl/embedded: Prevent leading newline in sitemap template
0f440460 <a href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14977">#14977</a></li>
<li>images: Recover from memory alloc errors in WASM image processors
4e17421e <a href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14985">#14985</a></li>
<li>images: Add quality setting per image format b01ecd4c <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14957">#14957</a></li>
<li>misc: Remove duplicate words in comments 45c00b7c <a
href="https://github.com/jmooring"><code>@​jmooring</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14936">#14936</a>
<a
href="https://redirect.github.com/gohugoio/hugo/issues/14950">#14950</a>
<a
href="https://redirect.github.com/gohugoio/hugo/issues/14965">#14965</a></li>
<li>Add some PNG to AVIF golden test cases 28d882ab <a
href="https://github.com/bep"><code>@​bep</code></a></li>
</ul>
<h2>Dependency Updates</h2>
<ul>
<li>build(deps): bump github.com/bits-and-blooms/bitset 0d29fc81 <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]</li>
<li>build(deps): bump github.com/tetratelabs/wazero bb57404f <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]</li>
<li>build(deps): bump github.com/rogpeppe/go-internal from 1.14.1 to
1.15.0 7d1b1fb3 <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]</li>
<li>build(deps): bump github.com/getkin/kin-openapi from 0.138.0 to
0.139.0 77a11470 <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]</li>
</ul>
<h2>v0.162.1</h2>
<h2>What's Changed</h2>
<ul>
<li>modules/npm: Fix false stale warning after npm pack 59f35cd9 <a
href="https://github.com/jmooring"><code>@​jmooring</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14959">#14959</a></li>
<li>Revert &quot;tpl/collections: Make dict return nil when no values
are provided&quot; c2709750 <a
href="https://github.com/bep"><code>@​bep</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14958">#14958</a></li>
<li>tpl/time: Fix locale-specific month abbreviations ea8b48af <a
href="https://github.com/jmooring"><code>@​jmooring</code></a> <a
href="https://redirect.github.com/gohugoio/hugo/issues/14948">#14948</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/gohugoio/hugo/commit/4a9485336a3ff2cea07ab88e2a17ec34d5baaa6e"><code>4a94853</code></a>
releaser: Bump versions for release of 0.163.0</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/1d018ef8573e1cbeca6c05b6df0792cb5f672541"><code>1d018ef</code></a>
pagesfromdata: Use relative path for content adapter template
metrics</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/121bc6ceb232effd98a85a5fec357181be8ff01e"><code>121bc6c</code></a>
ci: Re-add macos-latest to the test matrix</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/0d29fc81bb559750644bc163ec67f21f3c36ed1b"><code>0d29fc8</code></a>
build(deps): bump github.com/bits-and-blooms/bitset</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/bb57404f3d93cd588e98f34c742b8b7c2741a4c7"><code>bb57404</code></a>
build(deps): bump github.com/tetratelabs/wazero</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/781fabf4e406aae6b888d4f9f68331e7f13e89aa"><code>781fabf</code></a>
all: Run go fix ./...</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/cf18b827e2bebe95f87b36bff9937218348a55ca"><code>cf18b82</code></a>
images: Deprecate Imaging.Compression and move it down to webp and avif
configs</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/98ad9b3c03278d0af3ebd13f8ec9fc1a71d46745"><code>98ad9b3</code></a>
Only support the latest Go version</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/ff2903a9317ba45a65f9963f837c66cc6bce3c0e"><code>ff2903a</code></a>
resources/jsconfig: Remove deprecated baseUrl setting</li>
<li><a
href="https://github.com/gohugoio/hugo/commit/7d1b1fb33dd7bdbb0d16dde9509ce15d93f7d894"><code>7d1b1fb</code></a>
build(deps): bump github.com/rogpeppe/go-internal from 1.14.1 to
1.15.0</li>
<li>Additional commits viewable in <a
href="https://github.com/gohugoio/hugo/compare/v0.162.0...v0.163.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/gohugoio/hugo&package-manager=go_modules&previous-version=0.162.0&new-version=0.163.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-09 11:14:22 +00:00
Michael SuchaczandSusana Cardoso Ferreira c349ea6b78 fix: preserve gemini thought signatures (#25933)
AI Bridge reserializes OpenAI chat-completions requests before sending
them upstream. For Gemini OpenAI-compatible routes, that OpenAI
typed-parameter round trip drops
`tool_calls[].extra_content.google.thought_signature`, so Google rejects
tool-result continuations with `Function call is missing a
thought_signature`.

This PR:
- patches the AI Bridge upstream serialization boundary for Gemini
OpenAI-compatible chat completions
- shares the Gemini thought-signature patching helpers with chatd's
OpenAI-compatible transport patch to keep behavior consistent
- treats direct Google OpenAI-compatible upstream endpoints as
Gemini-scoped even when the request model is an alias
- adds the Google fallback thought signature to every assistant tool
call in the active turn, including parallel tool calls
- covers the regression that `extra_content` is dropped before the
upstream body is patched

> Mux updated this PR description on behalf of Mike.

---------

Co-authored-by: Susana Cardoso Ferreira <susana@coder.com>
2026-06-09 12:11:43 +01:00
Susana Ferreira a9fb2619e4 fix: always verify TLS on aibridgeproxyd upstream transport (#26131)
## Problem

aibridgeproxyd's HTTP transport (`proxy.Tr`) was configured with secure
TLS defaults only when an upstream proxy was set. Without one, it fell
back to [goproxy's default
transport](https://github.com/elazarl/goproxy/blob/v1.8.0/proxy.go#L152),
which has `InsecureSkipVerify: true`, leaving the connection between the
proxy and aibridge vulnerable to MITM on HTTPS deployments.

This PR moves the secure transport assignment outside the upstream proxy
branch so it applies unconditionally.

## Changes

* Apply secure TLS defaults to `proxy.Tr` unconditionally (verified
`RootCAs`, `MinVersion: TLS 1.2`).
* Add `TestProxy_AIBridgeTLSVerification` to cover the verification path
between the proxy and aibridge.

## Notes

* **Behavior change for `HTTPS_PROXY` env var**: previously, when
`UpstreamProxy` was unset, `proxy.Tr` honored `HTTP_PROXY` and
`HTTPS_PROXY` env vars. After this PR it does not, since MITM'd requests
now always go directly to aibridge. This matches the behavior when
`UpstreamProxy` is configured, which already ignored env vars.
* **HTTPS deployments with a private CA**: when `CoderAccessURL` is
HTTPS and its TLS certificate (or the load balancer's certificate
fronting it) is signed by a CA not in the system trust store, the proxy
will now fail with `x509: certificate signed by unknown authority`.

Closes
https://linear.app/codercom/issue/AIGOV-386/ai-bridge-proxy-uses-goproxy-default-with-tls-verification-disabled

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by
@ssncferreira
2026-06-09 11:53:38 +01:00
Susana Ferreira 01ec5e4577 feat: add key pool failover metrics to aibridge (#25901)
## Description

This PR adds Prometheus metrics for aibridge's API-key failover, giving visibility into key pool health and failover behavior per provider.

The following metrics are introduced:

- **`key_pool_state`** (gauge): number of keys currently in each state (`valid`, `temporary`, `permanent`) per provider, sampled at scrape time.
- **`key_pool_state_transitions_total`** (counter): key state transitions during failover, labeled by `reason` (`rate_limited`, `unauthorized`, `forbidden`).
- **`key_pool_exhaustions_total`** (counter): times a pool ran out of usable keys, labeled by `outcome` (`rate_limited`, `auth_failed`).
- **`key_pool_failover_attempts`** (histogram): keys attempted before success or exhaustion (per interception for bridged requests, per request for passthrough).

## Changes

- Moves `MarkKeyOnStatus` and key-pool error handling onto `*keypool.Pool`.
- Attaches metrics to each provider's key pool at install time, on construction and on provider reload.
- Adds a scrape-time state collector and a `KeyPools()` accessor on the bridge pool to feed it.
- Tracks per-request key attempts in the bridged and passthrough failover paths.
- Adds test coverage for the new metrics across the keypool unit tests, the bridged intercept failover tests, and the passthrough failover test.

Closes https://github.com/coder/internal/issues/1447
Closes https://linear.app/codercom/issue/AIGOV-198/aibridge-key-failover-observability

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-06-09 10:49:47 +01:00
Susana Ferreira f8c736f859 refactor(aibridge): consolidate key failover interceptor tests (#26032)
Consolidates the per-interceptor key-failover tests into a single table-driven `keyfailover_test.go`, parameterized over the interceptors (`messages`, `chatcompletions`, `responses`) and modes (blocking and streaming).

It keeps the two scenarios as separate tests: `TestInterception_KeyFailover` (failover within a single interception) and `TestInterception_AgenticLoopFailover` (failover across an agentic-loop continuation). Same cases and assertions as before with far less duplication, reusing the shared `testutil` mocks (`MockUpstream`, `MockServerProxier`, fixture helpers).

Closes https://linear.app/codercom/issue/AIGOV-396/consolidate-intercept-key-failover-tests-across-modes-and-providers
Closes https://linear.app/codercom/issue/AIGOV-395/share-a-single-mockupstream-helper-between-integration-tests-and

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-06-09 10:36:36 +01:00
Susana Ferreira f440cbd205 refactor(aibridge): move shared mock helpers to testutil (#25999)
Moves the shared aibridge mock test helpers (`MockUpstream`, `MockServerProxier`, `StubToolCaller`, and the `NewFixtureResponse`/`NewFixtureToolResponse` constructors) out of `aibridge/internal/integrationtest` into `aibridge/internal/testutil`, and exports them.

This lets the per-interceptor test packages (`messages`, `chatcompletions`, `responses`) reuse one set of mocks instead of each redefining its own. The symbols are exported and call sites updated, with no behavior change.

Closes: https://linear.app/codercom/issue/AIGOV-397/move-mockserverproxier-into-a-shared-testutil-package

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-06-09 10:24:33 +01:00
dependabot[bot] 75dbc57de2 chore: bump coder-labs/codex/coder from 5.0.0 to 5.1.0 in /dogfood/coder (#26152)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder-labs/codex/coder&package-manager=terraform&previous-version=5.0.0&new-version=5.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-09 00:27:06 +00:00
dependabot[bot] c9650c2bba chore: bump the coder-modules group across 3 directories with 1 update (#26151)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-09 00:26:53 +00:00
McKayla はな f242ef0799 feat(site): copy PR branch name from git panel (#25589) 2026-06-08 13:21:18 -06:00