Commit Graph
659 Commits
Author SHA1 Message Date
Sas Swart fc188fdaee fix: create agent firewall sessions without requiring agent read access (#26990)
## Overview

Part of the **boundary correlation** feature. Fixes lazy creation of
`boundary_sessions` rows so it works within the agent's RBAC
constraints, and consumes the new `ConfinedProcessName` field reported
by boundary.

Pairs with coder/boundary#206, which adds `ConfinedProcessName` to
`ReportBoundaryLogsRequest`. This branch bumps the
`github.com/coder/boundary` module to pick up that work.

## Problem

`ensureSession` did a pre-insert existence check via
`GetBoundarySessionByID`. Agents are **not permitted to read boundary
sessions**, so that read path is not viable when the session is created
from an agent-reported log batch.

## Changes

- **Remove the pre-insert read.** `ensureSession` now inserts directly
and treats a primary-key unique violation as success, covering sessions
already created by a prior batch, a reconnection, or another coderd
replica — without requiring read access.
- **Per-connection guard.** Add a mutex-protected `ensuredSessions` set
so repeated log batches on the same connection skip the existence check
and insert entirely, touching the database only for the logs. On a
transient insert failure the session is left unmarked so the next batch
retries.
- **Consume `ConfinedProcessName`.** Pass `req.GetConfinedProcessName()`
through to the session insert.
- **Bump boundary module** from `v0.9.0` to
`v0.9.1-0.20260706095856-35ba90f9e8b2`.
- **Tests.**
- Add `TestReportBoundaryLogsAgentRBAC`
(`coderd/boundary_logs_test.go`), an integration test that connects as a
real workspace agent, verifies the session and log are persisted under
agent RBAC, and asserts the agent subject cannot read boundary sessions
— guarding against reintroducing a pre-insert read.
- Add `TestReportBoundaryLogsSessionGuard` (session inserted once across
two batches, logs inserted per batch) and
`TestReportBoundaryLogsSessionRetriedOnError` (insert retried after a
transient error).
- Regenerate `agent-firewall` CLI docs/golden files and adjust the
clidocgen template to render the YAML path when a flag has no long name.

> 🤖 This PR was opened by Coder Agents on behalf of @SasSwart.
2026-07-07 10:42:01 +00:00
Cian Johnston b21e0717d5 feat: remove chat chain mode (#26980)
Removes OpenAI Responses "chain mode" from chatd. Closes CODAGT-445.

- Deletes `chatopenai/responses.go` (chain detection, activation, prompt filtering, response ID extraction) and its tests.
- Deletes the `ChainBroken` classification in `chaterror` and the chatloop retry bookkeeping that disabled chain mode mid-generation.
- Drops the `chain_broken` label from the `coderd_chatd_stream_retries_total` metric.
- Stops reading and writing `chat_messages.provider_response_id`
- Deletes the dead `ClearChatMessageProviderResponseIDsByChatID` query. Dropping the column is a follow-up migration.
- Deletes three chatloop hooks no caller sets (`ReloadMessages`, `DisableChainMode`, `PrepareMessages`), the dead `const AgentChatContextSentinelPath`, and stale chain-mode comments.

🤖 Generated by Coder Agents on behalf of @johnstcn.
2026-07-06 11:57:12 +01:00
Garrett Delfosse b1ead5f085 fix: set git identity for release tagging and surface git stderr (#26945)
## What happened

The [Tag and Release
run](https://github.com/coder/coder/actions/runs/28549109434/job/84641825784)
failed in the `prepare-release` job at the step "Prepare release
(calculate version, create tag and branch)" with:

```
error: create tag v2.35.0-rc.0: exit status 128
```

## Root cause

`prepare-release` creates an **annotated** tag via `git tag -a`
(`scripts/release-action/prepare.go`), which records a tagger and
therefore requires a git identity. The job never ran `git config
user.name/user.email`, and runners have none configured, so git aborts
with exit status 128. The real `fatal:` message was hidden because
`realExecutor.RunMutation` discarded the command's stderr.

## Changes

- **`.github/workflows/tag-and-release.yaml`**: add a "Configure git
identity" step (`ci@coder.com` / `Coder CI`) to the `prepare-release`
job, before the release tool runs. This matches the identity pattern
already used later in the same workflow.
- **`scripts/release-action/cmdexec.go`**: capture stderr in
`RunMutation` and include it in the returned error, so a failing
mutation surfaces the underlying command output (e.g. git's `fatal:`
line) instead of only `exit status N`.
- **`scripts/release-action/cmdexec_test.go`**: add a test asserting
stderr is surfaced on failure.

## Testing

- `go test ./scripts/release-action/...` passes.
- `go vet ./scripts/release-action/...` and `gofmt` clean.
- `actionlint .github/workflows/tag-and-release.yaml` clean.
- Reproduced the failure locally: `git tag -a` with no usable identity
exits 128 (`fatal: no email was given and auto-detection is disabled`);
with an identity configured it succeeds.

<details>
<summary>Root-cause analysis / decision log</summary>

**Failing step** runs `go run ./scripts/release-action prepare-release
--type create-release-branch --ref main --commit cb1a87b…`.

1. The tool computes the next version `v2.35.0-rc.0` and calls
`createAndPushTag`, which runs `git tag -a v2.35.0-rc.0 -m "Release
v2.35.0-rc.0" <targetRef>` (`prepare.go:56`).
2. That git command exits **128**, wrapped as `error: create tag
v2.35.0-rc.0: exit status 128`.

**Why it's the identity, and not something else:**

- No `git config user.name/user.email` step exists in the
`prepare-release` job; the `setup-mise` action does not set it; and the
tool itself never sets an identity. Annotated tags require a tagger, so
`git tag -a` fails on runners whose auto-detected identity is bogus
(`…@runner.(none)`), which is rejected under git's strict identity
check.
- Not a pre-existing tag collision: no `v2.35.0*` tag exists on the
remote, and the code pre-checks for an existing tag (and would emit a
different "already exists" error).
- Not an unresolved ref: `targetRef` resolves to the provided commit
SHA, checked out at `fetch-depth: 0`.
- The log was unhelpful because `RunMutation` used `cmd.Run()` without
wiring git's stderr (`cmdexec.go`), discarding the `fatal:` line and
leaving only `exit status 128`. This PR fixes that too.
- The sibling `release.yaml` explicitly sets `git config
user.email/user.name` before its git mutations; that step was simply
missing from the newer `tag-and-release.yaml` `prepare-release` job.

</details>

---

> Generated by Coder Agents on behalf of @f0ssel.
2026-07-01 15:10:45 -07:00
Garrett Delfosse ff7e0bc193 feat: add dry-run flag via CommandExecutor interface (#26422)
## Summary

Adds a `--dry-run` capability to the `release-action` Go tool and
exposes it through a **new** manual workflow, `tag-and-release.yaml`,
without disturbing the existing `release.yaml` pipeline.

PR #25162 had rewritten `release.yaml` in place to be driven by
`scripts/release-action`, which changed its `workflow_dispatch` inputs
from `release_channel`/`release_notes`/`dry_run` to
`release_type`/`commit_sha`. That broke `scripts/releaser`, which
dispatches `release.yaml` with the original inputs. This PR restores
`release.yaml` and moves the Go-driven pipeline to its own workflow.

## Workflow layout after this PR

| Workflow | Trigger | Driven by | Purpose |
|---|---|---|---|
| `release.yaml` | `scripts/releaser` (`gh workflow run`) | legacy
inline shell | Existing pipeline, restored to pre-#25162 state |
| `tag-and-release.yaml` | Manual (Actions UI) |
`scripts/release-action` Go tool | New pipeline with `prepare-release` +
`dry_run` |

`release.yaml` is restored byte-for-byte to its pre-#25162 version, so
its inputs match what `scripts/releaser` sends again.

## `release-action` design

### CommandExecutor interface

Abstracts CLI command execution behind read-only and mutating methods:

| Method | Purpose | Dry-run behavior |
|---|---|---|
| `RunOutput` | Read-only, capture stdout | Executes normally |
| `Run` | Read-only, exit code only | Executes normally |
| `RunMutation` | Changes remote state, no output | **Prints command,
skips execution** |
| `RunMutationStdout` | Changes remote state, streaming I/O | **Prints
command, skips execution** |

Two implementations: `realExecutor` (executes via `os/exec`) and
`dryRunExecutor` (delegates read-only calls, prints mutating calls).

### `prepare-release` subcommand

Composes `calculateNextVersion` with idempotent tag and branch
creation+push, emitting the same JSON as `calculate-version`. Matching
existing refs are skipped; mismatched refs error.

### `tag-and-release.yaml` `dry_run` input

When enabled: `prepare-release` runs with `--dry-run` (version
calculated, plan printed, nothing pushed), notes are generated for
inspection, and the build+publish job is skipped via an `if` guard
(cascading to homebrew/winget/docs).

## Mutating commands covered by `--dry-run`

| Command | Call site |
|---|---|
| `git tag -a <version> ...` | `createAndPushTag` |
| `git push origin refs/tags/...` | `createAndPushTag` |
| `git push origin <sha>:refs/heads/...` | `createAndPushBranch` |
| `gh release create ...` | `publishRelease` |

`git fetch --tags --force origin` is intentionally not a mutation; it
only updates local remote-tracking refs and must run for accurate
version calculation.

## Changes

- **New**: `scripts/release-action/cmdexec.go`, `prepare.go` (+ tests)
- **Refactored**: `git.go`, `github.go`, `calculate.go`, `notes.go`,
`commit.go`, `publish.go` to thread `CommandExecutor`; added `gitMutate`
- **Updated**: `main.go` adds `--dry-run` flag and `prepare-release`
subcommand
- **New**: `.github/workflows/tag-and-release.yaml` (manual, Go-driven,
with `dry_run`)
- **Reverted**: `.github/workflows/release.yaml` to its pre-#25162 state

> [!NOTE]
> Generated by Coder Agents on behalf of @f0ssel
2026-07-01 16:20:00 -04:00
Bobby Ho 608bc6e837 fix(scripts/oauth2): fix test-mcp-oauth2.sh for macOS and OAuth 2.1 compliance (#26825)
The `test-mcp-oauth2.sh` script had three bugs that caused tests 2, 3,
and 4 to fail when run on macOS.

`grep -oP` uses PCRE lookbehind (`\K`), which is not supported by BSD
grep on macOS. Replaced with `grep -oE … | sed 's/code=//'` which works
on both platforms.

The token exchange requests in tests 2, 3, and 4 omitted `redirect_uri`,
which is required by RFC 6749 §4.1.3 whenever `redirect_uri` was
included in the authorization request. The server correctly rejects
these with `invalid_grant`, masking the actual PKCE validation.

Test 4's resource parameter flow was missing PKCE parameters entirely.
The server enforces PKCE on all authorization code flows per OAuth 2.1,
so the authorization request returned 400 and the script exited silently
due to `set -euo pipefail`.
2026-06-30 08:02:55 -07:00
Jeremy Ruppel 7daf3123cb feat: import new modules and refactor codegen script (#26838) 2026-06-29 17:47:06 -04:00
Jeremy Ruppel 48e8f70e09 fix: remove Goose module from catalog (#26833)
Removes the Goose AI agent module from the template builder backend
catalog.

## Changes

- Deleted `coderd/templatebuilder/modules/goose/` (Terraform template
and module metadata)
- Removed the `"goose"` entry from
`scripts/templatebuildermodulegen/main.go`

Frontend assets (`goose.svg`, `icons.json`) are intentionally left in
place as other parts of the app still reference them.

> Generated by Coder Agents on behalf of @jeremyruppel
2026-06-29 16:52:41 -04:00
Danny Kopping 9f211ce5ae fix: use HEAD instead of fetching base branch for emdash linter (#26733)
## Problem

The `lint/emdash` check fails on Graphite-stacked PRs. See [this failed
run](https://github.com/coder/coder/actions/runs/28225390084/job/83616080375?pr=26650):

```
Base ref origin/graphite-base/26650 not found locally, fetching graphite-base/26650...
ERROR: could not fetch base ref origin/graphite-base/26650.
ERROR: could not determine base ref.
make: *** [Makefile:768: lint/emdash] Error 1
```

`scripts/check_emdash.sh` resolved its diff base by fetching
`origin/$GITHUB_BASE_REF` and computing a merge-base. Graphite sets
`GITHUB_BASE_REF` to a `graphite-base/<n>` ref that is ephemeral (it is
not reliably present on origin), so the fetch fails and the check errors
out instead of running.

## Fix

`actions/checkout` checks out the PR **merge commit**
(`refs/pull/<n>/merge`), whose **first parent (`HEAD^1`) is the exact
base commit GitHub merged against**. Diffing `HEAD^1` against the
checkout yields every change the PR makes against its base branch, for
normal and Graphite-stacked PRs alike. No base-branch fetch, no
merge-base computation, no `gh`-based deepen dance.

- `scripts/check_emdash.sh`: use `HEAD^1` (the PR base commit) as the
diff base in CI. Drops `resolve_merge_base` and `fetch_base_ref`. Emits
a clear error if `HEAD^1` is missing (checkout too shallow).
- `.github/workflows/ci.yaml`: bump the `lint` job checkout to
`fetch-depth: 2` so `HEAD^1` is present with no runtime fetch.

Local dev behavior (merge-base against `origin/main`) is unchanged.

## Verification

- `make lint/emdash`, `make lint/shellcheck`, `make
lint/actions/actionlint` pass.
- Simulated the CI path with `GITHUB_BASE_REF` set: the check resolves
to `HEAD^1` without fetching and still flags an added line containing an
emdash.

<details>
<summary>Why the merge commit's first parent</summary>

For a `pull_request` checkout of `refs/pull/<n>/merge`:

- `HEAD` = GitHub's synthetic PR merge commit
- `HEAD^1` = the exact base commit used for the merge
- `HEAD^2` = the PR head commit

`git diff HEAD^1 HEAD` is the full-tree diff from the base snapshot to
the merged result, i.e. all of the PR's changes against its base. This
is immutable and always local (given depth >= 2), unlike base branch
refs which are mutable and, for Graphite stacks, ephemeral.

</details>

---

This PR was generated by Coder Agents on behalf of @dannykopping.
2026-06-26 12:34:49 +00:00
Zach 953091c7bc refactor: use sync.WaitGroup.Go in tests (#26671)
Migrate `wg.Add(1); go func() { defer wg.Done(); ... }()` to
`wg.Go(func() { ... })` in tests.

Where the prior pattern passed the loop variable explicitly via a
closure parameter (`go func(id int) { ... }(i)`), drop the parameter and
reference the loop variable directly. Per-iteration loop variables since
Go 1.22 make this safe.
2026-06-25 15:41:09 -06:00
Kyle Carberry 32217259b7 feat: cap tool output to fit the model context window (#26637)
## Problem

Local tool results were persisted and replayed to the model verbatim,
with no size cap. A single oversized result, most often a multi-megabyte
response from an MCP tool, overflows the prompt on the next request.
Every retry rebuilds the same history and fails the same way, leaving
the chat wedged in `error`. Auto-compaction is reactive (token usage is
only known after a response), so it can't catch a single result that
blows the very next request.

## Fix

Cap every locally-executed tool result at its single choke point,
`executeSingleTool` in `chatloop`, so the cap covers built-in tools,
**global (deployment-pinned) MCP**, **workspace MCP**, and provider
runners uniformly. Because this runs before the result is published to
the live stream and before it is committed, the SSE preview, the
persisted message, and the model replay all see the same bounded output.

The budget is token-aware: a single tool result may use at most half the
model's context window (`~4 bytes/token`), with a `16KB` floor and a
`64KB` default when the window is unknown. Truncation keeps the head and
tail of the output and replaces the middle with a marker telling the
model how much was removed and to narrow its query; it is UTF-8 safe and
never exceeds the budget. Binary media `Data` is passed through
untouched (only the text payload is bounded).

A `coderd_chatd_tool_result_truncated_total{provider,model,tool_name}`
counter and a warning log record each truncation.

## Out of scope

- Provider-executed results (e.g. web search) arrive via the stream, not
`executeSingleTool`.
- Dynamic/external tool results submitted through the `/tool-results`
API are validated as JSON elsewhere.
- Cumulative growth across many results is still handled by context
compaction; this change only bounds any single result.

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

- New `coderd/x/chatd/chatloop/tooltruncate.go`:
`toolResultByteBudget(contextLimitTokens)` and
`truncateToolResultText(text, maxBytes)` (pure, unit-tested).
- `chatloop.go`: added `ContextLimit` to `ExecuteLocalToolsOptions`;
threaded a computed byte budget through `executeTools` into
`executeSingleTool`, where `resp.Content` is capped for the text,
media-text, and error branches.
- `generation.go`: passes `ContextLimit: prepared.ContextLimitFallback`
(the model's configured context limit).
- `metrics.go`: new `ToolResultTruncatedTotal` counter +
`RecordToolResultTruncated`.
- Tunable knobs live as constants in `tooltruncate.go`
(`toolResultContextDivisor = 2`, `bytesPerTokenEstimate`,
`minToolResultBytes`, `defaultToolResultBytes`).

Verified: `go build ./coderd/x/chatd/...`, `go test
./coderd/x/chatd/chatloop/...`, and the `chatd` test binary compiles.

</details>

---

Resolves CODAGT-678

Generated by Coder Agents on behalf of @kylecarbs.
2026-06-24 09:16:38 -06:00
Jon Ayers 6da322d59f feat: add Prometheus metrics to NATS pubsub for parity with PGPubsub (#26441) 2026-06-23 11:59:48 -05:00
Jeremy Ruppel a30631198d feat: template builder backend fixes (DEVEX-287) (#26432)
Part of the Template Builder wizard PR stack.

## Backend fixes

1. **Registry URL scheme fix**: Default
`CODER_TEMPLATE_BUILDER_REGISTRY_URL` was `https://registry.coder.com`
but Terraform module registry addresses must be scheme-less. Changed to
`registry.coder.com`.

2. **Sensitive variable defaults**: Module `.tf.tmpl` files for
claude-code, aider, amazon-q had sensitive `variable` blocks without
`default`, causing `terraform plan` to fail during template import. Also
fixed the `templatebuildermodulegen` script.

3. **Auto-quote string variables**: The backend now accepts raw string
values from callers and wraps them in HCL quotes automatically.
Previously callers were required to send pre-quoted HCL literals, which
is not a reasonable API contract.

---
> [!NOTE]
> Generated by Coder Agents on behalf of @jeremyruppel
2026-06-23 09:17:14 -04:00
Danielle Maywood ecfff8a7db feat: move model settings page to ai settings 2026-06-23 12:33:28 +01:00
Zach 917dbde439 fix: regen feature stage docs from HEAD & enforce generation (#26528)
Generate the experimental and beta tables in
docs/install/releases/feature-stages.md from the current source tree
instead of release tags + GitHub API because we found the table of beta
features was stale in recent release(s). This approach works now that
Coder publishes per-release docs.

This change was assisted by Coder Agents.
2026-06-22 11:12:26 -06:00
Garrett Delfosse e188ee03a4 fix(scripts/check_emdash.sh): skip emdash check when no diff base is available (#26489)
## Problem

`scripts/check_emdash.sh` is a diff gate for pull requests: it resolves
the merge-base against the target branch and only inspects added lines.
When it cannot resolve a base ref, it fell back to scanning **every
tracked file**.

Push builds on release branches hit exactly this case: the `lint` job
checks out with `fetch-depth: 1`, so `origin/main` is absent, and
`GITHUB_BASE_REF` is only set for `pull_request` events. With no base
ref, the whole-tree scan flags the many pre-existing emdash/endash
characters already in the repo and fails `make lint` (`lint/emdash`),
even though the build introduced none of them. Observed on
`release/2.34` CI (run
[27704528068](https://github.com/coder/coder/actions/runs/27704528068/job/81949529546)).

## Fix

When no base ref can be determined (i.e. outside a pull request), skip
the check instead of scanning the entire tree. A full scan remains
available on demand via `scripts/check_emdash.sh --all`.

## Testing

- **No base ref** (release-push simulation, no `GITHUB_BASE_REF`, no
`origin/main`): old script scans all files and fails on a pre-existing
emdash; new script skips and exits 0.
- **PR path** (diff vs merge-base): `OK: no emdash or endash characters
found.`
- **`--all`**: still scans the full tree (flags pre-existing characters
as before).
- `shellcheck` and `shfmt` clean.

## Backports

Backport PRs target `release/2.33` and `release/2.34` (same bug, older
script variant). `release/2.29` and `release/2.32` do **not** contain
`scripts/check_emdash.sh`, so there is nothing to backport there.

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

Considered alternatives to the skip:

1. **Compare against `github.event.before`** on push events. Rejected:
the before-SHA is frequently unreachable in a `fetch-depth: 1` clone,
and wiring it in requires per-workflow env changes that complicate
backports.
2. **Fetch `origin/main` / deepen history** in the release lint job.
Rejected for the same backport-surface reason and because it only masks
the design intent.

The check exists to stop *new* emdashes from landing via PRs; that gate
already ran on the originating PRs. On non-PR builds there is no
meaningful diff base, so skipping is correct and self-contained in the
script (clean to backport). The explicit `--all` mode is preserved for
intentional full-tree audits.

</details>

---
Generated by Coder Agents on behalf of @f0ssel.
2026-06-17 16:30:48 -04:00
Paweł Banaszewski f1ce1013c4 chore: export AI Gateway metrics under new branding + keep old as alias (#26413)
> AI Tools where used in this request.

Registers `coder_aibridged_*` and `coder_aibridgeproxyd_*` metrics under
new prefixes: `coder_ai_gateway_*` and `coder_ai_gateway_proxy_*`.
Old prefix is still exported. Will be removed in later release.

Also updated the `metricsdocgen` static fixture. Added 4
previously-undocumented metrics `key_pool_state`,
`key_pool_state_transitions_total`, `key_pool_exhaustions_total`,
`key_pool_failover_attempts` added the `client` label to the existing
interception, prompt, and token counter samples.

Updated AI Gateway documentation.
2026-06-17 13:10:53 +02:00
dependabot[bot] 0040ea2efd chore: bump alpine from 3.23.3 to 3.24.1 in /scripts (#26406)
Bumps alpine from 3.23.3 to 3.24.1.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=alpine&package-manager=docker&previous-version=3.23.3&new-version=3.24.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)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 11:08:21 +00:00
Danny Kopping a1330e3a8c refactor: rename Ai* database identifiers to AI* (AIGOV-369) (#26327)
Adds `ai` to sqlc's `gen.go.initialisms` in `coderd/database/sqlc.yaml`
so the generated DB code follows Go's initialism convention. Adds the
matching `ai` -> `AI` case to the dbgen PascalCase helper
(`scripts/dbgen/main.go`) so the corresponding `dbmem` / mock
identifiers stay in sync. `make gen` regenerates the rest; hand-written
call sites that consume DB-generated identifiers
(`enterprise/audit/table.go`, `coderd/database/modelmethods.go`,
`enterprise/coderd/aigatewaykeys.go`, `coderd/database/dbauthz/*`, etc.)
are updated to match.

Scope is deliberately limited to the database layer:

- `coderd/rbac/*` (resource and scope generators) is untouched —
`ResourceAi*` / `ScopeAi*` constants stay on main's casing.
- `codersdk/*` (Go SDK) is untouched — `codersdk.ResourceAi*` /
`codersdk.APIKeyScopeAi*` constants stay on main's casing, so external
Go SDK consumers see no source-level break.
- `Aibridge*` identifiers (one SQL token `aibridge`, not `ai_bridge`)
are out of scope.

On-the-wire values are unchanged: enum strings, RBAC resource type
strings, API key scope strings, and JSON tags all stay the same. The
HTTP/JSON surface is unaffected.

Refs:
[AIGOV-369](https://linear.app/codercom/issue/AIGOV-369/change-ai-references-in-coderddatabasemodelsgo-to-ai)

🤖 Generated with [Coder Agents](https://coder.com)
2026-06-16 09:01:43 +00:00
Jeremy Ruppel 809bd613e3 feat(scripts): add generator for template builder module catalog (#26193)
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.

Adds `scripts/templatebuildermodulegen/`, a Go tool that fetches module metadata from the Coder registry HTTP API and generates the `module.json` manifests and `.tf.tmpl` files used by the template builder catalog.

The generator calls `GET /api/modules/{id}` for per-module metadata (display name, description, icon, tags, variables) and the Terraform protocol versions endpoint for semver resolution. No git clone or HCL parsing required.

Split into four files:
- `main.go`: orchestration, module config map, CLI flags
- `types.go`: output types (`ModuleManifest`, `ModuleVariable`) and API response types
- `fetch.go`: HTTP fetching, version resolution, variable conversion, icon normalization
- `write.go`: JSON writer, `.tf.tmpl` Go template and writer
2026-06-15 09:25:56 -04:00
Nick Vigilante a86e1ca4bb fix: pin Terraform 1.15.5 for all Nix platforms (#25799)
The terraform_1_15_5 derivation previously only handled linux/amd64,
falling through to unstablePkgs.terraform on all other platforms. On
macOS this meant a different Terraform version was used, which caused
the version check in make pre-commit to trigger generate.sh,
regenerating all testdata with the host platform's OS/arch
(darwin/arm64) instead of the committed linux/amd64 values.

Three changes:

1. `flake.nix`: add explicit linux_arm64, darwin_arm64, and darwin_amd64
cases with SHA256 hashes from the official HashiCorp release. Unknown
platforms still fall back to unstablePkgs.terraform.

2. `provisioner/terraform/testdata/generate.sh`: guard full regeneration
behind a Linux-only check. The committed testdata encodes linux/amd64
values from the coder_provisioner data source, so regenerating on macOS
would permanently bake in darwin/arm64. The --check path still runs on
all platforms so the version target can detect provider mismatches.
Regeneration via CI or an explicit Linux run is unchanged.

3. `scripts/release/check_commit_metadata.sh`: fix a shfmt (>=3.13)
false positive. The [install.sh] key in an associative array literal was
parsed as floating-point arithmetic (a zsh-only feature). Moving it to a
post-declaration assignment satisfies the stricter parser without
changing runtime behavior.

<!--

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.

-->



Linear: DOCS-279
2026-06-12 16:28:54 -04:00
Hugo Dutka 4debd23cbb fix: chatd refactor (#26270)
Implements the chatd stabilization RFC.

Combines:
- https://github.com/coder/coder/pull/25908
- https://github.com/coder/coder/pull/25923
- https://github.com/coder/coder/pull/26109
- https://github.com/coder/coder/pull/26110
- https://github.com/coder/coder/pull/26111
- https://github.com/coder/coder/pull/26112
2026-06-12 13:33:12 +02:00
Nick Vigilante cfb03f52db fix: update stale docs URLs across non-TS files (#25750)
Closes [DOCS-256](https://linear.app/coder/issue/DOCS-256). Sibling to
[DOCS-253](https://linear.app/coder/issue/DOCS-253) (#25740).

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

## What changed

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

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

## What did not change

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

## Verification

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

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

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

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

</details>

---

Generated by Coder Agent on behalf of @nickvigilante.
2026-06-10 13:40:50 -04:00
Callum StyanandMux 4627b01415 fix: reduce agentfake manager startup time (#25669)
Signed-off-by: Callum Styan <callumstyan@gmail.com>
Co-authored-by: Mux <noreply@coder.com>
2026-06-04 15:28:13 -07:00
Garrett Delfosse b95697a370 ci: rewrite release workflow to be fully GitHub Actions-driven (#25162)
Replace the local interactive release CLI and legacy shell scripts with
a non-interactive Go tool (`scripts/release-action/`) and a rewritten
`release.yaml` workflow. Release managers trigger releases from the
GitHub Actions UI by selecting a branch, picking a release type (`rc`,
`release`, or `create-release-branch`), and optionally providing a
commit SHA.

The Go tool has four subcommands: `calculate-version` (computes next
version from git state), `generate-notes` (release notes from commit log
and PR metadata), `publish` (creates GitHub release with checksums), and
the workflow handles tag creation, branch creation, building, and
downstream publishing.

`scripts/version.sh` fallback now uses `git describe` (nearest ancestor
tag) instead of global latest so dev builds on release branches show the
correct version series.
2026-06-04 14:38:48 -04:00
Garrett Delfosse 2cbce86eee chore: update install docs for v2.34.0 release (#26058)
Updates the install docs for the v2.34.0 release, branched off the
latest `main`.

Supersedes #25995: same release-docs update, but cut from current `main`
and with every "Latest Release" link refreshed. The automated PR carried
stale patch links and a `vv2.34.0` typo.

## Changes

- `docs/install/releases/index.md`: regenerate the release calendar.
2.34 → Mainline, 2.33 → Stable, and every "Latest Release" link points
to the current patch per minor (`2.24.6, 2.29.16, 2.30.9, 2.31.14,
2.32.5, 2.33.6, 2.34.0`).
- `docs/install/rancher.md`: version selector → Mainline `2.34.0`,
Stable `2.33.6`.
- `docs/install/kubernetes.md`: Helm `--version` → Mainline `2.34.0`,
Stable `2.33.6` (chart + OCI), matching the Rancher guide.

Addresses the review feedback on #25995: the `vv2.34.0` typo, bumping
Stable to `2.33.6`, and keeping the Kubernetes guide in sync with
Rancher.

<details>
<summary>Notes for reviewers</summary>

- Verified with `markdownlint-cli2` (0 errors) and
`markdown-table-formatter --check` (no reformatting needed).
- The calendar was regenerated via `scripts/update-release-calendar.sh`.
That script's `get_latest_patch` does not exclude prerelease tags, so it
selected `v2.34.0-rc.0` over `v2.34.0`; that row was corrected by hand.
A follow-up fix to the script would prevent this recurring.
- The linkspector 404 on `coder.com/changelog/coder-2-34` is expected
for a fresh release; that page publishes alongside the release.

</details>

---
*Generated by Coder Agents on behalf of @f0ssel.*
2026-06-04 12:46:23 +00:00
Cian Johnston 8b058dc949 feat: add coderd_api_websocket_probes_total metric (#25012)
Relates to CODAGT-115

Adds metric `coderd_api_websocket_probes_total`. Every successful
heartbeat for a given path will increment the metric.

Comparing this with `coderd_api_concurrent_websockets` will give an
indication of how many websocket connections are open but in a 'wedged'
state (when heartbeats stopped versus when we closed the connection).
2026-06-03 10:46:07 +01:00
Thomas Kosiewski fe257666d7 ci: refactor CI to use mise for shared tool setup (#25727) 2026-06-01 15:55:19 +02:00
Dean Sheather 9c111a2be2 chore: disable release freezing on dev.coder.com (#25881) 2026-05-31 13:36:05 +00:00
Danny Kopping 12520ee964 feat: add ai provider status and reload freshness metrics (#25770)
Add metrics for `aibridged` and `aibridgeproxyd`'s provider statuses. AI providers can be modified, and possibly misconfigured, at runtime. These metrics help operators understand the state of these provider definitions in case unexpected behaviour is observed.
2026-05-28 14:57:33 +02:00
Mathias Fredriksson 3770176b7f fix(scripts): use merge-base in emdash lint to avoid false positives (#25726)
When GITHUB_BASE_REF is set, the emdash lint compared against the tip
of main instead of the merge-base. For PRs behind main, this produced
a diff covering all divergent files, flagging pre-existing emdashes the
PR never touched.

Query the PR commit count via gh, deepen HEAD by that amount, and
resolve HEAD~N as the merge-base. Falls back to the branch tip when
the merge-base cannot be determined.
2026-05-28 13:45:01 +03:00
blinkagent[bot]andblink-so[bot] 1bfc1ce2c4 chore: update terraform to v1.15.5 (#25746)
Bumps bundled Terraform from `1.15.2` to `1.15.5` across all pinned
locations:

- `.github/actions/setup-tf/action.yaml`
- `scripts/Dockerfile.base`
- `install.sh`
- `flake.nix` (+ updated SRI hash for the linux_amd64 zip)
- `mise.toml`
- `mise.lock` (+ updated per-platform SHA256 checksums)
- `provisioner/terraform/testdata/version.txt`
-
`provisioner/terraform/testdata/resources/ai-tasks-disabled/ai-tasks-disabled.tfplan.json`

## Why

Terraform 1.15.5 is built with Go 1.25.10, while the 1.15.2 we currently
ship was built with Go 1.25.8. The newer Go runtime addresses recent
stdlib CVEs flagged by security scanners.

Releases included: 1.15.3 (provider install crash fix, nested-module
stack migration fix), 1.15.4 (Linux s390x builds, symlinked provider dir
fix), 1.15.5.

Release notes:
https://github.com/hashicorp/terraform/releases/tag/v1.15.5

## Cherry-pick

#25747 mirrors this PR against `release/2.34`.

Created on behalf of @Shelnutt2

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-05-27 16:46:25 -04:00
Thomas KosiewskiandClaude Opus 4.7 51836e681e refactor: build dogfood image as base + mise oci layers (#25448)
Splits the dogfood image into two artifacts:

- `ghcr.io/coder/oss-dogfood-base:<distro>-<base-sha>`: Ubuntu base with
apt packages, chrome, rustup, brew, gh, and the mise binary. The
base-sha is a cache key over `Dockerfile.base` and `files/`, so commits
that don't touch those inputs reuse the previous build.
- `codercom/oss-dogfood:<final-sha>-<distro>` and rolling tags
(`:22.04`, `:26.04`, `:latest`, `:<branch>`): produced by `mise oci
build` on top of the base, with one content-addressed OCI layer per mise
tool. The rolling tag scheme is unchanged, so the workspace template
doesn't need updating.

Single-tool version bumps now invalidate only that tool's OCI layer, so
workspaces re-pull just what changed instead of the entire 5-6 GB image
on every recreate.

Also:

- Drops the build-time `pnpm dlx playwright@1.47.0 install --with-deps
chromium` step (~400 MB) and the equivalent `playwright-driver.browsers`
install from `flake.nix`. `@playwright/mcp` (used by the claude-code and
codex MCP servers in `dogfood/coder/main.tf`) does NOT auto-install
browsers, so the existing `install-deps` `coder_script` now runs two
installs on workspace start: `pnpm exec playwright install chromium` for
the site's pinned `@playwright/test`, and `npx
--package=@playwright/mcp@latest playwright-core install --no-shell
chromium` so the MCP servers find their matching browser revision.
Browser revisions coexist under
`~/.cache/ms-playwright/chromium-<rev>/`, which lives on the home volume
so both downloads happen once per workspace recreate and persist across
restarts. Net effect: same MCP behavior as before, +~1-2 min on first
workspace start. Nix devshell users running site e2e tests locally now
need `pnpm exec playwright install` once (instead of getting browsers
via nixpkgs).
- Bumps the pinned mise binary to v2026.5.12 (matching main after
#25521) and adds top-level `min_version = "2026.5.12"` to `mise.toml` so
every consumer (devs, CI, the embedded mise inside the dogfood image,
mise oci builds) fails fast on an older mise.
- Adds bison, flex, libicu-dev, libreadline-dev, uuid-dev, and
zlib1g-dev to both Ubuntu base images for source-build use cases (e.g.,
building Postgres from source).
- Replaces skopeo with crane as the registry client `mise oci push`
shells out to: crane is added to `mise.toml`, the workflow drops its
`apt-get install skopeo` and forces `--tool crane`, and the local
wrapper image stops bundling skopeo. One source of truth for tool
versions, no apt drift, smaller wrapper image, and workspace users get a
registry client on PATH for free via mise oci's tool layers.
- Removes `nix.hash`/`mise.hash` and their Makefile rules. The registry
digest already captures every effective change since CI rebuilds when
any baked-in input moves; the per-file `filesha1()` entries in
`pull_triggers` are redundant.

Supersedes #25400 (the `mise.hash` pull trigger landed there in
`2b612abe7b`; this PR removes it as part of the broader simplification).

> [!NOTE]
> `mise oci build` is experimental and requires `MISE_EXPERIMENTAL=1`
(set at job level in the workflow). The local-only
`scripts/dogfood/mise-oci-wrapper.sh` builds a tiny
`coderdev/mise-oci-wrapper:<version>` Debian image with curl-installed
mise on first invocation (cached by version tag thereafter); we don't
reuse `jdxcode/mise:latest` because that tag lags upstream GitHub
releases by days and would defeat the `min_version` enforcement above.

> [!NOTE]
> `compute-base-sha.sh` and `compute-final-sha.sh` are cache keys, not
strict content addresses: the base Dockerfile still pulls dynamic
resources at build time (gh/buildx `releases/latest`, chrome
`stable_current_amd64.deb`, apt mirror state). Two runs with identical
checked-in files can produce slightly different bytes, which is
acceptable here because the cache-hit savings on irrelevant commits
outweigh that drift.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 14:52:21 +02:00
Cian Johnston 0a45f96d30 ci: validate dogfood image tooling by running gen, fmt, lint, build (#25475)
Adds a `test_image` job that runs `make gen`, `make fmt`, `make lint`, and `make build` inside the
newly built image via `docker run`. This helps detect breaking changes before merge. 

> [!NOTE]
> Generated with [Coder Agents](https://coder.com/agents)
2026-05-25 17:02:13 +01:00
Cian Johnston a4afb9dfc6 feat: add --env-file flag to develop.sh (#25621)
Adds `--env-file` to `scripts/develop.sh` to allow reading environment 
from a given file. This makes it easier to configure things like external 
auth providers, access URLs, and other dev-time settings without 
exporting a wall of environment variables in every shell session.

> Generated with [Coder Agents](https://coder.com/agents)
2026-05-25 11:54:57 +01:00
Michael Suchacz ca1f6b19a2 feat: remove legacy chat provider tables (#25416) 2026-05-22 09:50:01 +02:00
Spike Curtis 8dc4d76890 chore: add agent-connection-watch for workspaces (#24507)
<!--

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.

-->

relates to GRU-18  
  
Adds basic implementation for Workspace Agent Connection Watch and tests.  
  
Missing are handling of logs.
2026-05-20 13:09:11 -04:00
Steven Masley 19a1fa5c13 chore: disable access url to get a try.coder.app in dev (#25510) 2026-05-20 08:49:23 -05:00
Thomas KosiewskiandClaude Opus 4.7 5f9b3220b5 chore: install dogfood image tooling via mise.toml (#25282)
This PR replaces the hand-rolled `curl | tar | go install | cargo
install` chains in the dogfood Ubuntu 22.04 and 26.04 Dockerfiles with a
single `mise install` driven by a new repo-root `mise.toml`.

The previous Dockerfiles installed ~25 CLIs across three multi-stage
builds with versions hardcoded inline. Version bumps were scattered
across the Dockerfiles, the root `mise.toml` (added in #24618 but
otherwise unused at runtime), and CI's setup actions; build-time network
failures came from a dozen distinct endpoints; and `mise` itself sat in
the image with no manifest to install from.

The new flow:

- The repo's `mise.toml` is the single source of truth for image tool
versions. The Dockerfiles `COPY` it to `/etc/mise/config.toml` and run a
single `mise install` as the `coder` user.
- Tools are installed into `/opt/mise/data` rather than the default
`/home/coder/.local/share/mise`, so they live in the image (not on the
persistent home volume) and reach every workspace on recreate.
- Build context moves to the repo root so the Dockerfile can `COPY
mise.toml`; an allowlist `.dockerignore` keeps the transferred context
to ~24 kB.
- Optional `--secret id=github_token` plumbing through the Makefile and
`.github/workflows/dogfood.yaml` lifts aqua's GitHub API quota from
60/hr unauthenticated to 1000/hr with `secrets.GITHUB_TOKEN`.
- `MISE_TRUSTED_CONFIG_PATHS=/home/coder:/etc/mise` is set as an ENV so
users who clone the coder repo into their workspace home aren't prompted
to `mise trust`.

Net diff for the two Ubuntu Dockerfiles: -399 / +244 lines (~200 lines
shorter each). The `FROM rust-utils`, `FROM go`, and `FROM proto`
multi-stage builds are gone; so are the NVM/Node block, the bulk
binary-install block (golangci-lint, helm, kubectx, syft, cosign, bun),
the gh `.deb`/lazygit/doctl tarball installs, the gofmt
`update-alternatives` line, and the `yq`→`yq4` rename
(`scripts/lib.sh:267-275` already auto-detects either name).

Both images were built and smoke-tested with Apple's `container` CLI on
macOS — every migrated tool resolves to the expected pinned version
including outside the cloned coder repo (e.g. `gh` from `/home/coder`,
matching the workspace startup script in `dogfood/coder/main.tf`),
`sqlc` runs (proving `CGO_ENABLED=1` was honoured at install), `yq
--version` reports v4 for `scripts/lib.sh`'s detection, and `gofmt`
resolves via the mise shim.

Follow-ups (out of scope here):

- Commit a multi-platform `mise.lock` so `gh = "latest"` and the other
floating versions resolve deterministically across rebuilds and dev
machines.
- Migrate CI's `setup-go` / `setup-node` actions to consume `mise.toml`
so image and CI versions stop being able to drift.

---------

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:36:22 +02:00
Garrett Delfosse d97f5ae2a6 fix: add ESR support to release calendar script (#25205)
The `update-release-calendar.sh` script did not account for Extended
Support Release (ESR) versions. Running it would drop ESR entries (e.g.
2.24) from the calendar entirely or mark them as "Not Supported" instead
of "Extended Support Release".

## Changes

- Add `ESR_VERSIONS` array for tracking active ESR minor versions
- Add `is_esr_version()` helper to check ESR membership
- Extract `generate_release_row()` to reduce duplication
- Prepend ESR versions older than the standard window
- Override "Not Supported" status for ESR versions within the window

> [!NOTE]
> When new ESR versions are designated or old ones reach end of life,
update the `ESR_VERSIONS` array at the top of the script.

<!-- This PR was authored by Coder Agents -->
2026-05-14 15:35:30 -04:00
Seth Shelnutt 8eb7051987 fix(scripts/ironbank): update base image to UBI9 and remove urllib3 (CVE-2026-44431) (#25217)
The IronBank Dockerfile used UBI8-minimal:8.7 as its base image.
IronBank has migrated images to UBI9 base, and the bundled urllib3
1.26.5 in the image triggers CVE-2026-44431 (sensitive headers leaked on
cross-origin redirects via the low-level API).

This updates the base image from UBI8-minimal to UBI9-minimal and
explicitly removes python3-urllib3 after package installation. Coder is
a Go binary and does not invoke Python at runtime, so urllib3 is unused.

Refs
[ENT-4](https://linear.app/codercom/issue/ENT-4/ironbank-v23111-update-urllib3-from-1265-to-fix-cve-2026-44431),
[ENT-51](https://linear.app/codercom/issue/ENT-51/ironbank-main-update-base-image-urllib3-cve-2026-44431),
[CVE-2026-44431](https://nvd.nist.gov/vuln/detail/CVE-2026-44431)

> Generated by Coder Agents

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

- **Base image**: Moved from `ubi8-minimal:8.7` to `ubi9-minimal:9.6` to
align with IronBank's UBI9 migration and reduce overall vulnerability
surface.
- **urllib3 removal**: Added explicit `microdnf remove python3-urllib3`
with error suppression (`|| true`) so the build succeeds whether or not
the package is present in the base image. This handles both the minimal
and full UBI9 base image variants that IronBank may use.
- **Crypto policies**: RHEL 9 uses the same
`/etc/crypto-policies/back-ends/*.config` paths as RHEL 8; no changes
needed.
- **Build script**: Updated the `registry.access.redhat.com` override
from `ubi8/ubi-minimal:8.7` to `ubi9/ubi-minimal:9.6` for local builds.

</details>
2026-05-13 10:41:56 -04:00
Garrett DelfosseandZach 566dace1bc fix(scripts/releaser): use last stable release as changelog base for .0 releases (#24988)
When releasing a `.0` version (e.g. `v2.33.0`) from a release branch,
the release notes diff was comparing against the most recent RC (e.g.
`v2.33.0-rc.3`) instead of the last stable release from the previous
minor series (e.g. `v2.32.X`).

## The bug

`prevVersion` is set to the latest tag matching the branch's
`major.minor` from merged tags. For a `.0` release, this is the latest
RC (e.g. `v2.33.0-rc.3`). The commit range for release notes then
becomes `v2.33.0-rc.3..HEAD` instead of `v2.32.X..HEAD`, so the notes
only show the delta from the last RC rather than all changes since the
previous real release. The compare link also points to
`v2.33.0-rc.3...v2.33.0`.

## The fix

After all semver sanity checks have run (so version suggestion and
validation are unaffected), when the new version is a `.0` release and
`prevVersion` is an RC, override `prevVersion` with the last stable
release from the previous minor series. This makes both the commit range
and compare link use the correct base (e.g. `v2.32.X..HEAD` and
`v2.32.X...v2.33.0`).

> Generated with [Coder Agents](https://coder.com/agents)

---------

Co-authored-by: Zach <3724288+zedkipp@users.noreply.github.com>
2026-05-11 22:18:09 +00:00
Michael Suchacz bb8c40e764 feat: stream go test failure summary and drop raw json artifact (#25146)
This follows up on
https://github.com/coder/coder/actions/runs/25684936801/job/75406131184?pr=25139
by replacing the large raw Go test JSON artifact with inline structured
summaries and a compact failures-only artifact.

## What changed

- Added `scripts/gotestsummary`, a streaming Go tool that reads
gotestsum JSON and renders failed tests as Markdown.
- Updated the three Go test jobs to publish per-test `<details>`
sections in the job summary.
- Removed upload of the raw `go-test.json` artifact.
- Added upload of `go-test-failures-*.ndjson` with compact failure
records for deeper inspection.
- Deleted the old bash and `jq` summary script.

## Why

- The previous raw artifact was about 35 MB compressed and 445 MB raw in
the linked run.
- Passing-test output made the artifact noisy and slow to inspect.
- The old summary truncated output to 600 characters.
- The new path keeps streaming, bounded output and writes structured
diagnostics for only final failed tests.

## Validation

- `gofmt -w scripts/gotestsummary`
- `gofmt -l scripts/gotestsummary`
- `go test ./scripts/gotestsummary/...`
- `go vet ./scripts/gotestsummary/...`
- `grep -rn 'go-test-failure-summary.sh' . || true`
- `grep -rn 'go-test-failure-summary.sh\|go-test.json\|go-test-json-'
.claude .agents docs AGENTS.md || true`
- `make lint/agents`
- `make lint/emdash`
- `make lint/markdown`
- `make lint/shellcheck`
- `git diff --check origin/main..HEAD`

> This PR was prepared by Mux working on Mike's behalf.
2026-05-12 00:08:37 +02:00
J. Scott Miller 3e46c7986f feat: event driven agent connection metric (#24355)
Moves the `coderd_agents_first_connection_seconds` histogram from the
polling-based `prometheusmetrics.Agents()` loop to the event-driven
`agentConnectionMonitor.init()` path. The metric is now recorded exactly
once when an agent first connects over the RPC websocket, instead of
being retroactively computed each polling tick.

The `username` and `workspace_name` labels are removed to reduce
cardinality; only `template_name` and `agent_name` are retained.

Adds unit tests covering both the happy path (first connection recorded)
and the negative-duration guard (clock skew logs a warning, no sample
emitted).
2026-05-11 14:27:40 -05:00
Cian Johnston e8508b2d90 fix: recover chatd from poisoned chain anchor on retry (#25097)
When OpenAI's Responses API returns `Previous response with id ... not
found` for a chained turn, classify it as a `ChainBroken` retry, clear
`previous_response_id`, exit chain mode, reload full history, and let
`chatretry` retry. Self-heals chats whose anchor was poisoned before
#25074 stopped truncated streams from being persisted as a successful
turn with a stored response id.

The new state is exposed via the existing
`coderd_chatd_stream_retries_total` counter as a
`chain_broken="true"|"false"` label. Aggregating queries (`sum`, `rate`
over `provider`/`model`/`kind`) keep working without changes; raw-series
matchers without aggregation will now see two series per `(provider,
model, kind)` where they previously saw one. The metric is internal-only
so the blast radius should be small, but if you have dashboards that
index by exact label matchers without aggregation they will need an
extra `sum` or an explicit `chain_broken` selector.

> 🤖 This PR was created with the help of Coder Agents, and was reviewed by a human 🧑‍💻
2026-05-11 17:43:40 +01:00
Michael Suchacz 85792d08bc feat: add harness engineering layer for agent workflows (#24791)
This PR adds an opinionated harness-engineering layer for agent-driven
workflows: a small set of agent-readable docs, mechanical structure
checks, structured CI failure summaries, an architecture-lint umbrella,
and per-worktree dev-server isolation. The goal is to make local dev,
tests, and CI mechanically inspectable by agents without changing app
runtime behavior.

## What landed

**Agent docs and navigation**
- `.claude/docs/OBSERVABILITY.md`, `.claude/docs/DEV_ISOLATION.md`,
`.claude/docs/AGENT_FAILURES.md`: task-oriented guides for logs,
tracing, Prometheus, dev-server isolation, and a seeded failure catalog.
- `AGENTS.md`: added an `Agent navigation` block, then trimmed the file
from 375 to 229 lines by migrating duplicated detail into
`WORKFLOWS.md`, `GO.md`, `TESTING.md`, and `DATABASE.md`. The
user-managed custom-instructions block is preserved.
- `.agents/docs`: symlink mirror of `.claude/docs` for agent runtimes
that look under `.agents`.

**Mechanical checks**
- `scripts/check_agents_structure.sh`: validates `@...` references in
tracked `AGENTS.md` files and warns when root grows past 600 lines.
Wired as `make lint/agents` and into `make lint`.
- `scripts/audit-agent-readiness.sh`: report-first audit of harness
readiness. Currently `10 ok, 0 warn, 0 fail`.
- `scripts/check_architecture.sh` / `make lint/architecture`: umbrella
architecture-lint target. Consolidates the existing
`check_enterprise_imports.sh` and `check_codersdk_imports.sh` so they
run exactly once via the umbrella. Slot is open for new high-confidence
rules.

**Structured CI failure summaries**
- `scripts/playwright-failure-summary.sh`: parses
`site/test-results/results.json` and writes Markdown to
`$GITHUB_STEP_SUMMARY` on failure. Wired into the `test-e2e` matrix job.
- `scripts/go-test-failure-summary.sh`: parses `go test -json`
line-delimited output the same way. Wired into `test-go-pg`,
`test-go-pg-17`, and `test-go-race-pg` by injecting `gotestsum
--jsonfile` in the workflow without touching `Makefile`. JSON also
uploaded as a CI artifact on failure.
- `site/e2e/playwright.config.ts`: enables `screenshot:
only-on-failure`, `trace: retain-on-failure`, JSON reporter, and HTML
reporter alongside existing reporters.
- `.github/workflows/ci.yaml`: failure artifact uploads for Playwright
now use `if: failure()` and predictable names
(`playwright-artifacts-<variant>-<sha>`).

**Per-worktree dev-server isolation** (`scripts/develop/main.go`)
- Deterministic FNV-64a hash of the worktree path produces a port offset
in `[0, 1000)` (50 buckets, step 20 to avoid API/proxy overlap across
adjacent buckets).
- Offset is applied only to defaults; both env vars (`CODER_DEV_PORT`,
`CODER_DEV_WEB_PORT`, `CODER_DEV_PROXY_PORT`,
`CODER_DEV_PROMETHEUS_PORT`) and CLI flags retain priority.
- Hardcoded ports `9090` (embedded Prometheus UI) and `12345` (Delve)
are unchanged by design.
- Startup banner shows each port's source: `default`, `offset`, or
`explicit`.
- Unit tests in `scripts/develop/main_test.go` cover determinism,
bounds, no-overlap across the four ports, and explicit-skip behavior.
- State (`.coderv2/`) was already worktree-isolated via `os.Getwd()`, so
no state-dir changes were needed.

## Validation

`make lint/agents`, `make lint/architecture`, `make lint/emdash`, `bash
scripts/audit-agent-readiness.sh` (10 ok, 0 warn, 0 fail), `shellcheck`
on all 5 new scripts, `go test ./scripts/develop/...`, and `js-yaml`
parse of `ci.yaml` all pass. Synthetic fixtures verify both
failure-summary scripts handle empty/missing input (silent exit 0),
ANSI-stripped output, and parent/subtest formatting.

## Known follow-ups (deferred)

- Frontend Storybook/Vitest failure summary: lowest-leverage slice of
the failure-summary work. Skipping until observed pain.
- Architecture lint currently only delegates to existing import checks;
new rules (`InTx` outer-store detection, swagger-annotation lint) plug
in as needed.
- 50 port-offset buckets means two worktree paths can occasionally
collide. The DEV_ISOLATION doc tells users to set the relevant env var
when this happens.

> Mux opened this PR on Mike's behalf.
2026-05-11 17:27:29 +02:00
Yevhenii Shcherbina 4124d1137d feat: add ai_model_prices table (#24932)
# Summary

Implements
https://linear.app/codercom/issue/AIGOV-282/add-ai-model-price-table-and-seed-generator

This PR lays the groundwork for AI Bridge cost controls (per the AI
Governance RFC). It adds the foundation needed for future cost tracking:
a place to store per-model token prices, a way to keep those prices in
sync with upstream pricing data, and a startup mechanism that ensures
every deployment has prices loaded before AI Bridge starts processing
requests.

The price data comes from [models.dev](https://models.dev/), a
community-maintained catalogue of AI provider pricing. A generator
script fetches the latest prices, filters to Anthropic and OpenAI for
now, and produces a seed file checked into the repository.

On every server startup the seed is applied to the database, so new
releases automatically pick up any price corrections that landed since
the previous one. Existing rows are overwritten with the latest prices;
rows for models no longer in the seed are left untouched.

# Batching the AI model price seed: three approaches

Context: at server startup we seed the `ai_model_prices` table from an
embedded JSON price book (~70 rows today, will grow as we add providers,
potentially 4000+).

Each row is:

```text
(provider, model, input_price, output_price, cache_read_price, cache_write_price)
```

Any of the four price columns can be:

- `NULL` → “price unknown for this dimension”
- explicit `0` → “free”

The batch must be an UPSERT so re-running is idempotent and existing
rows pick up new prices.

We considered three implementations.

---

## Approach 1 — Per-row UPSERT in a Go loop

```go
for _, row := range rows {
    if err := db.UpsertAIModelPrice(ctx, database.UpsertAIModelPriceParams{
        Provider:   row.Provider,
        Model:      row.Model,
        InputPrice: nullInt64(row.InputPrice),
        // ...
    }); err != nil {
        return err
    }
}
```

### Pros

- Trivial.
- NULL handling falls out naturally from `sql.NullInt64`.

### Cons

- `N` round-trips per seed.
- With ~70 rows that means ~70 statement executions on every startup,
even inside a transaction.
- Doesn't scale gracefully as the price book grows, potentially 4000+.

---

## Approach 2 — `UNNEST` with parallel arrays

Pass each column as a separate Go slice. Postgres unnests them in
parallel into a virtual table, then `INSERT ... SELECT`.

```sql
INSERT INTO ai_model_prices (
    provider,
    model,
    input_price,
    output_price,
    cache_read_price,
    cache_write_price
)
SELECT
    UNNEST(@providers::text[]),
    UNNEST(@models::text[]),
    NULLIF(UNNEST(@input_prices::bigint[]), -1),
    NULLIF(UNNEST(@output_prices::bigint[]), -1),
    NULLIF(UNNEST(@cache_read_prices::bigint[]), -1),
    NULLIF(UNNEST(@cache_write_prices::bigint[]), -1)
ON CONFLICT (provider, model) DO UPDATE SET
    input_price       = EXCLUDED.input_price,
    output_price      = EXCLUDED.output_price,
    cache_read_price  = EXCLUDED.cache_read_price,
    cache_write_price = EXCLUDED.cache_write_price,
    updated_at        = NOW();
```

Go side: flatten rows into six parallel slices.

Use a sentinel (`-1`) for “missing”, since `lib/pq` can't encode `NULL`
into a `bigint[]` element.

```go
providers := make([]string, len(rows))
models    := make([]string, len(rows))
inputs    := make([]int64,  len(rows))
outputs   := make([]int64,  len(rows))
cacheR    := make([]int64,  len(rows))
cacheW    := make([]int64,  len(rows))

for i, r := range rows {
    providers[i] = r.Provider
    models[i]    = r.Model

    inputs[i] = -1
    if r.InputPrice != nil {
        inputs[i] = *r.InputPrice
    }

    outputs[i] = -1
    if r.OutputPrice != nil {
        outputs[i] = *r.OutputPrice
    }

    cacheR[i] = -1
    if r.CacheReadPrice != nil {
        cacheR[i] = *r.CacheReadPrice
    }

    cacheW[i] = -1
    if r.CacheWritePrice != nil {
        cacheW[i] = *r.CacheWritePrice
    }
}

return db.UpsertAIModelPrices(ctx, database.UpsertAIModelPricesParams{
    Providers:        providers,
    Models:           models,
    InputPrices:      inputs,
    OutputPrices:     outputs,
    CacheReadPrices:  cacheR,
    CacheWritePrices: cacheW,
})
```

### Pros

- Single round-trip.

### Cons

- The generated `sqlc` params become plain `[]int64`, which can't
represent `NULL`.

---

## Approach 3 — `jsonb_array_elements` over a single `@seed::jsonb`
(chosen)

Pass the raw seed JSON as one parameter; let Postgres expand and parse
it.

```sql
INSERT INTO ai_model_prices (
    provider,
    model,
    input_price,
    output_price,
    cache_read_price,
    cache_write_price
)
SELECT
    elem->>'provider',
    elem->>'model',
    (elem->>'input_price')::bigint,
    (elem->>'output_price')::bigint,
    (elem->>'cache_read_price')::bigint,
    (elem->>'cache_write_price')::bigint
FROM jsonb_array_elements(@seed::jsonb) AS elem
ON CONFLICT (provider, model) DO UPDATE SET
    input_price       = EXCLUDED.input_price,
    output_price      = EXCLUDED.output_price,
    cache_read_price  = EXCLUDED.cache_read_price,
    cache_write_price = EXCLUDED.cache_write_price,
    updated_at        = NOW();
```

Go side reduces to:

```go
return db.UpsertAIModelPrices(ctx, seedJSON)
```

### Pros

- Single round-trip.
- NULLs fall out naturally:
  - `(elem->>'cache_write_price')::bigint` becomes `NULL`
  - no sentinels
- The seed is already JSON:
- Existing precedent:
  - `jsonb_array_elements` is already used elsewhere in the codebase

### Cons

- Less type-safe at the SQL boundary than `UNNEST`
- Slightly less standard than `UNNEST`
- Readers need familiarity with:
  - `jsonb_array_elements`
  - `->>` extraction syntax
- Postgres pays JSON parse cost
  - negligible at our scale

---

---

# Decision

We picked Approach 3.

It collapses the round-trips like `UNNEST` does, but without:

- nullable-array workarounds
- sentinel values
2026-05-08 16:45:14 -04:00
Jon Ayers 400374992c fix: add pnpm overrides for vulnerable transitive dependencies (#25064) 2026-05-07 15:11:32 -05:00
Jon Ayers eef09f3d98 chore: update terraform to v1.15.2 (#25045) 2026-05-07 11:07:19 -05:00
david-fraley e7360da974 docs: generate Chats API docs from swagger annotations (#24830) 2026-05-05 18:52:54 +00:00
Garrett Delfosse a8222e02e5 fix(scripts/releaser): fix tag sorting and changelog blurb for older branches (#24798)
Fixes two bugs in the release tool.

## 1. RC tags chosen over release tags on release branches

`allSemverTags()` and `mergedSemverTags()` rely on `git tag
--sort=-v:refname` for ordering. Git's version sort treats pre-release
suffixes (e.g. `-rc.0`) as *greater* than the base release version,
which is the opposite of semver where `v2.32.0 > v2.32.0-rc.0`.

When the release branch code iterates the tag list looking for the first
matching `major.minor`, it finds the RC tag first, leading to incorrect
version suggestions (e.g. suggesting `v2.32.0` again instead of
`v2.32.1`).

**Fix:** Re-sort parsed tags using the existing `GreaterThan` method via
a new `sortVersionsDesc` helper.

## 2. Misleading mainline changelog blurb on ESR/older branch patches

When releasing a patch on an older branch (e.g. `release/2.29` for ESR),
the version is neither mainline nor stable. Declining the stable prompt
would always produce the mainline changelog note ("This is a mainline
Coder release..."), which is incorrect.

**Fix:** Only emit the mainline note when the version's minor matches
the current mainline series. For older branches the changelog omits the
note entirely.

> Generated by Coder Agents
2026-05-01 14:41:09 -04:00