Commit Graph
15380 Commits
Author SHA1 Message Date
dependabot[bot] 69a045f944 chore: bump axios from 1.16.1 to 1.18.0 in /site (#27350)
Bumps [axios](https://github.com/axios/axios) from 1.16.1 to 1.18.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/releases">axios's
releases</a>.</em></p>
<blockquote>
<h2>v1.18.0 — June 13, 2026</h2>
<p>This release hardens redirect and URL handling, improves the
validateStatus configuration semantics, and includes updates to
documentation, dependencies, and release metadata.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Redirect Header Safety:</strong> Added Node HTTP adapter
support for stripping caller-specified sensitive headers on cross-origin
redirects, helping prevent custom auth headers such as API keys from
leaking to another origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a></strong>)</p>
</li>
<li>
<p><strong>URL And Request Hardening:</strong> Rejects malformed
<code>http:</code> and <code>https:</code> URLs that omit
<code>//</code> with <code>ERR_INVALID_URL</code>, while tightening
prototype-pollution-safe config reads, stream size limits, FormData
depth handling, data URL sizing, and local <code>NO_PROXY</code>
matching. (<strong><a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a></strong>)</p>
</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Status Validation:</strong> Added
<code>transitional.validateStatusUndefinedResolves</code> so
applications can opt in to treating <code>validateStatus:
undefined</code> like the option was omitted, while
<code>validateStatus: null</code> remains the explicit way to accept
every status. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li>
<p><strong>Documentation:</strong> Published the v1.17.0 release notes,
fixed a changelog typo, clarified the package update PR policy, and
marked the <code>proxy</code> request config as Node.js-only in the
advanced docs. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</p>
</li>
<li>
<p><strong>Dependencies:</strong> Bumped <code>@babel/core</code>,
<code>@babel/preset-env</code>, <code>@commitlint/cli</code>,
<code>@commitlint/config-conventional</code>,
<code>@rollup/plugin-babel</code>, <code>@rollup/plugin-commonjs</code>,
<code>@vitest/browser</code>, <code>@vitest/browser-playwright</code>,
<code>eslint</code>, <code>lint-staged</code>, <code>rollup</code>,
<code>vitest</code>, and <code>actions/checkout</code>. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10996">#10996</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10997">#10997</a></strong>)</p>
</li>
<li>
<p><strong>Release Metadata:</strong> Prepared the 1.18.0 release by
updating package metadata and the runtime <code>VERSION</code> value.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a></strong>)</p>
</li>
</ul>
<h2>🌟 New Contributors</h2>
<p>We are thrilled to welcome our new contributors. Thank you for
helping improve axios:</p>
<ul>
<li><strong><a
href="https://github.com/drori12"><code>@​drori12</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>)</li>
<li><strong><a
href="https://github.com/eyupcanakman"><code>@​eyupcanakman</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
<li><strong><a
href="https://github.com/Adi-Beker"><code>@​Adi-Beker</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.17.0...v1.18.0">Full
Changelog</a></p>
<h2>v1.17.0 — June 1, 2026</h2>
<p>This release adds Node HTTP zstd decompression, hardens config and
release workflows, and fixes authentication, header, proxy, and
type-handling regressions.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Config Hardening:</strong> Guarded <code>socketPath</code>,
<code>params</code>, and <code>paramsSerializer</code> reads with
own-property checks to prevent inherited prototype values from affecting
request behavior, including SSRF-sensitive paths. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10901">#10901</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10922">#10922</a></strong>)</li>
<li><strong>Release Publishing:</strong> Switched the publish workflow
to npm staged publishing for safer, auditable package releases with
provenance. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10926">#10926</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>HTTP Compression:</strong> Added Node HTTP adapter support
for zstd response decompression, with
<code>transitional.advertiseZstdAcceptEncoding</code> controlling
whether <code>zstd</code> is advertised in <code>Accept-Encoding</code>.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/6792">#6792</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10920">#10920</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Authentication Handling:</strong> Restored Basic auth on
same-origin Node redirects while continuing to strip credentials
cross-origin, and aligned the fetch adapter with HTTP adapter behavior
for URL-embedded Basic auth. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10929">#10929</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10896">#10896</a></strong>)</li>
<li><strong>Proxy TLS:</strong> Preserved user <code>httpsAgent</code>
TLS options when tunneling HTTPS requests through HTTP CONNECT proxies.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10957">#10957</a></strong>)</li>
<li><strong>React Native FormData:</strong> Cleared default
<code>Content-Type</code> for React Native <code>FormData</code> so
multipart boundaries can be generated correctly. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10898">#10898</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's
changelog</a>.</em></p>
<blockquote>
<h2>v1.18.0 — June 13, 2026</h2>
<p>This release hardens redirect and URL handling, improves the
validateStatus configuration semantics, and includes updates to
documentation, dependencies, and release metadata.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Redirect Header Safety:</strong> Added Node HTTP adapter
support for stripping caller-specified sensitive headers on cross-origin
redirects, helping prevent custom auth headers such as API keys from
leaking to another origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a></strong>)</p>
</li>
<li>
<p><strong>URL And Request Hardening:</strong> Rejects malformed
<code>http:</code> and <code>https:</code> URLs that omit
<code>//</code> with <code>ERR_INVALID_URL</code>, while tightening
prototype-pollution-safe config reads, stream size limits, FormData
depth handling, data URL sizing, and local <code>NO_PROXY</code>
matching. (<strong><a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a></strong>)</p>
</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Status Validation:</strong> Added
<code>transitional.validateStatusUndefinedResolves</code> so
applications can opt in to treating <code>validateStatus:
undefined</code> like the option was omitted, while
<code>validateStatus: null</code> remains the explicit way to accept
every status. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li>
<p><strong>Documentation:</strong> Published the v1.17.0 release notes,
fixed a changelog typo, clarified the package update PR policy, and
marked the <code>proxy</code> request config as Node.js-only in the
advanced docs. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</p>
</li>
<li>
<p><strong>Dependencies:</strong> Bumped <code>@babel/core</code>,
<code>@babel/preset-env</code>, <code>@commitlint/cli</code>,
<code>@commitlint/config-conventional</code>,
<code>@rollup/plugin-babel</code>, <code>@rollup/plugin-commonjs</code>,
<code>@vitest/browser</code>, <code>@vitest/browser-playwright</code>,
<code>eslint</code>, <code>lint-staged</code>, <code>rollup</code>,
<code>vitest</code>, and <code>actions/checkout</code>. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10996">#10996</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10997">#10997</a></strong>)</p>
</li>
<li>
<p><strong>Release Metadata:</strong> Prepared the 1.18.0 release by
updating package metadata and the runtime <code>VERSION</code> value.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a></strong>)</p>
</li>
</ul>
<h2>🌟 New Contributors</h2>
<p>We are thrilled to welcome our new contributors. Thank you for
helping improve axios:</p>
<ul>
<li><strong><a
href="https://github.com/drori12"><code>@​drori12</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>)</li>
<li><strong><a
href="https://github.com/eyupcanakman"><code>@​eyupcanakman</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
<li><strong><a
href="https://github.com/Adi-Beker"><code>@​Adi-Beker</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.17.0...v1.18.0">Full
Changelog</a></p>
<h2>v1.17.0 — June 1, 2026</h2>
<p>This release adds Node HTTP zstd decompression, hardens config and
release workflows, and fixes authentication, header, proxy, and
type-handling regressions.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Config Hardening:</strong> Guarded <code>socketPath</code>,
<code>params</code>, and <code>paramsSerializer</code> reads with
own-property checks to prevent inherited prototype values from affecting
request behavior, including SSRF-sensitive paths. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10901">#10901</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10922">#10922</a></strong>)</li>
<li><strong>Release Publishing:</strong> Switched the publish workflow
to npm staged publishing for safer, auditable package releases with
provenance. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10926">#10926</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>HTTP Compression:</strong> Added Node HTTP adapter support
for zstd response decompression, with
<code>transitional.advertiseZstdAcceptEncoding</code> controlling
whether <code>zstd</code> is advertised in <code>Accept-Encoding</code>.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/6792">#6792</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10920">#10920</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Authentication Handling:</strong> Restored Basic auth on
same-origin Node redirects while continuing to strip credentials
cross-origin, and aligned the fetch adapter with HTTP adapter behavior
for URL-embedded Basic auth. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10929">#10929</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10896">#10896</a></strong>)</li>
<li><strong>Proxy TLS:</strong> Preserved user <code>httpsAgent</code>
TLS options when tunneling HTTPS requests through HTTP CONNECT proxies.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10957">#10957</a></strong>)</li>
<li><strong>React Native FormData:</strong> Cleared default
<code>Content-Type</code> for React Native <code>FormData</code> so
multipart boundaries can be generated correctly. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10898">#10898</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/2d06f96e8602c2db13b65a26340ee4a1bbc0b61f"><code>2d06f96</code></a>
chore(release): prepare release 1.18.0 (<a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2"><code>32fc489</code></a>
fix: malformed http urls (<a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/b40ce498abfa10d90b873b4fd08f520afa5d2545"><code>b40ce49</code></a>
chore(deps-dev): bump the development_dependencies group with 10 updates
(<a
href="https://redirect.github.com/axios/axios/issues/10">#10</a>...</li>
<li><a
href="https://github.com/axios/axios/commit/fe964f960ecb52c3e1155b0daf7be77541956b01"><code>fe964f9</code></a>
docs: mark proxy config as Node.js only (<a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/5f229d2d1f018d1db3dab6bbe034dbf3f9041b99"><code>5f229d2</code></a>
chore(deps): bump actions/checkout from 6.0.2 to 6.0.3 in the
github-actions ...</li>
<li><a
href="https://github.com/axios/axios/commit/fae9d4e7db6a858c407c75e607a071c533c5c4f6"><code>fae9d4e</code></a>
docs: clarify package update PR policy (<a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/28ab2ced820e55192806c53472ab3eb0cbb68dc2"><code>28ab2ce</code></a>
chore(deps-dev): bump the development_dependencies group with 2 updates
(<a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/a8e4f13aeecc45a3b8fab3ecfd9ddb5d70fb772b"><code>a8e4f13</code></a>
fix(core): keep default validateStatus when request passes undefined (<a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/614f4552a17de757d4171ad7c3bd38c9c1025fd8"><code>614f455</code></a>
docs: publish v1.17.0 release notes (<a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/6bb12c191f5380fad321322fb90216ae0dc36985"><code>6bb12c1</code></a>
fix: custom auth headers not stripped on cross-origin redirects (<a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.16.1...v1.18.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=axios&package-manager=npm_and_yarn&previous-version=1.16.1&new-version=1.18.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)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/coder/coder/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 19:06:59 +00:00
Michael Suchacz 4ed6fcced7 refactor(coderd): stop storing chat gateway key IDs and drop the columns (#27171)
> Mux is working on behalf of Mike.

## Summary

Stop reading and writing the legacy `api_key_id` columns on chat
messages and queued messages, and drop the columns in the same PR.
Runtime AI Gateway attribution continues to use the per-user synthetic
key introduced by #27170.

With the columns gone, `sqlc` generates `database.ChatMessage` and
`database.ChatQueuedMessage` without `api_key_id`, so no transitional
query scaffolding is needed.

Migration `000548` drops the `api_key_id` columns. #27170 already
removed their foreign keys, so the down migration re-adds nullable text
columns without constraints. Previous column values cannot be restored.

Also moves the model config validation in `CreateChat` above the
message-building work so a disabled or invalid model fails fast. On main
this mattered more: the old ordering minted a synthetic API key before
rejecting the request.

Deploy note: replicas still running the previous release write
`api_key_id` on insert, so chat message inserts on old replicas fail
during the rolling window after the column drop. This was previously
split across two PRs to avoid that window; per review feedback the split
added more churn than it was worth for an experimental surface.

Depends on #27170 (merged).
2026-07-20 19:49:19 +02:00
Michael Suchacz f18c664be2 fix(site): stack settings layouts on mobile (#27334)
## Problem

On mobile viewports every settings shell renders a fixed 240px sidebar
next to the content in a non-responsive flex row, leaving the content
almost no width. The MCP Servers page is worst: its fixed-layout table
cannot shrink, so the whole page collapses into a single cramped column.

## Changes

- `Sidebar` component: full width below the `lg` breakpoint, `w-60` at
`lg`+.
- Six settings layouts (AI, Deployment, Organization, User, Workspace,
Template) stack the nav above the content below `lg` and keep the
previous side-by-side spacing at `lg`+. Content wrappers get `min-w-0`
so flex children cannot force overflow, and horizontal padding tightens
on small screens.
- MCP servers table gets `min-w-[640px]` so the existing `overflow-auto`
wrapper provides horizontal scrolling instead of colliding column
headers.

Tailwind class changes only; no component or behavior changes.

## Testing

- `pnpm check` and `pnpm run lint:types` pass.
- Dogfood UAT on a dev deployment: at 390x844 the MCP Servers,
Deployment, Account, and Template settings pages stack nav-above-content
with no horizontal body overflow and a scrollable MCP table; boundary
verified stacked at 1023px and side-by-side at 1024px; at 1440x900 the
layouts are pixel-identical to before (240px sidebar, 112px gap, 40px
padding).

Closes CODAGT-828.

> Created by Mux, an AI agent, on Mike's behalf.
2026-07-20 19:35:23 +02:00
Sas Swart 66e6f40b8b chore: rename agent firewall flags (#27231)
* Alias --boundary-log-proxy-socket-path to
--agent-firewall-log-proxy-socket-path
* Also alias CODER_AGENT_BOUNDARY_LOG_PROXY_SOCKET_PATH to
CODER_AGENT_FIREWALL_LOG_PROXY_SOCKET_PATH
* Also Rename related variables and symbols to reflect the new name.

<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->
2026-07-20 15:39:21 +02:00
Susana Ferreira a9fdf87a2f feat: add GET /groups/{group}/members/ai/spend (#27130)
## Description

Adds `GET /api/v2/groups/{group}/members/ai/spend?user_ids=...` (also available org-scoped at `/api/v2/organizations/{org}/groups/{groupName}/members/ai/spend`) to return per-member AI spend attributed to a group, along with each member's effective budget group and the applied spend limit when the queried group is their effective budget source.

In the UI, this endpoint is used alongside the existing `/api/v2/groups/{group}/members` endpoint. AI spend data is kept separate from that endpoint so that:

- Different concepts stay on different endpoints: identity (group members) vs. cost control (spend). Cost control is an additional feature layered on top of groups/orgs.
- Callers that don't need spend information don't pay for its computation.

UI flow:

1. Request `/api/v2/groups/{group}/members` → returns the group's members.
2. Request `/api/v2/groups/{group}/members/ai/spend?user_ids=...` with the IDs from step 1.

**Note:** Only current members of the queried group are returned. `spend_limit_micros` and `limit_source` are populated only when the queried group is the member's effective budget source (its own limit or a user override). `effective_group_id` is null when the member's budget resolves to a group in another organization, since an organization is treated as a tenant boundary.

<img width="2880" height="1904" alt="image" src="https://github.com/user-attachments/assets/33ed395d-d1a3-4b46-bb04-c8d3f41c8886" />

## Changes

- Add `codersdk.GroupMembersAISpend` and `GroupMemberAISpend` types, reusing the shared `AISpendPeriodWindow`.
- Add `GetGroupMembersAISpend` SQL query with a dbauthz per-row filter that mirrors `GET /api/v2/groups/{group}/members`.
- Add handler and routes under `/groups/{group}/members/ai/spend` (and the org-scoped alias) with a required `user_ids` query param (cap 100). Callers with more than 100 members are expected to batch across multiple requests.
- Add codersdk client method.
- Tests: dbauthz, raw SQL, endpoint, and role-access.

Closes https://linear.app/codercom/issue/AIGOV-471/backend-group-members-endpoint-with-members-spend

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-07-20 13:04:37 +01:00
Susana Ferreira 2adc8f5272 feat: add GET /organizations/{org}/groups/ai/spend (#27123)
## Description

Adds `GET /api/v2/organizations/{org}/groups/ai/spend?group_ids=...` to return per-group AI spend and configured limits for a set of groups in an organization.

In the UI, this endpoint is used alongside the existing `/api/v2/organizations/{org}/groups` endpoint. AI spend data is kept separate from that endpoint so that:

- Different concepts stay on different endpoints: identity (groups) vs. cost control (spend). Cost control is an additional feature layered on top of groups/orgs.
- Callers that don't need spend information don't pay for its computation.

UI flow:

1. Request `/api/v2/organizations/{org}/groups` → returns the organization's groups.
2. Request `/api/v2/organizations/{org}/groups/ai/spend?group_ids=...` with the IDs from step 1.

The groups endpoint from 1) is currently not paginated, but if pagination is added later, this design keeps the two responses in sync. This spend endpoint intentionally takes `group_ids` rather than paginating on its own, since it depends on the group set from step 1. Pagination could be added in the future, especially for Cost Control-focused pages.

<img width="2880" height="1460" alt="image" src="https://github.com/user-attachments/assets/ea83b74d-6a4f-45a6-af2f-1024e019da07" />

## Changes

- Add `codersdk.OrganizationGroupsAISpend` and `OrganizationGroupAISpend` types, plus a shared `AISpendPeriodWindow` embedded in the spend response.
- Add `GetOrganizationGroupsAISpend` SQL query with a dbauthz per-row filter that mirrors `GET /organizations/{org}/groups`.
- Add handler and route under `/organizations/{organization}/groups/ai/spend` with a required `group_ids` query param (cap 100). Callers with more than 100 groups are expected to batch across multiple requests.
- Add codersdk client method.
- Tests: dbauthz, raw SQL, endpoint, and role-access.

Closes https://linear.app/codercom/issue/AIGOV-466/backend-organization-groups-endpoint-with-groups-spend

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-07-20 12:54:52 +01:00
Mathias Fredriksson b511a68ab0 fix(coderd/x/chatd): clarify wait agent timeout (#27335)
The model-visible timeout schema did not state its five-minute default.
Clarify that waits return on completion and that a timeout leaves the
agent running.
2026-07-20 13:47:25 +03:00
Cian Johnston 54fa4a087e chore: wire quartz.Clock into Acquirer (#27291)
- Wires quartz.Clock into provisionerdserver.Acquirer
- Allows overriding Acquirer in coderd.Options
- Updates existing tests to use an Acquirer driven by a quartz.Mock 

Before this change `enterprise/coderd/prebuilds` package tests would
take ~60-70s to run.
After this change, it's down to ~10s.

> Generated by Coder agents, massaged by this human.
2026-07-20 10:30:02 +01:00
Michael Suchacz 9f4ddea571 feat: revoke MCP server OAuth grants at the provider on disconnect (#27300)
Closes
[CODAGT-805](https://linear.app/codercom/issue/CODAGT-805/revoke-oauth-grants-at-the-source-for-mcp-servers).

The experimental MCP server OAuth2 disconnect endpoint previously
deleted only the stored token row, leaving the grant active at the OAuth
provider. This PR adds provider-side token revocation while keeping
local disconnect independent of provider availability.

## Changes

- Add `mcp_server_configs.oauth2_revocation_url` in migration `000547`.
The value can be configured manually, discovered from RFC 8414 metadata,
and managed through the MCP server settings UI. Non-admin responses
redact it with the other OAuth2 fields.
- Revoke the refresh token first through the RFC 7009 endpoint, then
fall back to the access token only for `unsupported_token_type`. Public
clients send `client_id`; confidential clients use
`client_secret_basic`.
- Delete the local token transactionally before best-effort provider
revocation. Callers without a token receive the same response for hidden
and nonexistent config IDs, and provider failures return a generic
warning without exposing provider response bodies.
- Require HTTPS revocation endpoints except for HTTP loopback URLs.
Redirects must preserve the POST and remain on the configured origin.
Redirect errors omit provider-controlled paths and query strings so
reflected token material cannot enter logs.
- Treat `200 OK` and `204 No Content` as completed revocations. `202
Accepted` remains a failure because it does not confirm completion.
- Prevent an in-flight refresh from recreating a token deleted by
disconnect. Refresh persistence now uses an optimistic update keyed by
token ID and `updated_at`; only the OAuth callback can create a token
row. Refresh conflicts reload the current row or clear in-memory auth
when disconnect deleted it.
- Return `{token_revoked, token_revocation_error}` from disconnect,
while retaining SDK compatibility with the legacy `204` response. The UI
surfaces provider revocation failures as warning toasts.
- Document revocation endpoint discovery, HTTPS requirements, and
best-effort disconnect behavior.

No token or no configured revocation URL returns `token_revoked: false`
without an error, so disconnect remains idempotent.

> Updated by Mux, an AI coding agent, on Mike's behalf.
2026-07-20 00:14:03 +02:00
Michael Suchacz 33fcc9de68 fix(coderd/x/chatd): drop stale APIKeyID from CreateOptions test literal (#27331)
> Mux is working on behalf of Mike.

Closes coder/internal#1622 (ENG-3061).

## Problem

`main` is broken: the chatd test package fails to compile, taking down
`lint`, `test-go-pg`, `test-go-pg-17`, and `test-go-race-pg`.

This was a semantic merge conflict between two individually green PRs:

- #27170 removed `APIKeyID` from `chatd.CreateOptions` (chatd now mints
a synthetic gateway key from the chat owner).
- #27070 branched before that merge and added the
`CreateChatProviderDisabledRejected` test, which sets `APIKeyID` in a
`CreateOptions` literal. Its CI ran against the old base and passed.

Merged together: `unknown field APIKeyID in struct literal of type
CreateOptions`.

## Fix

Two lines in the test:

- Drop the stale `APIKeyID` field from the `CreateOptions` literal.
- Create the chat owner with `dbgen.User` instead of a random
`uuid.New()`. On current `main`, `CreateChat` resolves the owner's
synthetic API key before the model-config recheck, so a nonexistent
owner fails with `sql: no rows` instead of reaching the
`ErrInvalidModelConfigID` assertion.

## Validation

- `go build ./...`
- `go test ./coderd/x/chatd/...` (full package, passes)
- pre-commit hooks (lint/go, lint/ts)
2026-07-19 10:20:26 +00:00
Michael Suchacz 9b3af629cd fix: hide and reject chat models from disabled AI providers (#27070) 2026-07-19 08:33:40 +02:00
Michael Suchacz 34ed124478 fix(site): align React Compiler check scope with vite.config.mts (#27216)
## Stack Context

First PR of a 6-PR stack that thins the agent instruction corpus (~4,800
lines down to ~2,800) by removing startup bloat, assigning each
procedure one canonical owner, and fixing rules that drifted from
reality. Split from #27203 for reviewability.

## Why?

`site/vite.config.mts` compiles `src/pages/AIBridgePage/` with the React
Compiler, but `site/scripts/check-compiler.mjs` did not include that
directory. Compiler regressions in AIBridgePage were invisible to CI:
code could silently bail out of compilation with no signal. The two
lists had already drifted once, which is exactly how this class of bug
recurs.

## What?

- Add `src/pages/AIBridgePage/` to the check-compiler scope. Verified
all 381 functions in scope compile cleanly.
- Cross-reference the two lists with comments so the next person who
edits one finds the other.

This is the only behavioral (non-docs) change in the stack, which is why
it sits at the bottom.

> This PR was prepared by Mux (AI agent) on Mike's behalf.
2026-07-19 07:29:53 +02:00
Michael Suchacz 5f5efa49da fix: stop sending adaptive thinking to pre-4.6 Anthropic models (#27314)
## Problem

A chat model config with `reasoning_effort` set on a pre-4.6 Anthropic
model (for example `claude-haiku-4-5`) fails every generation with HTTP
400 `adaptive thinking is not supported on this model`, surfaced in chat
as "Anthropic returned an unexpected error." The fantasy Anthropic
provider always serialized effort as `thinking: {type: "adaptive"}` plus
`output_config.effort`, a shape only Claude 4.6+ accepts.

## Changes

- Bump the coder/fantasy pin to include coder/fantasy#47: the provider
now converts effort into `{type: "enabled", budget_tokens}` on models
older than Claude 4.6, with the budget derived from the call's
`max_tokens` (aibridge-mirroring ratios, 1024-token API floor; below the
floor thinking is omitted, which keeps small-budget calls like title
generation working). Adaptive-capable models keep the current shape, and
Opus 4.5 keeps `output_config.effort` alongside the derived budget since
it supports effort without adaptive thinking. Models older than Claude
3.7 predate extended thinking, so effort sends no thinking at all there.
`minimal` is normalized to `low`, `xhigh` falls back to `max` on
adaptive models that predate the xhigh tier (Claude 4.7+); effort `none`
disables thinking, including an explicit `thinking: {type: "disabled"}`
on Claude 5+ models that otherwise run adaptive thinking by default. The
Bedrock provider wraps the Anthropic one, so both are covered, and
Vertex-style `@date` model IDs parse correctly.
- `TestActiveServer_CompactionModelOverride` previously codified the
buggy shape (asserting `output_config.effort` sent to
`claude-3-5-haiku-latest`). The summary-routing subtest is now a
three-case table: pre-thinking override models (Claude 3.5) expect no
thinking, legacy budget-thinking ones (Haiku 4.5) expect enabled
thinking with the derived budget, adaptive-capable ones still expect
`output_config.effort`.
- New regression test `TestActiveServer_AnthropicModelReasoningEffort`:
a `claude-haiku-4-5` config with `reasoning_effort` produces enabled
thinking with the derived budget and no `output_config` on the wire, and
a `claude-sonnet-5` config with effort `none` sends an explicit thinking
disable.
- `chattest.AnthropicRequest` gains a `Thinking` field so tests can
assert the thinking config.
- One-sentence note in the chatd ARCHITECTURE reasoning-effort section.

No chatd production code changes: `ApplyReasoningEffort` keeps setting
`Effort`, which is now valid for every Anthropic model.

## Validation

- `go test ./coderd/x/chatd/...` passes (19 packages).
- Fork PR validated separately: full fantasy test suite plus new
provider unit tests (version gating incl. Vertex/Bedrock IDs, budget
derivation, floor behavior, normalization, effort `none` incl. Claude 5+
disable, Opus 4.5 effort preservation, sampling-param stripping),
golangci-lint clean.

Closes
[CODAGT-812](https://linear.app/codercom/issue/CODAGT-812/reasoning-effort-on-pre-46-anthropic-models-fails-generations-with).

> This PR was authored by Mux, an AI coding agent, acting on Mike's
behalf.
2026-07-18 22:47:02 +02:00
Michael Suchacz 1ea61b976b fix(site): prevent slash menu from flashing at top-left corner when closed (#27326)
Typing `/` in the agent chat input opens the skills slash menu. Pressing
Backspace to erase the `/` made the menu flash at the top-left corner of
the app for a split second before disappearing.

Radix keeps the popover content mounted through its exit animation, but
the caret-positioned `PopoverAnchor` was unmounted in the same render
that closed the menu. Without an anchor, the popper repositioned the
still-visible closing content to the viewport origin. The anchor now
stays rendered at the last known caret rect, so the menu holds its
position while it animates out.

Verified with a frame-by-frame position recorder in the browser: before
the fix the closing menu jumped from the caret position to `(0, 4)`;
after the fix it stays in place until unmount. Added a
`BackspaceClosesMenuWithoutRepositioning` story that fails without the
fix.

> This PR was created by Mux, an AI coding agent, on Mike's behalf.
2026-07-18 22:43:34 +02:00
Michael Suchacz 46d1823c0a feat: add workspace skills to agent chat slash menu (#25600)
> This Pull Request was updated by Mux working on behalf of Mike.

Adds workspace skills to the agent chat slash menu, sourced entirely
from the chat's pinned context resources (the single-chat GET response
the page already fetches), the same inventory `read_skill` resolves
from. No new API endpoint is introduced.

Personal entries insert `/name`, or `/personal/name` when the name
collides with a workspace skill or the chat's pinned context has not
resolved yet; workspace entries insert `/workspace/name`. Qualified
aliases stay searchable even when the displayed trigger is bare. Before
a chat binds a workspace (new chat form, or a selected but unbound
workspace), the menu lists personal skills only.

Sending a message invalidates the chat detail query, and chatd
broadcasts a context watch event when a first-turn bind pins the chat,
so the menu picks up newly pinned context without a reload.

Makes `UpdateChatWorkspaceBinding` a no-op when the requested
workspace/build/agent binding is unchanged, preserving `updated_at` so
chat list ordering and watch events stay stable.

Includes regression coverage for the no-op binding guard, pinned-context
skill mapping, collision qualification, and skills menu behavior.

Refs
[CODAGT-474](https://linear.app/codercom/issue/CODAGT-474/ux-improvements-for-coder-agents)
(skills autocompleting in the editor).
2026-07-18 21:52:02 +02:00
Michael Suchacz 997b5d0843 feat: add synthetic gateway keys (#27170)
> Mux is working on behalf of Mike.

## Summary

Add a per-user synthetic API key for chatd AI Gateway attribution. Chatd
resolves the key from the chat owner, extends it before expiry, and
discards the generated bearer token so the key is never a usable
credential.

There is no mapping table. The key is resolved from `api_keys` by a
deterministic token name (`chatd_<owner_id>_session_token`), mirroring
the provisionerd session token model, with three deltas that chatd
needs:

- **Login type guard**: token names are unvalidated user input, so a
user can create a bearer token with the colliding name. The lookup
excludes `login_type = 'token'` rows, so chatd never picks up (or
extends) a real user token. Synthetic keys are minted with the owner's
login type, which is never `token`.
- **In-place expiry extension instead of delete-and-reinsert**: chat
generations have no stop boundary, and an in-flight generation may have
already delegated the current key ID to aibridged. Extending
`expires_at` keeps the key ID stable forever.
- **Advisory-lock mint**: the unique index on token names is partial
(`WHERE login_type = 'token'`), so nothing DB-enforces uniqueness for
synthetic keys. A per-user advisory lock serializes concurrent mints.

Keys carry a minimal scope (`api_key:read`) as defense in depth; the
delegated gateway path never evaluates scopes and the secret is
discarded at mint.

Migration 000544 removes the foreign keys from the legacy message and
queue `api_key_id` columns while chatd continues stamping them for
rolling compatibility. Stale IDs are tolerated because routing uses
`chats.owner_id`. Individual key deletion, delete-all, and password
reset remove the key without changing chat history or queue versions,
and the next lookup remints it. Suspension does not delete the key;
delegated gateway authorization rejects inactive users at request time.

This is the first PR in a three-PR rollout and must be fully deployed
before #27171.

Refs
https://linear.app/codercom/issue/CODAGT-561/maintain-synthetic-api-key-per-user-per-chat
2026-07-18 20:45:13 +02:00
Nick Vigilante 4d4d2575e4 fix: exempt docs/.style/ prose from Vale's own Coder rules (#27192)
## Problem

The repo-root `.vale.ini` lints all of `docs/**/*.md`, including the
style guide under `docs/.style/style-guide/`. The guide deliberately
contains the constructs the Coder rules ban:

- Don't examples in blockquotes and in the Don't column of Do/Don't
tables.
- Banned terms named in prose and headings (a rule about "Next steps"
must write "Next steps").

`Coder.BrandNames` already fired on the Brand names table's Don't column
(`Hashicorp`, `HASHICORP`), and each future `Coder.*` rule would fire on
its matching section's examples. Vale runs advisory, so these surface as
non-blocking annotations, exactly the standing backlog the README warns
against, and they break the documented "zero baseline findings"
doctrine.

## Change

Option B, narrowed after review to the style-guide subtree:

- `.vale.ini`: clear `BasedOnStyles` for `docs/.style/style-guide/**`
(the guide subpages only). The annotation demo and the rest of
`docs/.style/` stay linted; the demo keeps firing its `Coder.Demo*`
rules by inheriting `Coder` from `[*.md]`, with no re-include. Also
corrects the `error`-tier doctrine line to reflect advisory-only Vale.
- `docs/.style/README.md`: "What still runs" / "What does not run"
describe the narrowed exemption, and record that it holds only for paths
that resolve to `docs/.style/style-guide/...` (repo-root-relative), not
absolute or subdirectory-relative invocations.
- `docs/.style/style-guide/README.md`: exemption note scoped to
`docs/.style/style-guide/**`.
- `docs/.style/styles/Coder/BrandNames.yml`,
`docs/.style/styles/Coder/README.md`: fix the remaining dead
`style-guide.md` links (the `BrandNames.yml` one was a live 404 surfaced
in Vale annotations).

## Validation

- `make lint/prose` reports only the 3 intended `Coder.Demo*` findings
across the corpus; the guide's `BrandNames` findings are gone.
- `content-guidelines.md`, the landing `README.md`, and
`styles/Coder/README.md` are now linted and clean (0). Injecting a
miscased `Hashicorp` into `content-guidelines.md` fires
`Coder.BrandNames`; reverted.
- The guide subpages stay exempt (0); the annotation demo still fires
its 3 findings via `[*.md]`.
- Invocation-path behavior verified against
`docs/.style/style-guide/word-choice.md`: repo-root-relative `docs/...`
is exempt (0), while `docs/`-relative and absolute-path invocations
still fire 2 `Coder.BrandNames` errors.
- `markdownlint-cli2` clean on the changed READMEs.

## Decision log

Considered three options from the issue:

- **A. Surgical in-file suppression** (`vale off`/`vale on` comment
blocks, backticking banned terms). Rejected as primary: noisy in source,
repeated per example, bare-term headings still fire, and every new rule
can re-break the guide. It is path-independent, so it would have covered
the editor case noted in Option B's limitation.
- **B. Config-level subtree exemption** (chosen; narrowed to the guide
subtree after round-2 review). One place, zero source noise,
future-proof for the guide subpages.
- **Scope.** The clear applies to `docs/.style/style-guide/**` only.
Round-2 review (three reviewers converged, verified end-to-end) showed
the original directory-wide clear over-reached: `content-guidelines.md`
and the landing `README.md` are ordinary contributor prose that lints
clean today (`content-guidelines.md` uses `HashiCorp` correctly), so
they should stay linted. Narrowing to the guide subtree preserves the
exact 3-finding baseline, relints those two pages, removes the
last-match-wins ordering hazard, and drops the whole-package demo
re-include. The demo sits at the `.style/` root and keeps firing via
`[*.md]`.
- **Tradeoff.** The guide's own prose under `style-guide/` is no longer
auto-linted by Vale. Acceptable because the guide must contain banned
terms by design, one-sentence-per-line is enforced by markdownlint, and
human review covers the rest.
- **Limitation.** The exemption holds only for invocations whose path
resolves to `docs/.style/style-guide/...` (repo-root-relative
`docs/...`, what `make lint/prose` and CI pass). Absolute paths
(editors/LSP) and subdirectory-relative paths still flag the guide.
Recorded in `docs/.style/README.md`.
- **C. Restructure examples into fenced code blocks.** Rejected: changes
the guide's rendered format and doesn't cover Do/Don't tables or
headings.

## Notes

- `.vale.ini` is outside `docs/`, so this PR modifies repo-wide lint
config; the clear is scoped to `docs/.style/style-guide/` only.
- Linear: DOCS-543.

---
Opened via Coder Agents on behalf of @nickvigilante.
2026-07-18 13:41:27 -04:00
Michael Suchacz 36e36e2048 fix(site): wrap workspace topbar controls on narrow viewports (#27313)
On mobile-width viewports the workspace page grew to ~1080px wide (390px
viewport), pushing the schedule controls, status indicator, and action
buttons off-screen. Users had to zoom out or scroll horizontally to
reach Stop/Restart/Favorite/Share.

The topbar header and the right-side controls group used non-wrapping
flex rows, and every child is a `whitespace-nowrap` button, so the row's
minimum width (~725px for the controls alone) forced the document wider
than the viewport.

## Changes

- `WorkspaceTopbar`: allow the topbar header and the right controls
group to wrap; right controls stay right-aligned when they wrap onto
their own row.
- `WorkspaceActions`: allow the button row to wrap.
- `TopbarData`: merge a caller-provided `className` (no existing caller
passed one); the workspace breadcrumbs use it to wrap on very narrow
screens.

## Verification

Compared before/after with agent-browser on Storybook stories
(`Workspace: Running`, `WorkspaceTopbar: Outdated / WithQuotaWithOrgs /
Dormant / ConnectedWithMaxDeadline`):

| Viewport | Before `scrollWidth` | After `scrollWidth` |
|---|---|---|
| 320 | 1080 (overflow) | 305 (fits) |
| 390 | 1080 (overflow) | 375 (fits) |
| 768 | 1080 (overflow) | 753 (fits) |
| 1024 | 1080 (overflow) | 1009 (fits) |
| 1440 | 1425 (fits) | 1425, pixel-identical (0% diff) |

At widths >= 1280 the layout is unchanged (0% pixel diff at 1440 across
the stories above). Between ~1080-1230px the controls now wrap onto a
second right-aligned row instead of squeezing label text onto two lines
inside a single row.

Validation: `biome check`, `tsc --noEmit`, and `pnpm test:storybook` for
`Workspace.stories.tsx` + `WorkspaceTopbar.stories.tsx` (36 passed).

> This PR was prepared by Mux, an AI coding agent, on Mike's behalf.
2026-07-17 18:12:25 +02:00
Michael Suchacz 1ac106255b feat: add Anthropic 1M context window toggle for Agents model configs (#27257) 2026-07-17 13:04:13 +02:00
Asher 2ac2295b1e fix: do not send or use stale init dynamic parameter state (#27283)
In summary, we use the init message if we have no autofill params. If we
do, then we ignore the init message, send another message with the
autofilled values, and then when we get *that* response, finally we
render the form since we know we have good state. This eliminates the
possibility of temporarily rendering with stale state.

This is the same fix that was applied to the edit page, but on the
create page this time. The only difference is that the create page does
not need to wait on a build parameters query, instead it has to wait on
the first message from the socket (to get defaults).

This also makes one change where we would send the defaults in the init
message. The server already knows the defaults so there is no need to
send them. The advantage here is that we no longer need to wait for the
first message, and it also fixes an issue where fields with blank values
were getting validation errors because they were not filled out, before
the user had a chance to actually fill them out.
2026-07-16 12:55:43 -08:00
Yevhenii Shcherbina 1453b4b1fc docs: document Bedrock mantle protocol (#27296)
Implements:
https://linear.app/codercom/issue/AIGOV-518/add-docs-for-bedrock-mantle
Follow-up to: https://github.com/coder/coder/pull/26745
2026-07-16 14:58:09 -04:00
Michael Suchacz 3dd9265fa6 feat: add UI option to disconnect OAuth2 MCP credentials (#27299)
Closes
[CODAGT-804](https://linear.app/codercom/issue/CODAGT-804/add-ui-option-to-revoke-oauth-mcp-credentials).

Users could authenticate with an OAuth2 MCP server from the chat input,
but there was no UI to disconnect those per-user credentials. The
backend endpoint (`DELETE
/api/experimental/mcp/servers/{id}/oauth2/disconnect`) already existed.

## Changes

- Connected OAuth2 MCP rows in the chat input plus menu now show a
disconnect icon button next to the enable switch. It opens a
confirmation dialog; confirming calls the disconnect endpoint, shows a
toast, and refetches MCP configs so the row reverts to the `Auth` button
without a reload.
- New `disconnectMCPServerOAuth2` API client method and react-query
mutation that invalidates `mcp-server-configs`.
- Storybook interaction tests: control visibility per auth state, cancel
makes no API call, confirm calls the endpoint once, failed disconnect
keeps the dialog open.
- Hardened `TestMCPServerConfigsOAuth2Disconnect`: seeded tokens flip
`auth_connected`, disconnect only removes the calling user's token, and
repeat disconnect stays idempotent.

The endpoint removes the token stored in Coder; it does not revoke the
upstream OAuth grant, so the UI copy says "disconnect" rather than
"revoke".

Validated with the targeted Go test, Storybook tests (51 passed), tsc,
biome, the react-compiler check, and a manual dogfood run (seeded token,
disconnect/cancel/reconnect flows verified in the UI).

> This PR was authored by Mux, an AI coding agent, on Mike's behalf.
2026-07-16 18:26:35 +02:00
Susana Ferreira 101aee8ee0 refactor: use Options struct in aibridgedserver.NewServer (#27200)
Refactor `aibridgedserver.NewServer` to take an `Options` struct instead
of a long list of positional arguments. Follow-up to review feedback in
https://github.com/coder/coder/pull/27117#discussion_r3571535760
2026-07-16 16:09:25 +01:00
Nick Vigilante 77582be805 fix: close <b> tag in generated audit log table header (#27293)
## What

The audit log resource table header in
`docs/admin/security/audit-logs.md` was
emitted as `<b>Resource<b>`: a second opening `<b>` instead of a closing
`</b>`.
Because the bold element never closes, Markdown/HTML renderers can bold
content
well beyond the header cell.

The page is generated (`<!-- Code generated by 'make
docs/admin/security/audit-logs.md'. DO NOT EDIT -->`),
so the fix belongs in the generator, `scripts/auditdocgen/main.go`, with
the
doc regenerated from it.

## Changes

- `scripts/auditdocgen/main.go`: emit a closing `</b>` instead of a
second `<b>` in the table header row.
- `docs/admin/security/audit-logs.md`: regenerated with `make
docs/admin/security/audit-logs.md`; only the header cell changes.

## Verification

<details>
<summary>Regenerated doc and local checks</summary>

Header cell before (unclosed tag):

```text
| <b>Resource<b>                                   | ...
```

Header cell after (balanced tag):

```text
| <b>Resource</b>                                  | ...
```

- `make docs/admin/security/audit-logs.md` regenerates the page from the
fixed generator and changes only the header cell (single line; the table
stays aligned).
- Local `make pre-commit` passed with `GEN_SKIP_GOLDEN=1` (this
workspace has no Docker daemon for the golden-file gen step, which this
change does not touch): `gen`, `fmt`, `lint/go`, `lint/ts`,
`lint/markdown`, `lint/typos`, `lint/emdash`, and the slim binary build
all green.

</details>

## Linear

DOCS-580:
https://linear.app/codercom/issue/DOCS-580/fix-unclosed-b-tag-in-generated-audit-logs-table-header

---

This PR was created using AI (Coder Agents) on behalf of @nickvigilante,
who is accountable for its contents. See the [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING).
2026-07-16 14:56:55 +00:00
Cian Johnston f7481c5d08 feat: Add full text search over chat messages (#27126)
Closes CODAGT-721
Closes CODAGT-722
Closes CODAGT-723
Closes CODAGT-724
Closes CODAGT-725

This PR adds the database and API pieces necessary to support full-text
chat message search.

- Adds required chat schema for full-text search
- Adds dbpurge job to populate search_tsv in the background
- Adds `search` parameter to GetChats query
- Adds `search` filter to `searchquery.Chats`
- Wires chat search filter into chats API

> Implemented by Coder Agents, reviewed and tested by a human.
2026-07-16 15:21:57 +01:00
Yevhenii ShcherbinaandJake Howell 9862f10484 feat(site): add Bedrock mantle protocol selector to provider form (#27156)
Implements:
https://linear.app/codercom/issue/AIGOV-517/add-ui-for-bedrock-mantle

Follow-up to https://github.com/coder/coder/pull/26745, which added AWS
Bedrock **mantle** support to the backend and modeled it as a `protocol`
field on the Bedrock provider settings.
## What changed

- Adds a **Protocol** selector to the Bedrock provider form: InvokeModel
(default) or Mantle.
- The form is now protocol-aware:
- **Model** / **Small-fast model** fields are shown only for
InvokeModel. Mantle is a passthrough (the client sends the model at
request time), so the fields are hidden and omitted from the saved
settings.
- **Endpoint** validation, placeholder, and hint switch per protocol.
Mantle requires a `https://bedrock-mantle.{region}.api.aws/anthropic`
URL; InvokeModel keeps the
`https://bedrock-runtime.{region}.amazonaws.com` shape. The `/anthropic`
suffix is required for mantle because the SDK appends `/v1/messages` to
the base URL.

## Manual Testing

Tested the following scenarios:

1. Creating a new Mantle provider — works.
2. Creating a new InvokeModel provider — works.
3. Verifying that an existing InvokeModel provider continues to work.
4. Upgrading an existing InvokeModel provider to Mantle — works.

## Screenshots

### InvokeModel

<img width="1085" height="474" alt="image"
src="https://github.com/user-attachments/assets/4c36b9b0-0eb8-4b17-80b7-e2112325f8d1"
/>


### Mantle

<img width="1082" height="357" alt="image"
src="https://github.com/user-attachments/assets/e8caef26-83d1-4b7e-8f96-79079949e8f1"
/>

---------

Co-authored-by: Jake Howell <jake@hwll.me>
2026-07-16 09:37:48 -04:00
Jeremy Ruppel b3ff4baeb9 fix: smooth compose loader to files page transition (#27277)
## Summary

During the template builder compose flow, the transition into the
template
files page briefly flashed the wizard form again before the files page
settled.

Root cause: the loader was gated on `createMutation.isPending`. When the
compose
POST resolved, `isPending` flipped to `false` in the same commit that
`onSuccess` navigated to the files page, so `TemplateBuilderPageView`
repainted
the wizard form for a frame before the route change committed and
unmounted it.

Fix: keep the loader mounted while the mutation is pending **or**
succeeded
(`createMutation.isPending || createMutation.isSuccess`). Since
`onSuccess`
always navigates away, the loader stays until the component unmounts, so
the
form never reflashes. The error path is unaffected (`isSuccess` stays
false).

Resolves DEVEX-561.


https://github.com/user-attachments/assets/6d5ec04e-9f97-4864-bd18-e1e75055f079

## Scope

Targets the wizard form reflash only. Two adjacent items were identified
during
investigation and intentionally left out:

- The destination files page briefly shows its own `<Loader />` while it
fetches
template files. Smoothing that requires prefetching before navigation
and is a
  larger change.
- The `justCreated` "Awesome, you just created a template!" alert is
cleared by a
mount effect, so it renders one frame then disappears. Arguably its own
bug.

Happy to follow up on either if wanted.

## Testing

- Biome clean on the changed file.
- Manual: build a template through the wizard and confirm the loader
holds
  straight through to the files page with no form flash.

## Stack

Stacked on top of #27276 (DEVEX-593).

---

Generated by Coder Agents.
2026-07-16 09:15:11 -04:00
Jeremy Ruppel 3ddf7d3baa fix: stop the template builder build progress bar from looping (#27276)
## Summary

The template builder's "Building your template" loader had a progress
bar that
animated 0→100% every 5s with an infinite repeat, so it visibly
restarted over
and over while a template built. It looked broken and was frustrating to
watch.

This replaces the looping fill with a single ease-out fill that
decelerates
toward 90% and holds until the request resolves and the loader unmounts.

Since the loader is intentionally indeterminate and no progress is
streamed to
the browser, this also removes the now-dead `onUpdate` callback plumbing
from
the backend `waitForProvisionerJob` (its only caller passed `nil`).

Resolves DEVEX-593.


https://github.com/user-attachments/assets/6d5ec04e-9f97-4864-bd18-e1e75055f079

## Commits

- `refactor(coderd): drop unused onUpdate callback from
waitForProvisionerJob`
- `fix(site/src/pages/TemplateBuilder): stop build progress bar from
looping`

## Testing

- `go build ./coderd/` passes with the reduced `waitForProvisionerJob`
signature.
- Biome clean on the changed frontend file.
- Storybook: `pages/TemplateBuilder/BuildingTemplateLoader` shows the
bar fill
  once and hold, with no restart.

<details>
<summary>Implementation plan</summary>

# DEVEX-593: Stop the build progress bar from looping repeatedly

## Problem

While the template builder composes and imports a template, the FE shows
`BuildingTemplateLoader`. Its progress bar animates from 0% to 100% over
5s
with `repeat: Number.POSITIVE_INFINITY`, so it visibly restarts over and
over.
Users report this looks broken and is frustrating to watch while
waiting.

## Decision (scope)

Minimal fix only: **stop the loop**, plus remove the now-dead `onUpdate`
plumbing from the backend. Since the UI is intentionally indeterminate
and no
progress signal is streamed, the callback serves no purpose and should
be
deleted rather than left as dead code.

### Why not "real sync" now

- `POST /api/v2/templatebuilder/compose/template` is a single blocking
request.
  It composes, bundles, inserts the provisioner job, then calls
`waitForProvisionerJob(jobCtx, provisionerJob.ID, nil)` and only
responds once
  the job completes.
- The `onUpdate` callback runs server-side only. Nothing is streamed to
the
  browser during the wait, so the FE has no progress signal to bind to.
- A provisioner job exposes no numeric percentage. Only status
transitions
  (`pending -> running -> succeeded`) and coarse log stages
(`init/plan/graph/apply`) exist. Real sync would require converting the
endpoint to a streaming protocol (SSE/WebSocket) plus FE rework, which
is
  disproportionate for this 1-point ticket.

### Keep polling (do not switch to pubsub-block)

The wait could technically block instead of poll: on completion
`CompleteJob`
publishes `ProvisionerJobLogsNotifyMessage{EndOfLogs: true}` on the job
logs
notify channel, so we could subscribe and wait for that message with the
context timeout as a fallback. We deliberately do not do that here:
correctness
would require subscribe-before-completion plus an initial DB completion
check to
avoid a race, and Postgres LISTEN/NOTIFY is at-most-once (can drop under
load),
so a poll fallback would still be needed. The existing backoff poll
(100ms -> 200ms -> 500ms -> 1s) is simple and robust for a short-lived
synchronous request.

## Approach

Replace the looping fill with a single, non-repeating ease-out fill that
decelerates and approaches (but never reaches) ~90%, holding there until
the
request resolves and the loader unmounts. This reads as continuous
forward
progress for an unknown-duration operation and never restarts. The
floating-icon
animation is intentional ambient motion and is not in scope.

## Out of scope

- Any behavioral change to how the endpoint waits (it still blocks on
the job).
- Streaming real job progress to the browser.
- Changes to the floating-icon animation.

</details>

---

Generated by Coder Agents.
2026-07-16 09:14:07 -04:00
TJandCoder Agents 529b2ead78 feat(site/src/pages/AgentsPage): show "Archived chats" sidebar heading when viewing archived chats (#26926)
In the agents sidebar, show "Archived chats" instead of "Chats" when the
archive filter is set to `archived`. The heading reads the existing
`sidebarFilters.archiveStatus` state, the same condition already used
for the archived empty-state message.

---

_This PR was opened by [Coder Agents](https://coder.com/) on behalf of
@tracyjohnsonux._

---------

Co-authored-by: Coder Agents <noreply@coder.com>
2026-07-16 06:04:52 -07:00
Michael Suchacz e489092154 feat: handle revoked OAuth grants for MCP servers gracefully (#27264)
Closes
[CODAGT-792](https://linear.app/codercom/issue/CODAGT-792/handle-revoked-oauth-grants-for-mcp-servers-gracefully).

When a user revokes an upstream OAuth grant for an MCP server used by
Coder Agents, Coder kept treating the cached token as valid:
`invalid_grant` refresh failures were logged and swallowed, the dead
bearer token kept being attached, the list endpoints re-attempted the
refresh on every call, and the UI kept showing the server as
authenticated.

## Changes

Backend, mirroring the `external_auth_links` prior art:

- New migration adds
`mcp_server_user_tokens.oauth_refresh_failure_reason`.
`UpsertMCPServerUserToken` clears it, so completing the OAuth flow again
recovers the row.
- New `MarkMCPServerUserTokenRefreshFailure` query records the failure
and clears all token material, guarded by an `updated_at` optimistic
lock so a stale failure never clobbers a concurrently refreshed token
(on a lock miss the winner's row is used).
- `mcpclient.IsPermanentRefreshError` classifies `*oauth2.RetrieveError`
codes: only `invalid_grant` and `bad_refresh_token` are permanent.
Client/config errors (`invalid_client`, `unauthorized_client`, ...) stay
transient for the user row since reconnecting cannot fix them.
- chatd token refresh and the MCP list/get endpoints persist permanent
failures, return cleared tokens for the in-flight request, and skip
provider calls for already-failed rows.
- `buildAuthHeaders` no longer attaches an Authorization header for
failed tokens, so chat degrades by omitting that server's tools instead
of sending a dead bearer.

API and UI:

- No new API surface. A permanently failed token simply reports
`auth_connected: false`, so the existing "Auth" button and "Not
authenticated" tooltip appear and the user re-runs the same OAuth flow
to recover. An earlier revision added an `auth_status` enum (`connected`
/ `not_connected` / `reconnect_required`) with a dedicated "Reconnect"
button; it was collapsed to keep the API minimal since both states lead
to the identical re-auth action.

Out of scope (follow-up): typed 401-on-connect detection and forced
refresh. mcp-go exposes no stable typed 401 signal in the static-header
path, so a revocation while the access token still looks valid locally
stays undetected until expiry triggers a refresh.

## Testing

- Unit and integration tests: classifier, chatd refresh paths
(permanent/transient/race/persist-failure), API endpoints (revoked,
transient, no-retry caching, re-auth recovery, stale-lock), dbauthz,
dbcrypt, migrations.
- Dogfood UAT against a dev instance with a mock IdP returning
`invalid_grant`: revoked grant detected on refresh and persisted once
(no repeated IdP calls), chat with the revoked server selected completes
with the server's tools omitted, and re-auth restores the connected
state.

> This PR was authored by Mux, working on Mike's behalf.
2026-07-16 11:43:05 +00:00
Danielle Maywood 213f5ce606 fix(site): redesign provider tri-state controls (#27288) 2026-07-16 12:12:38 +01:00
Danielle Maywood 457fa5afa3 fix(site): move thinking settings to provider configuration (#27287) 2026-07-16 12:12:24 +01:00
Danielle Maywood 9d1e881093 refactor(site/src/pages/AgentsPage): use model selector for personal overrides (#27229) 2026-07-16 11:22:48 +01:00
Ehab Younes 35ade9e3d2 feat: collect workspace logs in support bundles (#26694)
Add workspace-side file collection to `coder support bundle` via
repeatable --workspace-file flags. The agent resolves the requested
paths or globs inside the remote workspace and streams back a tar with
a manifest and the collected files; nothing is read from the machine
running the command.

- Add POST /api/v0/bundle-files to the agent's agentfiles package.
- Expand env vars in the agent's environment; paths must then be
  absolute or start with ~/ (the agent user's home directory).
- Support ** globs and tail oversized files.
- Record requested patterns, per-path errors, truncation, and the
  applied limits in a manifest.
- Unpack the archive into the bundle under agent/workspace_files/,
  recording dropped entries in collection_errors.txt.
- Write a manifest-only archive marking collection as unsupported for
  agents that predate the endpoint.
- Bound collection: 64 KB request body, 10000 files, 10 MiB per file,
  100 MiB total including archive overhead, 110 MiB client-side read
  cap, 5 minute timeout.

Closes #26020
2026-07-16 13:00:32 +03:00
Mathias Fredriksson f997afa220 feat(coderd/x/chatd/chatloop): retain user constraints in compaction summaries (#27230)
Compaction summaries drop or soften user-stated constraints,
corrections, and prohibitions, so post-compaction assistants repeat
behavior the user already corrected. Add a summary prompt bullet that
instructs the summarizer to quote them, treat them as standing until
revoked, and attribute rules to their true source instead of
defaulting to the user.

Validated offline on unseen human chats: holdout P1 delta +0.175
(arbitrated), 13/18 cases improve. This improves per-compaction
retention only; it does not address deep-chain correction loss.
2026-07-16 09:18:43 +00:00
Spike Curtis fa4c7c5700 chore: fix replicasync to function for NATS even if no DERP relay address is set (#27235)
<!--

If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting.

-->

Fixes `replicasync` so that it keeps peers even if they don't set a RelayAddress. This allows NATS to function even if you are not running a DERP relay on the primay Coderd instances.

Also renames some replicasync functions to make it clear they are for DERP.
2026-07-16 09:42:23 +02:00
Ethan 21d08241e9 fix(coderd/x/chatd): recover timed out agents (#27254)
Closes CODAGT-802

Coder Agents only escalated failed workspace dials when the agent had
connected and later disconnected. An agent that never connected and had
already exceeded its `connection_timeout` stayed on the soft retry error
indefinitely, so a chat could keep attempting tools against an unhealthy
workspace.

To fix, we'll classify the latest agent after a failed dial and return
stop/start recovery guidance when its status is `timeout`. Agents still
connecting, including templates with `connection_timeout = 0`, keep the
existing retryable behaviour.

## Before

<img width="843" height="229" alt="image"
src="https://github.com/user-attachments/assets/d659a376-c8d4-4983-b7d7-d1a699770dfb"
/>


## After

<img width="848" height="250" alt="image"
src="https://github.com/user-attachments/assets/26b88f72-f67c-4d9e-87b1-51d701b7352f"
/>
2026-07-16 12:52:41 +10:00
Bobby Ho de716f89dc fix: normalize path before rate-limit bucket keying (#27273)
Coder's rate limiter keyed its bucket on the raw, un-normalized request
path (`httprate.KeyByEndpoint` reads `r.URL.Path` directly). The
router's `singleSlashMW` already collapses redundant slashes so a
request like `/api/v2/users//validate-password` reaches the same handler
as the canonical path, but it never touched `r.URL.Path`, so the rate
limiter saw a different key and let a client bypass a limit it had
already hit just by respelling the URL.

`keyByNormalizedEndpoint` replaces `KeyByEndpoint` and runs `path.Clean`
on `r.URL.Path` before using it as the key, so equivalent paths share
one bucket. Includes a unit test at the key-function level and an
integration test (`TestRateLimitPathNormalization`) that reproduces the
bypass against a real server.

Fixes CDM-02-003 (Cure53). Refs
https://github.com/coder/security-disclosures/issues/166.
2026-07-15 17:07:57 -07:00
dependabot[bot] 0fab0fa0ae chore: bump github.com/DataDog/dd-trace-go/v2 from 2.0.0 to 2.8.1 (#27282)
Bumps
[github.com/DataDog/dd-trace-go/v2](https://github.com/DataDog/dd-trace-go)
from 2.0.0 to 2.8.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/DataDog/dd-trace-go/releases">github.com/DataDog/dd-trace-go/v2's
releases</a>.</em></p>
<blockquote>
<h2>v2.8.1</h2>
<!-- raw HTML omitted -->
<h3>Application Performance Monitoring (APM)</h3>
<ul>
<li>Revert &quot;fix(ddtrace/tracer): cache trace ID hex encoding (<a
href="https://redirect.github.com/DataDog/dd-trace-go/issues/4481">#4481</a>)&quot;
by <a href="https://github.com/darccio"><code>@​darccio</code></a></li>
<li>fix(tracer): enforce baggage item and byte limits on extraction by
<a href="https://github.com/mtoffl01"><code>@​mtoffl01</code></a> in <a
href="https://redirect.github.com/DataDog/dd-trace-go/issues/4720">#4720</a></li>
<li>fix(tracer): drop dd= list-entries over 256 bytes from incoming
tracestate by <a
href="https://github.com/mtoffl01"><code>@​mtoffl01</code></a> in <a
href="https://redirect.github.com/DataDog/dd-trace-go/issues/4721">#4721</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/DataDog/dd-trace-go/compare/v2.8.0...v2.8.1">https://github.com/DataDog/dd-trace-go/compare/v2.8.0...v2.8.1</a></p>
<h2>v2.8.0</h2>
<!-- raw HTML omitted -->
<h2>Summary</h2>
<p><strong>New integrations.</strong> Two new integrations land in this
release: Azure API Management (APIM) callout processor for security (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4620">#4620</a>),
and twmb/franz-go for Kafka (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4250">#4250</a>).</p>
<p><strong>Data Streams Monitoring.</strong> All three major Kafka
integrations — confluent-kafka-go (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4470">#4470</a>),
segmentio/kafka-go (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4477">#4477</a>),
and Sarama (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4560">#4560</a>)
— now attach <code>kafka_cluster_id</code> for cluster-level visibility.
<code>TrackDataStreamsTransaction</code> also gains span tagging and
custom timestamp support (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4499">#4499</a>).</p>
<p><strong>OpenTelemetry (OTel) and OTLP.</strong> The tracer can now
export traces directly via the OpenTelemetry Protocol (OTLP), bypassing
the Datadog Agent entirely (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4600">#4600</a>,
<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4583">#4583</a>).
OTel process context v2 (OTLP proto format) is supported (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4478">#4478</a>),
and the <code>parentbased_always_on</code> sampler works in OTLP mode
(<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4567">#4567</a>).</p>
<p><strong>Large Language Model (LLM) Observability.</strong> Prompt
tracking is now available for LLMObs spans (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4608">#4608</a>).
Experiment scope propagates from APM baggage into spans automatically
(<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4651">#4651</a>).</p>
<p><strong>Profiler.</strong> An experimental goroutine leak profile is
available as opt-in (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4420">#4420</a>).
The goroutine wait profile type has been removed — this is a breaking
change for anyone using it explicitly (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4589">#4589</a>).</p>
<p><strong>HTTP and tracing.</strong> A new environment variable
<code>DD_TRACE_HTTP_URL_QUERY_STRING_ALLOWLIST</code> lets you whitelist
query string parameters to keep unredacted (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4562">#4562</a>).
A new <code>tracer.StartSpanFromPropagatedContext</code> API simplifies
span creation from propagated contexts (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4492">#4492</a>).
AWS EventBridge max payload size is bumped to 1 MB (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4458">#4458</a>).
Envoy Service Extensions integration gains Unix Domain Socket (UDS)
support (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4463">#4463</a>).</p>
<p><strong>OpenFeature.</strong> Flag evaluation metrics now emit via
OTel Metrics (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4489">#4489</a>),
with allocation key tagging (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4515">#4515</a>)
and Remote Configuration (RC) integration via <code>FFE_FLAGS</code>
subscription at tracer startup (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4495">#4495</a>).</p>
<p><strong>Bug fixes.</strong> gorm now respects
<code>DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED</code> (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4618">#4618</a>).
Redis and Valkey pipeline commands are joined with newlines, fixing
agent obfuscation (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4593">#4593</a>).
A race condition in HTTP client trace timings is resolved (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4591">#4591</a>).
AppSec block responses now include a correct <code>Content-Length</code>
header (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4496">#4496</a>),
and spurious Remote Configuration errors are silenced when RC is
disabled (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4612">#4612</a>).
<code>ContextWithSpan</code> no longer panics on nil context (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4313">#4313</a>).
The OTel bridge preserves keep/drop sampling decisions for unsampled
spans (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4631">#4631</a>).
User-provided DogStatsD addresses now correctly take priority over
defaults (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4575">#4575</a>).</p>
<p><strong>Performance.</strong> Trace ID hex encoding is cached (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4481">#4481</a>),
the span metadata map is preallocated (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4541">#4541</a>),
and locking is removed from both sampling priority access (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4546">#4546</a>)
and the internal logger (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4547">#4547</a>)
— reducing allocations and contention on hot paths.</p>
<p><strong>CI Visibility.</strong> Bazel offline cache and payload-file
modes are supported (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4503">#4503</a>).
Known test pagination is implemented for large test suites (<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4509">#4509</a>).</p>
<h2>What's Changed</h2>
<h3>Application Performance Monitoring (APM)</h3>
<ul>
<li>feat: collect service override source by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4500">DataDog/dd-trace-go#4500</a></li>
<li>feat: support service source for 19 integrations by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4526">DataDog/dd-trace-go#4526</a></li>
<li>feat: support service source for 13integrations by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4534">DataDog/dd-trace-go#4534</a></li>
<li>feat: add service source on 10 integrations by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4540">DataDog/dd-trace-go#4540</a></li>
<li>feat: force usage of ServiceWithSource in contrib by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4549">DataDog/dd-trace-go#4549</a></li>
<li>fix(eventbridge): update max payload size to 1m by <a
href="https://github.com/Dogbu-cyber"><code>@​Dogbu-cyber</code></a> in
<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4458">DataDog/dd-trace-go#4458</a></li>
<li>feat(telemetry): add stable session identifier headers by <a
href="https://github.com/khanayan123"><code>@​khanayan123</code></a> in
<a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4574">DataDog/dd-trace-go#4574</a></li>
<li>feat: collect service source in client stats by <a
href="https://github.com/raphaelgavache"><code>@​raphaelgavache</code></a>
in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4519">DataDog/dd-trace-go#4519</a></li>
<li>feat: OTel process context v2 (otlp proto) by <a
href="https://github.com/nsavoire"><code>@​nsavoire</code></a> in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4478">DataDog/dd-trace-go#4478</a></li>
<li>fix: join redis and valkey pipeline commands with newlines for
correct agent obfuscation by <a
href="https://github.com/rarguelloF"><code>@​rarguelloF</code></a> in <a
href="https://redirect.github.com/DataDog/dd-trace-go/pull/4593">DataDog/dd-trace-go#4593</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/2b2b2c2c9c420dcc5df24165681ed11c3f1c8438"><code>2b2b2c2</code></a>
chore: make fix-modules &amp;&amp; make generate</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/21438ed81625961b1393806128b142fa7e3829d7"><code>21438ed</code></a>
internal/version: v2.8.1</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/0bc11f30cc930602a07c90a3b106b72bca13ecc0"><code>0bc11f3</code></a>
internal/orchestrion/_integration: v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/f17a712cf0ef081a42e1e972da5cb7d0d09fb1b5"><code>f17a712</code></a>
orchestrion/all: v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/1b8d8e59ef212bae8097c7025e13fcbb99a0e554"><code>1b8d8e5</code></a>
internal/traceprof/traceproftest: v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/7b30b1f0aec1bfd1f7f4a38edaccccd9c691c8fb"><code>7b30b1f</code></a>
contrib/aws/datadog-lambda-go/test/integration_tests/error:
v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/96cc2a4c04453a99cba785cafe17ffb6e9a316a9"><code>96cc2a4</code></a>
contrib/aws/datadog-lambda-go/test/integration_tests/hello:
v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/f3013b5aed4b2051a3da540cafeedbb05d4b89f9"><code>f3013b5</code></a>
instrumentation/internal/validationtest: v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/c9f98439255531363157d4f1b312c594c5ec10e6"><code>c9f9843</code></a>
contrib/labstack/echo.v4: v2.8.1-rc.2</li>
<li><a
href="https://github.com/DataDog/dd-trace-go/commit/e07b30bb083cb5e2aba59f083319f921118d174a"><code>e07b30b</code></a>
contrib/valyala/fasthttp: v2.8.1-rc.2</li>
<li>Additional commits viewable in <a
href="https://github.com/DataDog/dd-trace-go/compare/v2.0.0...v2.8.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/DataDog/dd-trace-go/v2&package-manager=go_modules&previous-version=2.0.0&new-version=2.8.1)](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)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/coder/coder/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-15 23:40:09 +00:00
Andrew Aquino baf4dfae4d fix(site/src/pages/TemplateBuilder): display TemplateCard/ModuleCard's official badge inline (#27036)
closes DEVEX-575

There are some screen widths / base template names where the official
badge will break lines by itself as an orphan (see Google Compute Engine
(Linux) in screenshot below). However, I personally prefer this over the
current flex layout (compare with the screenshot in original issue)

<img width="1840" height="1191" alt="image"
src="https://github.com/user-attachments/assets/d5bee310-0202-4d45-aef7-767e457be051"
/>

Unfortunately `&nbsp;` only works if the entities on either side are
both text--not text on the left + image on the right, which is what we
have here.

^One alternative to prevent orphan badges is to split the base template
name by words, then wrap the last word + the official badge in a span
with `white-space: nowrap;`. But that feels a little overwrought to me;
I like the clarity of continuing to just show `{name}` in the JSX. What
do you guys think?
2026-07-15 15:27:07 -07:00
Callum Styan 15da504cf9 fix: remove excess calls to prepareSQLFilter for workspace and template endpoints (#27248) 2026-07-15 14:23:44 -07:00
Asher 4d4cbd07e6 fix: prevent concurrent token refreshes (#26530)
This can cause bad refresh token errors, since it can only be used once.

Looks like there was an attempt to fix this by checking the database
after a failed refresh, but of course this depends on the first request
having updated the database in time, so both that and this fix are 
required to fully solve.
2026-07-15 12:16:25 -08:00
Nick Vigilante c14b4a010a chore(offlinedocs): update low-risk dependencies (#26876)
## Summary

Updates the `offlinedocs` doc-preview app's dependencies that can move
without code migration, and leaves the heavy framework upgrades for a
separate, deliberate PR.

## Changes

- `react-markdown` 9.1.0 → 10.1.0: used in source
(`pages/[[...slug]].tsx`, the `ReactMarkdown` renderer). The
`components` / `urlTransform` / `remarkPlugins` / `rehypePlugins` API we
rely on is unchanged across the major bump.
- `react-icons` 4.12.0 → 5.7.0: used in source (`MdMenu`, the mobile-nav
hamburger icon). The v5 API is backwards-compatible for our single
import.
- `sanitize-html` 2.17.4 → 2.17.5: used in source
(`sanitizeHtml(body)`); patch bump.
- `prettier` 3.8.3 → 3.9.4 (dev): minor bump, used by the `format`
scripts.
- `@types/node` 20.19.41 → 22.20.0 (dev): types only, capped at the 22.x
line to match the Node 22 runtime rather than tracking latest (26.x).
- `archiver` 6.0.2 → 8.0.0: not imported anywhere in source, so no
render risk (see Notes).

Intentionally **deferred** (coupled breaking migration, touches
component code): Chakra UI v2 → v3, React 18 → 19, Next 15 → 16, ESLint
8 → 10 + flat config, framer-motion 10 → 12.

## Testing

- `tsc --noEmit`: passes.
- `next build` (static export): all 442 pages prerender.
- Dev server launches; `/` and a markdown-rendered page (`/install/`)
both return HTTP 200 and render correctly.
- Verified on Node 22.19.0 / pnpm 10.33.2 (the repo-pinned toolchain);
lockfile `overrides:` block preserved.

## Notes

- `archiver` appears to be a dead dependency (nothing in source imports
it) and could be pruned in a follow-up. It is bumped here only to keep
the lockfile current.

---
🤖 Built with AI assistance.
2026-07-15 15:04:36 -04:00
Faur Ioan-Aurel 0caaac5d27 fix: prebuild coderd before Playwright startup for e2e tests (#27136)
The test-e2e job could flake while Playwright waited for its webServer
to become ready. CI already built site/e2e/bin/coder, but that binary
was built before pnpm build and without the embed tag, so Playwright
ignored it and started coderd with go run -tags embed instead. That put
Go compilation, including frontend asset embedding, inside Playwright's
webServer timeout.

Local runs had a similar ordering trap. pnpm playwright:test invoked
Playwright directly, and Playwright starts webServer before globalSetup,
so the existing preflight build could not guarantee a binary existed
before webServer startup.

Build the E2E coder binary with the embed tag and make it depend on
site/out/index.html. In CI, build the frontend first, then build the E2E
binary, then run Playwright. For local runs, have pnpm playwright:test
and pnpm playwright:test-ui run make site/e2e/bin/coder before invoking
Playwright.

Playwright now starts the prebuilt site/e2e/bin/coder binary and waits
on the public /healthz endpoint instead of an authenticated API
endpoint. This keeps compilation outside the webServer readiness timeout
and makes the readiness probe quieter and more direct. I moved to
/healtz because the existing endpoint was returning 401, which still
means “server is up,” but it is a strange readiness signal. /healthz is
explicitly public and returns 200 OK once the HTTP server is accepting
requests.

Caveat: running pnpm exec playwright test
--config=e2e/playwright.config.ts directly bypasses the package script
and therefore bypasses the prebuild. Use pnpm playwright:test or make
test-e2e for the supported local flow.

Because the site package scripts now call make, add make to knip's
ignored
system binaries.

Tests:
- pnpm lint:types
- pnpm exec playwright test --config=e2e/playwright.config.ts --list
-
PATH="/opt/homebrew/opt/make/libexec/gnubin:/opt/homebrew/opt/gnu-getopt/bin:$PATH"
make gen/mark-fresh
-
PATH="/opt/homebrew/opt/make/libexec/gnubin:/opt/homebrew/opt/gnu-getopt/bin:$PATH"
pnpm playwright:test --list

<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->
2026-07-15 21:21:59 +03:00
Nick Vigilante c84aa564ba docs: normalize code-fence languages for Shiki compatibility (#27161)
Normalizes non-standard code-fence language tags across `docs/**` so a
strict highlighter (Shiki, used by Fumadocs) won't fail the build on an
unrecognized language, and unifies redundant synonym tags onto one
canonical form per language. The current renderer (Speed-Highlight)
detects the language from the code content, not the fence label, so this
drift wasn't visible until now.

## Changes

- `hcl` -> `tf` (199 fences, including indented ones nested in
numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two
distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**`
is actually Terraform resource/data/provider syntax, so the more
specific `terraform` grammar is correct for all of them. `tf` is Shiki's
own alias for that grammar, and it's also what GitHub's own markdown
renderer resolves to the same HCL/Terraform highlighting.
- `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered
PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a
registered file extension (`.ps` isn't), so `ps1` renders identically to
`powershell` there today while bare `ps` would silently lose
highlighting.
- `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files)
- `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text
fallback either way, just shorter.
- `Dockerfile` -> `dockerfile` (lowercase)
- `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all
three to a single shell grammar; this was already the style guide's
stated preference, just not enforced across the existing corpus until
now.
- `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki
and GitHub.
- `jsonc` -> `json` (1 fence). The block has no comments or trailing
commas, so it doesn't need the comments-capable grammar.
- `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`).
Verified the actual content tokenizes identically under both grammars,
and a sibling block in the same file already needs `tsx` for real JSX,
so unifying to one tag is safe for this file. Documented a caveat: `tsx`
mis-tokenizes the legacy angle-bracket type-assertion syntax
(`<Type>value`), which is invalid in real `.tsx` files anyway, so use
`value as Type` instead.
- `yml` -> `yaml` (1 fence)
- Updated `docs/.style/style-guide/formatting.md` to document all
canonical tags

`promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki
doesn't bundle a grammar for either, so they need a custom grammar
registration when the site adopts Shiki, rather than degrading to `txt`.
Tracked as follow-up work under DOCS-118 and
[DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting)
(promql).

Does not touch `offlinedocs/`.

Linear:
[DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs)

<details>
<summary>How the fence tags were verified</summary>

Each tag was tested against a real `shiki@latest` highlighter instance
(`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's
`@wooorm/starry-night` grammar sources (the renderer that actually
displays these `.md` files today, in repo browsing and PR diffs), since
that's what determines whether brevity is safe before Shiki adoption:

```text
FAIL  env        -- Language `env` is not included in this bundle.
FAIL  Dockerfile -- Language `Dockerfile` is not included in this bundle.
FAIL  promql     -- Language `promql` is not included in this bundle.
FAIL  caddyfile  -- Language `caddyfile` is not included in this bundle.
FAIL  pwsh       -- Language `pwsh` is not included in this bundle.
FAIL  output     -- Language `output` is not included in this bundle.
```

`hcl` doesn't error in Shiki, since it's a real grammar, but that's
exactly the trap: it was silently rendering every fence with the generic
HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged
fence in `docs/**` was manually checked against `origin/main` and is
genuinely Terraform content.

For `ts`/`tsx`, tokenizing the actual doc content confirmed identical
output under both grammars; a synthetic test with the legacy
angle-bracket cast syntax confirmed `tsx` degrades on that specific
construct, which the style guide now calls out.

The first normalization pass only matched fence tags at column 0
(`^```tag$`), missing tags indented inside numbered/bulleted lists. A
follow-up pass caught the remaining occurrences at any indentation
level.

</details>


---

*This PR description and the underlying changes were prepared with Coder
Agents assistance.*
2026-07-15 14:07:09 -04:00
Jeremy Ruppel d0982e3cc7 fix(coderd/templatebuilder): prompt for DigitalOcean base variables (#27268)
## Summary

The DigitalOcean template builder base declared Terraform `variable`
blocks for `project_uuid` and `ssh_key_id` that the template builder
never filled. `project_uuid` was required with no default, so the build
broke with no way to supply a value from the wizard (DEVEX-591).

This brings the DigitalOcean base to parity with the GCP bases fixed in
#27015:

- Declare `project_uuid` (required) and `ssh_key_id` (optional, default
`0`) in `base.json` so the wizard prompts for them on the first step.
- Inject the entered values via `default = {{ .Variables.* }}` in
`main.tf.tmpl`, keeping the existing `variable` blocks and validation.
- Drop the `sensitive` flags. The variable-injection path
(`mergeBaseVariables`, `DefaultBaseRenderContext`, and the snapshot test
helper) skips sensitive variables, so a sensitive base variable renders
empty. A project UUID / SSH key ID are not secrets.
- Update the README now that the values are prompted rather than
manually edited.
- Regenerate the `digitalocean-linux.tf.golden` snapshot.

## Testing

- `go test ./coderd/templatebuilder/`

<img width="1048" height="616" alt="Screenshot 2026-07-15 at 12 44
42 PM"
src="https://github.com/user-attachments/assets/89e334ca-e904-4387-9264-6ed1614a40ba"
/>

<details>
<summary>Audit of all template builder bases for unfilled
variables</summary>

| Base | Variable status | Verdict |
|------|-----------------|---------|
| aws-linux | no HCL `variable` blocks; provider env auth | OK |
| aws-windows | same | OK |
| azure-linux | same | OK |
| **digitalocean-linux** | `project_uuid` (required, no default) +
`ssh_key_id`; absent from `base.json` | **Fixed here** |
| docker | `docker_socket` has `default = ""`; `container_image` via `{{
.Variables }}` + declared | OK |
| gcp-linux | fixed in #27015 | OK |
| gcp-windows | fixed in #27015 | OK |
| kubernetes | `namespace` (required), `use_kubeconfig`,
`container_image` all via `{{ .Variables }}` + declared | OK |
| scratch | no variables | OK |

DigitalOcean was the only broken base; all others either have safe
defaults or already declare their variables.

**Mechanism note:** `base.json` `variables[]` drives the first-step
prompts and values are injected as HCL literals via `{{
.Variables.<name> }}` (strings quoted, numbers/bools raw; supported
types: string, number, bool). Sensitive/computed variables are
intentionally skipped everywhere the injection map is built, so they
cannot currently be injected. That is why the `sensitive` flags were
removed here.
</details>

---
*This PR was generated by Coder Agents on behalf of @jeremyruppel.*
2026-07-15 14:05:18 -04:00
Steven Masley 3b72a3e5dd test(coderd/rbac): add many-orgs authorization benchmark (#27270)
<!-- Authored with Coder Agents on behalf of @Emyrk -->
Adds `BenchmarkRBACManyOrgs` to measure `Authorize`, `Prepare` (partial
evaluation), and `Prepare`+`CompileToSQL` as a subject's org-membership
count grows (1, 5, 10, 50, 100 orgs).

- Written to evaluate the org set-membership rewrite in #27244, where
partial-eval cost scales with org count.
- Subject uses pre-expanded cached roles (`WithCachedASTValue`), member
+ per-org `organization-member` roles, `ScopeAll`; authorizer has no
cache so each iteration measures a real evaluation.

Results comparing `main` vs #27244 are posted on that PR.

<sub>Coder Agents on behalf of @Emyrk.</sub>
2026-07-15 12:04:05 -06:00
Bobby HoandCian Johnston 511c3cddc0 fix(testutil/expecter): remove nested pipe from output logging path (#27204)
## Summary

Partial fix for the flake in
[PLAT-251](https://linear.app/codercom/issue/PLAT-251/flake-test-go-pg-macos-job-timeoutcancelled)
/ [coder/internal#1365](https://github.com/coder/internal/issues/1365)
(`test-go-pg (macos-latest)` timing out and getting cancelled after 25
minutes).

## Problem

`testutil/expecter.Expecter` drains a command's stdout/stderr through
`io.Copy` into an internal buffer, but it also teed every write through
a **second, independent unbuffered `io.Pipe()`**, read by a
`bufio.Scanner`, purely to produce human-readable debug logs:

```go
logr, logw := io.Pipe()
w := io.MultiWriter(logw, out)   // out never blocks; logw is a second unbuffered pipe
go func() { io.Copy(w, r) }()    // drains the command's real stdout/stderr
go func() { bufio.NewScanner(logr).Scan() ... }()  // only reads when scheduled
```

`io.MultiWriter` only returns once **every** writer succeeds. If the
scanner goroutine is ever delayed (GC pause, scheduler contention under
CI's `-parallel=16` test config), the write into `logw` blocks, which
blocks the `io.Copy` write, which stops it from reading the command's
actual output pipe, which means the **command's own write can never
complete either**, since nobody is left reading it. Nothing on this path
has a timeout, so once wedged it stays wedged until `go test`'s own
`-timeout 20m` kills the whole binary.

This reproduced locally in `TestConfigSSH_FileWriteAndOptionsFlow` under
the macOS CI job's exact parallelism, stuck writing a routine
"executable not in `$PATH`" warning (`cli.currentBinPath`) that the test
wasn't actively reading at that instant. It's a flake, not a
deterministic failure, because under light load the scanner always keeps
up trivially.

### Race condition

```mermaid
sequenceDiagram
    participant TG as Test goroutine
    participant CmdG as Command goroutine<br/>(inv.Run)
    participant P1 as Pipe 1<br/>(inv.Stdout)
    participant Copy as io.Copy goroutine
    participant P2 as Pipe 2<br/>(logw/logr, debug logging only)
    participant Scan as Scanner goroutine
    participant Buf as stdbuf (out)<br/>unbounded, never blocks

    CmdG->>P1: Write(warning output)
    P1-->>Copy: Read() unblocks
    Copy->>P2: MultiWriter step 1: write to logw
    Copy->>Buf: MultiWriter step 2: write to out

    rect rgb(255, 230, 230)
    Note over Scan: Under heavy parallel test load,<br/>Scan()'s next Read() is delayed
    P2--xCopy: Write(logw) blocks: nobody reading yet
    end

    Copy--xP1: Read() no longer called: Copy is stuck writing to P2
    CmdG--xP1: Write() can't complete either: nobody reads Pipe 1
    Note over CmdG: Command write blocks FOREVER<br/>(confirmed: 17-18 min in a goroutine dump)

    TG->>TG: ExpectMatch times out (got ""), fails the test
    Note over TG,CmdG: Test goroutine exits, but CmdG is<br/>orphaned and permanently blocked until<br/>go test's own -timeout kills the binary
```

## Fix

Remove the second pipe. `io.Copy` now writes only to the unbounded,
non-blocking `stdbuf`. Debug logging is forwarded via a **bounded,
non-blocking channel** instead of a second unbuffered pipe: a full
channel just drops the chunk rather than propagating backpressure.

This works because the only thing the command's real output pipe depends
on is `io.Copy(out, r)`, and `out.Write()` can never block, so `io.Copy`
always keeps calling `Read()`, so the command's write always has an
active reader. Debug logging becomes provably unable to backpressure the
command under test, since losing an occasional log line under extreme
load is an acceptable tradeoff, unlike losing a whole CI job to a silent
deadlock. The fix lives in the shared harness rather than in
`cli/configssh.go` because the warning it's tripping over is legitimate,
unrelated product behavior; every other test using this harness that
happens to emit output the test isn't actively matching at that instant
was exposed to the same bug.

**Note:** this addresses one of two distinct root causes bundled under
PLAT-251. The other is a Depot `GOCACHEPROG` shutdown hang in CI
infrastructure (outside this repo, previously diagnosed by a maintainer
on the Feb 2026 incident), which this change cannot affect. Locally this
fix measurably improves things, but a residual, load-dependent hang was
still observed under extreme synthetic contention on a shared dev
machine; watching several real CI runs is the next step before
considering the flake fully resolved.

---------

Co-authored-by: Cian Johnston <cian@coder.com>
2026-07-15 09:08:11 -07:00
Cian Johnston f958727887 chore: update mise.lock (#27258)
`mise install` now adds more properties to `mise.lock` after running
`mise install`:

- Bare URLs get `checksum` and `url`
- GitHub URLs get an `api_url` to the release asset
2026-07-15 14:57:23 +01:00
Spike Curtis ac35e0d3d8 test: fix flake in TestServer/Logging (#27263)
<!--

If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting.

-->

fixes https://github.com/coder/internal/issues/1618

same underlying issue as https://github.com/coder/internal/issues/946

Test flakes because main test ends before the server can connect to postrgres and this causes the CLI invocation to return an error we don't care about.
2026-07-15 14:39:45 +02:00