Commit Graph

2152 Commits

Author SHA1 Message Date
Kyle Carberry edee917d88 feat: add experimental agents support (#22290)
feat: add AI chat system with agent tools and chat UI

Introduce the chatd subsystem and Agents UI for AI-powered chat
within Coder workspaces.

- Add chatd package with chat loop, message compaction, prompt
  management, and LLM provider integration (OpenAI, Anthropic)
- Add agent tools: create workspace, list/read templates, read/write/
  edit files, execute commands
- Add chat API endpoints with streaming, message editing, and
  durable reconnection
- Add database schema and migrations for chats, chat messages, chat
  providers, and chat model configs
- Add RBAC policies and dbauthz enforcement for chat resources
- Add Agents UI pages with conversation timeline, queued messages
  list, diff viewer, and model configuration panel
- Add comprehensive test coverage including coderd integration tests,
  chatd unit tests, and Storybook stories
- Gate feature behind experiments flag

---------

Co-authored-by: Cian Johnston <cian@coder.com>
Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
Co-authored-by: Jeremy Ruppel <jeremy@coder.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:50:56 +00:00
Paweł Banaszewski 6c097797a1 feat: add Mux icon to client column in AI Bridge request log page (#22386)
Adds Mux to the recognized clients list in AI Bridge documentation.

Adds Mux icon to AI Bridge requests log page:
<img width="1886" height="848" alt="image"
src="https://github.com/user-attachments/assets/e7cb8d47-595c-4be3-93c9-00dbea3d1153"
/>
2026-02-27 16:13:39 +00:00
Steven Masley 21bc185254 doc: add language to mention disruptive nature of cookie host prefix (#22384) 2026-02-27 15:59:01 +00:00
Susana Ferreira ca234f346d fix: mark presets as validation_failed to prevent endless prebuild retries (#22085)
## Description

- Updates `wsbuilder` to return a `BuildError` with
`http.StatusBadRequest` to signify a "validation error" on missing or
invalid parameters
- Adds a short-circuit in `prebuilds.StoreReconciler` to mark presets
for which creating a build returns a "validation error" as "validation
failed" and skip further attempts to reconcile.
- Adds a test to verify the above
- Introduces a new Prometheus metric
`coderd_prebuilt_workspaces_preset_validation_failed` to track the above

Closes: https://github.com/coder/coder/issues/21237

---------

Co-authored-by: Cian Johnston <cian@coder.com>
2026-02-27 14:26:48 +00:00
blinkagent[bot] 24ab5205d2 docs: add AI Bridge structured logging section to setup page (#22361)
Adds a brief "Structured Logging" section to the [AI Bridge
Setup](https://coder.com/docs/ai-coder/ai-bridge/setup) page documenting
the `--aibridge-structured-logging` /
`CODER_AIBRIDGE_STRUCTURED_LOGGING` flag.

Covers:
- How to enable structured logging (CLI flag, env var, YAML)
- The five `record_type` values emitted (`interception_start`,
`interception_end`, `token_usage`, `prompt_usage`, `tool_usage`) and
their key fields
- How to filter for these records in a logging pipeline

Created on behalf of @dannykopping

---------

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-27 10:40:59 +01:00
Jake Howell d2787df442 feat: add AI Bridge request logs model filter (#22230)
This pull-request implements a simple filtering logic so that we're able
to pick which model the user actually used when logs were sent to AI
Bridge.

- Add `GET /aibridge/models` API endpoint that returns distinct model
names from AI Bridge interceptions, with pagination and search support
- New `ListAIBridgeModels` SQL query using case-sensitive prefix
matching (`LIKE model || '%'`) to allow B-tree index usage
- Hand-written `ListAuthorizedAIBridgeModels` in `modelqueries.go` for
RBAC authorization filter injection
- `AIBridgeModels` search query parser in searchquery/search.go
(defaults bare terms to the `model` field)
- dbauthz wrappers, dbmetrics, and dbmock implementations for the new
query

<img width="292" height="185" alt="image"
src="https://github.com/user-attachments/assets/134771df-2d26-4c54-acc4-27f58128b351"
/>
2026-02-26 02:40:45 +11:00
Garrett Delfosse 4057363f78 fix(coderd): add organization_name label to insights Prometheus metrics (#22296)
## Description

When multiple organizations have templates with the same name, the
Prometheus `/metrics` endpoint returns HTTP 500 because Prometheus
rejects duplicate label combinations. The three `coderd_insights_*`
metrics (`coderd_insights_templates_active_users`,
`coderd_insights_applications_usage_seconds`,
`coderd_insights_parameters`) used only `template_name` as a
distinguishing label, so two templates named e.g. `"openstack-v1"` in
different orgs would produce duplicate metric series.

This adds `organization_name` as a label to all three insight metric
descriptors to disambiguate templates across organizations.

## Changes

**`coderd/prometheusmetrics/insights/metricscollector.go`**:
- Added `organization_name` label to all three metric descriptors
- Added `organizationNames` field (template ID → org name) to the
`insightsData` struct
- In `doTick`: after fetching templates, collect unique org IDs, fetch
organizations via `GetOrganizations`, and build a
template-ID-to-org-name mapping
- In `Collect()`: pass the organization name as an additional label
value in every `MustNewConstMetric` call

**`coderd/prometheusmetrics/insights/testdata/insights-metrics.json`**:
Updated golden file to include `organization_name=coder` in all metric
label keys.

Fixes #21748
2026-02-25 08:58:50 +00:00
George K 119d436071 chore(docs): add app access section to workspace sharing docs (#22281)
Path-based routing (the default for, e.g., code-server) will prevent
access in workspace sharing scenarios. This commit documents the
workaround.

Closes: https://linear.app/codercom/issue/MAN-15/bug-code-server-throws-404-for-a-shared-workspace
2026-02-24 11:29:57 -08:00
Zach 9613e41d21 chore: update boundary version (#22289)
Updating to the latest tag before the 2.31 code freeze.
2026-02-24 13:33:37 -05:00
Sushant P 20797347b4 chore: update shared workspaces beta docs to include some screenshots (#22280)
Updating the docs to include some screenshots before Shared Workspace
goes into beta!
2026-02-24 08:28:22 -08:00
Kacper Sawicki 1e274063d4 feat(coderd): filter expired API tokens server-side (#22263)
## Summary

Moves expired token filtering from client-side to server-side by adding
an `include_expired` parameter to the `GetAPIKeysByLoginType` and
`GetAPIKeysByUserID` database queries. This is more efficient for large
deployments with many expired/short-lived tokens.

## Changes

- Add `include_expired` parameter to SQL queries using `OR`
short-circuit
- Add `include_expired` query parameter to `GET
/users/{user}/keys/tokens`
- Add `IncludeExpired` field to `codersdk.TokensFilter`
- Remove client-side filtering from CLI `tokens list` command
- Add `TestTokensFilterExpired` test

Fixes coder/internal#1357
2026-02-24 15:27:03 +00:00
Jon Ayers 0a7a3da178 fix: exclude provisioner_state from workspace_build_with_user view (#22159)
The provisioner state for a workspace build was being loaded for every
long-lived agent rpc connection. Since this state can be anywhere from
kilobytes to megabytes this can gradually cause the `coderd` memory
footprint to grow over time. It's also a lot of unnecessary allocations
for every query that fetches a workspace build since only a few callers
ever actually reference the provisioner state.

This PR removes it from the returned workspace build and adds a query to
fetch the provisioner state explicitly.
2026-02-23 22:46:17 -06:00
Sushant P 37a8e61ea2 chore: move Shared Workspaces from experiments to beta (#22206)
* Removed the shared-workspaces experiment and cleaned up related
middleware
* Added beta tagging to the UI for shared workspaces
2026-02-23 08:30:32 -08:00
Thomas Kosiewski b776a14b46 fix(coderd): harden OAuth2 provider security (#22194)
## Summary

Harden the OAuth2 provider with multiple security fixes addressing
`coder/security#121` (CSRF session takeover) and converge on OAuth 2.1
compliance.

### Security Fixes

| Fix | Description | Commits |
|-----|-------------|---------|
| **CSRF on `/oauth2/authorize`** | Enforce CSRF protection on the
authorize endpoint POST (consent form submission) | `ba7d646`, `b94a64e`
|
| **Clickjacking: `frame-ancestors` CSP** | Prevent consent page from
being iframed (`Content-Security-Policy: frame-ancestors 'none'` +
`X-Frame-Options: DENY`) | `597aeb2` |
| **Exact redirect URI matching** | Changed from prefix matching to full
string exact matching per OAuth 2.1 §4.1.2.1 | `73d64b1`, `93897f1` |
| **Store & verify `redirect_uri`** | Store redirect_uri with auth code
in DB, verify at token exchange matches exactly (RFC 6749 §4.1.3) |
`50569b9`, `d7ca315` |
| **Mandatory PKCE** | Require `code_challenge` at authorization (for
`response_type=code`) + unconditional `code_verifier` verification at
token exchange | `d7ca315`, `1cda1a9` |
| **Reject implicit grant** | `response_type=token` now returns
`unsupported_response_type` error page (OAuth 2.1 removes implicit flow)
| `d7ca315`, `91b8863` |

### Changes by File

**`coderd/httpmw/csrf.go`** — Extended the CSRF `ExemptFunc` to enforce
CSRF on `/oauth2/authorize` in addition to `/api` routes. The consent
form POST is now CSRF-protected to prevent cross-site authorization code
theft.

**`site/site.go`** — Added `Content-Security-Policy: frame-ancestors
'none'` and `X-Frame-Options: DENY` headers to `RenderOAuthAllowPage`
(consent page only — does not affect the SPA/global CSP used by AI
tasks).

**`coderd/httpapi/queryparams.go`** — Changed `RedirectURL` from prefix
matching (`strings.HasPrefix(v.Path, base.Path)`) to full URI exact
matching (`v.String() != base.String()`), comparing scheme, host, path,
and query.

**`coderd/oauth2provider/authorize.go`** — Added PKCE enforcement:
`code_challenge` is required when `response_type=code` (via a
conditional check, not `RequiredNotEmpty`, so `response_type=token` can
reach the explicit rejection path). `ShowAuthorizePage` (GET) validates
`response_type` before rendering and returns a 400 error page for
unsupported types. `ProcessAuthorize` (POST) stores the `redirect_uri`
with the auth code when explicitly provided.

**`coderd/oauth2provider/tokens.go`** — PKCE verification is now
unconditional (not gated on `code_challenge` being present in DB). If
the stored code has a `redirect_uri`, the token endpoint verifies it
matches exactly — mismatch returns `errBadCode` → `invalid_grant`.
Missing `code_verifier` returns `invalid_grant`.

**`codersdk/oauth2.go`** — `OAuth2ProviderResponseTypeToken` constant
and `Valid()` acceptance are **kept** so the authorize handler can parse
`response_type=token` and return the proper `unsupported_response_type`
error rather than failing at parameter validation.

**`coderd/database/migrations/000421_*`** — Added `redirect_uri text`
column to `oauth2_provider_app_codes`.

### Design Decisions

**`state` parameter remains optional** — The plan initially required
`state` via `RequiredNotEmpty`, but this was reverted in `376a753` to
avoid breaking existing clients. The `state` is still hashed and stored
when provided (via `state_hash` column), securing clients that opt in.

**`response_type=token` kept in `Valid()`** — Removing it from `Valid()`
would cause the parameter parser to reject the request before the
authorize handler can return the proper `unsupported_response_type`
error. The constant is kept for correct error handling flow.

**CSP scoped to consent page only** — `frame-ancestors 'none'` is set
only on the OAuth consent page renderer, not globally. The SPA/global
CSP was previously changed to allow framing for AI tasks
([#18102](https://github.com/coder/coder/pull/18102)); this change does
not regress that.

### Out of Scope (follow-up PRs)

- Bearer tokens in query strings (needs internal caller audit)
- Scope enforcement on OAuth2 tokens
- Rate limiting on dynamic client registration


---

<details>
<summary>📋 Implementation Plan</summary>

# Plan: Harden OAuth2 Provider — Security Fixes + OAuth 2.1 Compliance

## Context & Why

Security issue `coder/security#121` reports a critical session takeover
via CSRF on the OAuth2 provider. This plan covers all remaining security
fixes from that issue **plus** convergence on OAuth 2.1 requirements.
The goal is a single PR that closes all actionable gaps.

## Current State (already committed on branch `csrf-sjx1`)

| Fix | Status | Commits |
|-----|--------|---------|
| Fix 1: CSRF on `/oauth2/authorize` |  Done | `ba7d646`, `b94a64e` |
| CSRF token in consent form HTML |  Done | `b94a64e` |
| `state_hash` column + storage |  Done (hash stored, but state still
optional) | `9167d83`, `b94a64e` |
| Tests for CSRF + state hash |  Done | `e4119b5` |

## Remaining Work

### ~~Fix 2 — Require `state` parameter~~ (DROPPED)

> **Decision:** Do not enforce `state` as required. The `state`
parameter is still hashed and stored when provided (via
`hashOAuth2State` / `state_hash` column from prior commits), but clients
are not forced to supply it. This avoids breaking existing integrations
that omit state.

**Rollback:** Remove `"state"` from the `RequiredNotEmpty` call in
`coderd/oauth2provider/authorize.go:42`:

```go
// BEFORE (current on branch)
p.RequiredNotEmpty("response_type", "client_id", "state", "code_challenge")

// AFTER
p.RequiredNotEmpty("response_type", "client_id", "code_challenge")
```

No test changes needed — tests already pass `state` voluntarily.

### Fix 4 — Exact redirect URI matching

Currently `coderd/httpapi/queryparams.go:233` uses prefix matching:

```go
// CURRENT — prefix match
if v.Host != base.Host || !strings.HasPrefix(v.Path, base.Path) {
```

OAuth 2.1 requires **exact string matching**. Change to:

```go
// AFTER — exact match (OAuth 2.1 §4.1.2.1)
if v.Host != base.Host || v.Path != base.Path {
```

**File: `coderd/httpapi/queryparams.go` — `RedirectURL` method**

Also update the error message from "must be a subset of" to "must
exactly match".

**Additionally**, store `redirect_uri` with the auth code and verify at
the token endpoint (RFC 6749 §4.1.3):

1. **New migration** (same migration file or a new `000421`): Add
`redirect_uri text` column to `oauth2_provider_app_codes`
2. **Update INSERT query** in `coderd/database/queries/oauth2.sql` to
include `redirect_uri`
3. **`coderd/oauth2provider/authorize.go`**: Store
`params.redirectURL.String()` when inserting the code
4. **`coderd/oauth2provider/tokens.go`**: After retrieving the code from
DB, verify that `redirect_uri` from the token request matches the stored
value exactly. Currently `tokens.go:103` calls `p.RedirectURL(vals,
callbackURL, "redirect_uri")` for prefix validation only — it must
compare against the stored redirect_uri from the code, not just the
app's callback URL.

<details>
<summary>Why both exact match AND store+verify?</summary>

Exact matching at the authorize endpoint prevents open redirectors
(attacker can't use a sub-path).
Storing and verifying at the token endpoint prevents code injection — an
attacker who steals a code can't exchange it with a different
redirect_uri than was originally authorized. This is required by RFC
6749 §4.1.3 and OAuth 2.1.
</details>

### Fix 7 — `frame-ancestors` CSP on consent page

The consent page can be iframed by a workspace app (same-site), which is
the attack vector. Add a `Content-Security-Policy` header to prevent
framing.

**File: `site/site.go` — `RenderOAuthAllowPage` function (~line 731)**

Before writing the response, add:

```go
func RenderOAuthAllowPage(rw http.ResponseWriter, r *http.Request, data RenderOAuthAllowData) {
    rw.Header().Set("Content-Type", "text/html; charset=utf-8")
    // Prevent the consent page from being framed to mitigate
    // clickjacking attacks (coder/security#121).
    rw.Header().Set("Content-Security-Policy", "frame-ancestors 'none'")
    rw.Header().Set("X-Frame-Options", "DENY")
    ...
```

Both headers for defense-in-depth (CSP for modern browsers,
X-Frame-Options for legacy).

### OAuth 2.1 — Mandatory PKCE

Currently PKCE is checked only when `code_challenge` was provided during
authorization (`tokens.go:258`):

```go
// CURRENT — conditional check
if dbCode.CodeChallenge.Valid && dbCode.CodeChallenge.String != "" {
    // verify PKCE
}
```

OAuth 2.1 requires PKCE for ALL authorization code flows. Change to:

**File: `coderd/oauth2provider/authorize.go`** — Add `"code_challenge"`
to required params:

```go
p.RequiredNotEmpty("response_type", "client_id", "code_challenge")
```

**File: `coderd/oauth2provider/tokens.go:257-265`** — Make PKCE
verification unconditional:

```go
// AFTER — PKCE always required (OAuth 2.1)
if req.CodeVerifier == "" {
    return codersdk.OAuth2TokenResponse{}, errInvalidPKCE
}
if !dbCode.CodeChallenge.Valid || dbCode.CodeChallenge.String == "" {
    // Code was issued without a challenge — should not happen
    // with the authorize endpoint enforcement, but defend in
    // depth.
    return codersdk.OAuth2TokenResponse{}, errInvalidPKCE
}
if !VerifyPKCE(dbCode.CodeChallenge.String, req.CodeVerifier) {
    return codersdk.OAuth2TokenResponse{}, errInvalidPKCE
}
```

**File: `codersdk/oauth2.go`** — Remove
`OAuth2ProviderResponseTypeToken` from the enum or reject it explicitly
in the authorize handler. Currently it's defined at line 216 but the
handler ignores `response_type` and always issues a code. We should
either:
- (a) Remove the `"token"` variant from the enum and reject it with
`unsupported_response_type`, OR
- (b) Add an explicit check in `ProcessAuthorize` that rejects
`response_type=token`

Option (b) is simpler and more backwards-compatible:

```go
// In ProcessAuthorize, after extracting params:
if params.responseType != codersdk.OAuth2ProviderResponseTypeCode {
    httpapi.WriteOAuth2Error(ctx, rw, http.StatusBadRequest,
        codersdk.OAuth2ErrorCodeUnsupportedResponseType,
        "Only response_type=code is supported")
    return
}
```

### OAuth 2.1 — Bearer tokens in query strings

`coderd/httpmw/apikey.go:743` accepts `access_token` from URL query
parameters. OAuth 2.1 prohibits this. However, this may be used
internally (e.g., workspace apps, DERP). Need to audit callers before
removing.

**Approach:** This is a larger change with potential breakage. Mark as a
**separate follow-up issue** rather than including in this PR. Document
the finding.

### OAuth 2.1 — Removed flows

 **Already compliant.** `tokens.go` only supports `authorization_code`
and `refresh_token` grant types. The implicit grant
(`response_type=token`) will be explicitly rejected per the PKCE section
above.

### OAuth 2.1 — Refresh token rotation

 **Already compliant.** `tokens.go:442` deletes the old API key when a
refresh token is used.

## Migration Plan

All DB changes can go in a single new migration (or extend 000420 if the
branch is rebased before merge). Columns to add:
- `redirect_uri text` on `oauth2_provider_app_codes`

The `state_hash` column is already added by migration 000420.

## Implementation Order

1. **Fix 7** — CSP headers on consent page (isolated, no deps)
2. ~~**Fix 2** — Require `state` parameter~~ (DROPPED — state stays
optional)
3. **Fix 4** — Exact redirect URI matching + store/verify redirect_uri
4. **PKCE mandatory** — Require `code_challenge` + reject
`response_type=token`
5. **Rollback** — Remove `"state"` from `RequiredNotEmpty` in
`authorize.go`
6. **Tests** — Update/add tests for all changes
7. **`make gen`** after DB changes

## Out of Scope (separate PRs)

- Bearer tokens in query strings (needs internal caller audit)
- Scope enforcement on OAuth2 tokens
- Rate limiting / quota on dynamic client registration

</details>

---
_Generated with [`mux`](https://github.com/coder/mux) • Model:
`anthropic:claude-opus-4-6` • Thinking: `xhigh`_
2026-02-23 12:18:44 +01:00
Yevhenii Shcherbina e6f0a1b2f6 docs: improve boundary docs (#22183) 2026-02-20 15:41:54 -05:00
Jakub Domeracki ceb417f8ba fix: revert automatically set 'host-prefix-cookie' in https deployments" (#22225)
Reverts coder/coder#22224
2026-02-20 20:12:51 +01:00
Steven Masley 67044d80a0 chore: automatically set 'host-prefix-cookie' in https deployments (#22224)
The feature was never released, so this is not a breaking change
2026-02-20 17:17:50 +00:00
Steven Masley b0f35316da chore!: automatically use secure cookies if using https access-url (#22198)
`--secure-auth-cookie` now automatically sources it's default value from `--access-url`

If the access url uses HTTPS, secure is set to `true`. 
To revert to old behavior, set the value explicitly to `false`
2026-02-20 10:33:37 -06:00
Steven Masley efdaaa2c8f chore: add oidc redirect url to override access url (#21521)
If a deployment has 2 domains, overriding the oidc url allows the oidc
redirect to differ from the access_url

response to https://github.com/coder/coder/discussions/21500

**This config setting is hidden by default**
2026-02-20 09:11:01 -06:00
Steven Masley e5f64eb21d chore: optionally prefix authentication related cookies (#22148)
When the deployment option is enabled auth cookies are prefixed with
`__HOST-`
([info](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie)).

This is all done in a middleware that intercepts all requests and strips
the prefix on incoming request cookies.
2026-02-20 09:01:00 -06:00
Atif Ali a955de906a docs: convert a note to GFM style (#22197)
<!--

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-02-20 13:34:35 +05:00
Jake Howell 051ed34580 feat: convert soft_limit to limit (#22048)
In relation to
[`internal#1281`](https://github.com/coder/internal/issues/1281)

Remove the `soft_limit` field from the `Feature` type and simplify
license limit handling. This change:

- Removes the `soft_limit` field from the API and SDK
- Uses the soft limit value as the single `limit` value in the UI and
API
- Simplifies warning logic to only show warnings when the limit is
exceeded
- Updates tests to reflect the new behavior
- Updates the UI to use the single limit value for display
2026-02-20 16:09:12 +11:00
Garrett Delfosse e8d6016807 fix: allow users with workspace:create for any owner to list users (#21947)
## Summary

Custom roles that can create workspaces on behalf of other users need to
be able to list users to populate the owner dropdown in the workspace
creation UI. Previously, this required a separate `user:read`
permission, causing the dropdown to fail for custom roles.

## Changes

- Modified `GetUsers` in `dbauthz` to check if the user can create
workspaces for any owner (`workspace:create` with `owner_id: *`)
- If the user has this permission, they can list all users without
needing explicit `user:read` permission
- Added tests to verify the new behavior

## Testing

- Updated mock tests to assert the new authorization check
- Added integration tests for both positive and negative cases

Fixes #18203
2026-02-19 13:04:53 -05:00
Danielle Maywood 02a80eac2e docs: document new terraform-managed devcontainers (#21978) 2026-02-19 11:45:04 +00:00
blinkagent[bot] c8335fdc54 docs: rename ANTHROPIC_API_KEY to ANTHROPIC_AUTH_TOKEN in Claude Code docs (#22188)
Updates the reference to `ANTHROPIC_API_KEY` in the Claude Code client
docs to `ANTHROPIC_AUTH_TOKEN`.

**File changed:**
- `docs/ai-coder/ai-bridge/clients/claude-code.md` — configuration
instructions

Created on behalf of @dannykopping

---------

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-19 13:23:47 +02:00
Yevhenii Shcherbina 385554dff8 chore: add boundary and k8s docs (#22153) 2026-02-18 13:33:22 -05:00
blinkagent[bot] fb027da8bb docs: add Antigravity IDE integration documentation (#22177)
Closes #21130

Adds documentation for Google Antigravity IDE integration, following the
same pattern as Cursor and Windsurf (dedicated page for desktop IDEs).

**Changes:**

- `docs/user-guides/workspace-access/antigravity.md` — New dedicated
page with install guide, Coder extension setup, and template
configuration example using the [Antigravity registry
module](https://registry.coder.com/modules/coder/antigravity)
- `docs/user-guides/workspace-access/index.md` — Added Antigravity IDE
section alongside Cursor and Windsurf
- `docs/manifest.json` — Added sidebar navigation entry after Windsurf

Antigravity uses the `antigravity://` protocol (added in #20873) and the
built-in `/icon/antigravity.svg` icon (added in #21068). The [registry
module](https://registry.coder.com/modules/coder/antigravity) wraps
`vscode-desktop-core` with `protocol = "antigravity"`.

Created on behalf of @matifali

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-18 22:06:44 +05:00
Rowan Smith 1c4dd78b05 chore: add id to template version output columns (#22163)
At present it is not possible to obtain the `id` of the template version
in the table output:

```
➜  ~ coder templates version list -h                
coder v2.30.1+16408b1

USAGE:
  coder templates versions list [flags] <template>

  List all the versions of the specified template

OPTIONS:
  -O, --org string, $CODER_ORGANIZATION
          Select which organization (uuid or name) to use.

  -c, --column [name|created at|created by|status|active|archived] (default: name,created at,created by,status,active)
          Columns to display in table output.

➜  ~ coder templates version list aws-linux-dynamic 
NAME                 CREATED AT                 CREATED BY  STATUS     ACTIVE  
infallible_feistel2  2025-10-10T10:34:02+11:00  rowansmith  Succeeded  Active  
mystifying_almeida1  2025-10-10T10:32:38+11:00  rowansmith  Succeeded         
```

Adding this because it is useful when wanting to programatically
retrieve the details of the latest template version, and `-ojson` does
not include `active` details in it's output.

```
➜  Downloads ./coder-cli-templateversions-list-id templates version list -h                
coder v2.30.1-devel+bab99db9e7

USAGE:
  coder templates versions list [flags] <template>

  List all the versions of the specified template

OPTIONS:
  -O, --org string, $CODER_ORGANIZATION
          Select which organization (uuid or name) to use.

  -c, --column [id|name|created at|created by|status|active|archived] (default: name,created at,created by,status,active)
          Columns to display in table output.

      --include-archived bool
          Include archived versions in the result list.

  -o, --output table|json (default: table)
          Output format.

———
Run `coder --help` for a list of global options.

➜  Downloads ./coder-cli-templateversions-list-id templates version list aws-linux-dynamic -c id,name,'created at','created by',status,active
ID                                    NAME                 CREATED AT                 CREATED BY  STATUS     ACTIVE  
38f66eae-ec63-49b7-a9d2-cdb79c379d19  infallible_feistel2  2025-10-10T10:34:02+11:00  rowansmith  Succeeded  Active  
aa797ea5-4221-461b-80b0-90c5164f8dc0  mystifying_almeida1  2025-10-10T10:32:38+11:00  rowansmith  Succeeded
```
2026-02-18 16:47:45 +11:00
Danielle Maywood d737f8c104 feat(cli): add coder task resume command (#22066)
Complements https://github.com/coder/coder/pull/22012 by adding a `coder task resume` command
2026-02-17 16:24:13 +00:00
Cian Johnston f8eea54e97 fix(coderd): use BuildReasonTaskAutoPause for task workspaces (#22126)
Relates to https://github.com/coder/internal/issues/1252

When a workspace with a TaskID hits its deadline, use
BuildReasonTaskAutoPause instead of BuildReasonAutostop. This allows
downstream systems to distinguish between regular autostop and task
workspace pauses.

Created by Mux using Opus 4.5.
2026-02-17 15:11:04 +00:00
Paweł Banaszewski 90c11f3386 feat: add client column to aibridge_interceptions table (#21839)
Adds `client` column to `aibridge_interceptions` table. It is set accordingly to what is passed from AI Bridge in `RecordInterception`.
Adds interception filtering by `client` value.

Depends on: https://github.com/coder/aibridge/pull/158
Updates aibridge library to include this change.

Fixes: https://github.com/coder/aibridge/issues/31
2026-02-17 15:43:02 +01:00
blinkagent[bot] 81a928915c docs: remove outdated Toolbox log level persistence warning (#22139)
Remove the warning about JetBrains Toolbox not persisting log level
configuration between restarts.

As of JetBrains Toolbox 3.2, log level configuration now persists
between restarts, making this warning outdated.

Created on behalf of @matifali

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-17 19:17:22 +05:00
Cian Johnston 4a3304fc38 feat(cli)!: expire tokens by default (#21783)
## Summary

> NOTE: Calling this out as a breaking change in case existing consumers
of the CLI depend on being able to see expired tokens OR being able to
delete tokens immediately.

Updates the `coder tokens rm` command to immediately expire a token by
ID, preserving the token record for audit trail purposes. Tokens can
still be deleted by passing `--delete`.

## Problem

During an incident on dev.coder.com, operators needed to urgently expire
an API key that was stuck in a hot loop. The only way to do this was via
direct database access:

```sql
UPDATE api_keys SET expires_at = NOW() WHERE id = '...';
```

This is not ideal for operators who may not have direct DB access or
want to avoid manual SQL.

## Solution

This PR adds:

- **API endpoint**: `PUT /api/v2/users/{user}/keys/{keyid}/expire` -
Sets the token's `expires_at` to now
- **SDK method**: `ExpireAPIKey(ctx, userID, keyID)` 
- **Updates CLI**: `coder tokens rm <name|id|token>` now _expires_ by
default. You can still delete by passing the `--delete` flag. The `coder
tokens list` command now also hides expired tokens by default. You can
`--include-expired` if needed to include them.
- **Audit logging**: The expire action is logged with old and new key
states

## Test plan

- Tests cover: owner expiring own token, admin expiring other user's
token, non-admin cannot expire other's token, 404 for non-existent token

Closes #21782

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 13:16:46 +00:00
Atif Ali 63563e57db docs: add registry mirroring guide for Artifactory (#22025)
Verified to be working locally.

---------

Co-authored-by: Phorcys <57866459+phorcys420@users.noreply.github.com>
2026-02-16 18:29:48 +01:00
Jeremy Ruppel 0df864fb88 fix: hide "Create Workspace" button for deleted templates (#22092)
**Background**

Reported in #17417, there is a `deleted` query parameter supported by
/api/v2/templates, but we do not respect this field on the client,
showing the "Create Workspace" button for deleted templates.

**Expected Behavior**

Don't show the "Create Workspace" button for deleted templates.

**Notes**

This PR adds a new `deleted` field to the templates API response.

Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
2026-02-13 19:44:50 -05:00
blinkagent[bot] 00713385fb feat: remove license gate from workspace and task bulk actions (#22090)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-13 20:08:36 +05:00
Danielle Maywood 6d41d98b65 feat(cli): add coder task pause command (#22012)
Adds a new `coder task pause`
2026-02-13 14:21:31 +00:00
Susana Ferreira df84cea924 feat(scripts/metricsdocgen): support merging static and generated metrics files (#21464)
## Description

This PR refactors `scripts/metricsdocgen/main.go` to support merging static and generated metrics files for documentation generation.

The static `metrics` file remains necessary for metrics not defined in the coder codebase (`go_*`, `process_*`, `promhttp_*`, `coder_aibridged_*`), as well as **edge cases** the scanner cannot handle (e.g.,  such as metrics with runtime-determined labels or function-local variable references for fields, ...). Handling these edge cases in the scanner would make it significantly more complex, so we keep this hybrid approach to accommodate them. This means that in such cases, developers need to update the `metrics` file directly, meaning there is still a risk of out-of-date information in the documentation. However, this solution should already encompass most cases.

Static metrics take priority over generated metrics when both files contain the same metric name, allowing manual overrides without modifying the scanner. Some of these edge cases could be easily fixed by updating the codebase to use one of the supported patterns.

## Changes

* Update `scripts/metricsdocgen/main.go` to read from two separate metrics files:
  * `metrics`: static, manually maintained metrics (e.g., `go_*`, `process_*`, `promhttp_*`, `coder_aibridged_*`)
  * `generated_metrics`: auto-generated by the AST scanner
* Update `metrics` file to contain only static and edge-case metrics
* Skip metrics with empty HELP descriptions in the scanner
* Update `generated_metrics` to reflect skipped metrics
* Update `docs/admin/integrations/prometheus.md` with merged metrics

Related to: https://github.com/coder/coder/issues/13223

**Disclosure:** This PR was mainly developed with Claude Sonnet 4, with iterative review and refinement by @ssncferreira
2026-02-13 12:19:33 +00:00
Callum Styan 5f3be6b288 feat: add provisioner job queue wait time histogram and jobs enqueued counter (#21869)
This PR adds some metrics to help identify job enqueue rates and
latencies. This work was initiated as a way to help reduce the cost of
the observation/measurement itself for autostart scaletests, which
impacts our ability to identify/reason about the load caused by
autostart. See: https://github.com/coder/internal/issues/1209

I've extended the metrics here to account for regular user initiated
builds, prebuilds, autostarts, etc. IMO there is still the question here
of whether we want to include or need the `transition` label, which is
only present on workspace builds. Including it does lead to an increase
in cardinality, and in the case of the histogram (when not using native
histograms) that's at least a few extra series for every bucket. We
could remove the transition label there but keep it on the counter.

Additionally, the histogram is currently observing latencies for other
jobs, such as template builds/version imports, those do not have a
transition type associated with them.

Tested briefly in a workspace, can see metric values like the following:
-
`coderd_workspace_builds_enqueued_total{build_reason="autostart",provisioner_type="terraform",status="success",transition="start"}
1`
-
`coderd_provisioner_job_queue_wait_seconds_bucket{build_reason="autostart",job_type="workspace_build",provisioner_type="terraform",transition="start",le="0.025"}
1`

---------

Signed-off-by: Callum Styan <callumstyan@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 13:40:47 -08:00
blinkagent[bot] 1e1d312cab docs: split env var declaration from command in AI Bridge setup (#22072)
The AI Bridge setup docs showed `CODER_AIBRIDGE_ENABLED=true coder
server` as a single line, which can confuse users into thinking the env
var is a one-time prefix rather than a persistent setting.

Split this into `export CODER_AIBRIDGE_ENABLED=true` on its own line
followed by `coder server`, which is clearer and consistent with how the
Bedrock credentials section already handles env vars in the same file.

Created on behalf of @dannykopping

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-12 18:15:44 +00:00
Kacper Sawicki 60e3ab7632 feat(site)!: add consent prompt for auto-creation with prefilled parameters (#22011)
### Summary

Workspace created via mode=auto links now require explicit user
confirmation before provisioning. A warning dialog shows all prefilled
param.* values from the URL and blocks creation until the user clicks
`Confirm and Create`. Clicking `Cancel` falls back to the standard form
view.

<img width="820" height="475" alt="auto-create-consent-dialog"
src="https://github.com/user-attachments/assets/8339e3bd-434f-4a04-9385-436bf95f49d7"
/>

### Breaking behavior change

Links using `mode=auto` (e.g., "Open in Coder" buttons) will no longer
silently create workspaces. Users will now see a consent dialog and must
explicitly confirm before the workspace is provisioned. Any existing
integrations or automation relying on `mode=auto` for seamless workspace
creation will now require manual user interaction.

---------

Co-authored-by: Jake Howell <jacob@coder.com>
2026-02-12 15:39:02 +01:00
Sas Swart 47b8ca940c feat: add an endpoint to manually resume a coder task (#21948)
Closes https://github.com/coder/internal/issues/1262.

This PR adds:
* the `POST /api/experimental/tasks/{user}/{task}/resume` endpoint
* follows conventions from https://github.com/coder/internal/issues/1261
* sets the build reason to `task_resume`
* a task that is not paused (ie. is already running), cannot be resumed.
2026-02-12 09:59:53 +02:00
blinkagent[bot] 53ceea918b docs: remove broken image reference in contributing guide (#22013)
The "Deploy PR manually" image (`deploy-pr-manually.png`) referenced in
the contributing docs has never existed in the repository, resulting in
a broken image on the [docs
site](https://coder.com/docs/about/contributing/CONTRIBUTING#deploying-a-pr).

This PR removes the broken `<Image>` tag and ends the sentence with a
period instead. The `pr-deploy.yaml` workflow link remains intact for
users to navigate to the workflow dispatch page directly.

Created on behalf of @DavidFrawormo

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-09 15:50:47 +00:00
Jake Howell f11a8086b0 fix: migrate all uses of visuallyHidden (#22001)
Replace all usages of MUI's `visuallyHidden` utility from `@mui/utils`
with Tailwind's `sr-only` class. Both produce identical CSS, so this is
a no-op behaviorally -- just removes another MUI dependency from the
codebase. Also updates the accessibility example in the frontend
contributing docs to match.
2026-02-09 23:17:03 +11:00
Sas Swart e6fbf501ac feat: add an endpoint to manually pause a coder task (#21889)
Closes https://github.com/coder/internal/issues/1261.

This pull request adds an endpoint to pause coder tasks by stopping the
underlying workspace.
* Instead of `POST /api/v2/tasks/{user}/{task}/pause`, the endpoint is
currently experimental.
* We do not currently set the build reason to `task_manual_pause`,
because build reasons are currently only used on stop transitions.
2026-02-09 08:56:41 +02:00
Jon Ayers 6035e45cb8 feat: add e2e workspace build duration metric (#21739)
Adds coderd_template_workspace_build_duration_seconds histogram that
tracks the full duration from workspace build creation to agent ready.
This captures the complete user-perceived build time including
provisioning and agent startup.

The metric is emitted when the agent reports ready/error/timeout via the
lifecycle API, ensuring each build is counted exactly once per replica.
2026-02-06 16:26:02 -06:00
blinkagent[bot] e5c3d151bb docs: add upgrade best practices guide (#21656) 2026-02-06 16:08:59 +00:00
Danielle Maywood 6ccd20d45f feat(agent): populate subagent ID for terraform-defined devcontainers (#21942)
Completes the final piece of the puzzle. Support the pre-creation flow
from the agent side.
2026-02-06 15:52:54 +00:00
blinkagent[bot] e98ee5e33d docs: fix incorrect path to coder modules in registry repo (#21976)
## Description

Fixes an incorrect path in the air-gapped/offline installation
documentation for publishing Coder modules to Artifactory.

The [coder/registry](https://github.com/coder/registry) repo has the
following structure:
```
registry/           # repo root
└── registry/       # subdirectory
    └── coder/
        └── modules/
```

The documentation previously instructed users to run:
```shell
cd registry/coder/modules
```

But the correct path is:
```shell
cd registry/registry/coder/modules
```

This was causing confusion for users trying to set up Coder modules in
air-gapped environments with Artifactory or similar repository managers.

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-02-06 09:30:03 -05:00
Yevhenii Shcherbina 45e08aa9f6 chore: update boundary version (#21955)
Update boundary version to v0.8.0
2026-02-06 09:12:14 -05:00