Commit Graph

14304 Commits

Author SHA1 Message Date
Kayla はな df5e16ed6d fix(dogfood): install rust-src component (#25349) 2026-05-14 12:06:00 -06:00
Danielle Maywood 68baf84b8c fix: hide empty execute tool calls (#25346) 2026-05-14 18:19:12 +01:00
35C4n0r 2871a02352 fix: use actual ai_task instances for HasAITasks (#25197)
Previously, `hasAITaskResources()` scanned the Terraform graph for
`coder_ai_task` node labels. The graph includes resource definitions
regardless of `count`, so templates with `count = 0` were incorrectly
marked as `HasAITasks = true`, causing them to appear on the `/tasks`
page when no AI task resources would be created.

Replace the graph-based check with `len(aiTasks) > 0`. The `aiTasks`
slice is populated from state modules where Terraform has already
evaluated `count`, so it correctly reflects actual resource instances.

ref:
https://linear.app/codercom/issue/ECO-39/make-coder-tasks-respect-count

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

---------

Signed-off-by: 35C4n0r <work.jaykumar@gmail.com>
Signed-off-by: Jay Kumar <jay.kumar@coder.com>
2026-05-14 21:49:05 +05:30
Danielle Maywood 9ddfafe2b1 feat: add chat ACL database foundation (#25080) 2026-05-14 17:18:50 +01:00
Nick Vigilante 507ece3bc4 docs: Fix the display of the tab block in External Workspaces (#25341)
Fixes DOCS-169

<!--

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-05-14 12:04:45 -04:00
Cian Johnston 15c958fea2 fix(testutil): ensure FakeSink does not swallow logs (#25185)
`FakeSink` was silently capturing log entries without forwarding them to
`testing.TB.Log`. This made debugging test failures harder because logs
were invisible in `go test -v` output.

Store `testing.TB` in `FakeSink` and call `t.Log` on each entry, guarded
by a check to avoid logging after the test has finished.

Split out from #25012.

> 🤖 Generated with [Coder Agents](https://coder.com)
2026-05-14 16:51:44 +01:00
Spike Curtis 132fa87bf3 fix: only embed Azure roots on darwin (#25312)
Partially reverts #25136 for non-darwin platforms.

In general we want to avoid pinning trust roots to embedded Certs, since that limits operational flexibility. If Azure changes CAs, operators should, at most, be able to update the OS trust store to keep Coder working correctly. Embedding roots means we need to upgrade the Coder binary.

Since Coder Server on macOS is not really supported for production use, embedding only in that case to ease development and testing is OK.
2026-05-14 11:45:21 -04:00
Ethan e37bf4f7be ci: bump paralleltestctx to v0.0.2 (#25323)
## Summary

- bump `github.com/coder/paralleltestctx` from v0.0.1 to v0.0.2
- pick up the latest paralleltestctx timeout-context detection
improvements in `go tool ... paralleltestctx` runs
2026-05-15 00:14:38 +10:00
Danny Kopping 841b777ccd feat: add ai_providers table, queries, dbauthz, audit, RBAC (#24892) 2026-05-14 16:10:46 +02:00
Jaayden Halko acf57b3b35 feat(site): add legacy auto sync helper and tritan cleanup (#25180)
## Summary

- Add `legacyAutoToSync` to map legacy auto-family theme preferences to
light and dark sync pairs.
- Expand colorblind theme tests for legacy auto-family handling.
- Move tritan success and git-added surfaces onto the sky-blue palette
in theme roles and CSS variables.

## Dependencies

- None. This can merge independently before the dropdown work.

## Validation

- `pnpm -C site exec vitest run --project=unit
src/theme/colorblind.test.ts`
- `pnpm -C site lint:types`
- Pre-commit hook passed on the branch commit.
2026-05-14 14:43:13 +01:00
Danielle Maywood 25a803221e feat: add shell tool display mode preference (#25029) 2026-05-14 14:25:07 +01:00
Jaayden Halko 3a070a83dd fix(site/src/pages/AgentsPage): theme diff changed-line backgrounds (#25179)
## Summary

- Update AgentsPage diff viewer CSS so changed lines use theme-aware git
added and deleted surfaces.
- Add unit coverage for the changed-line CSS variables and line-type
selectors.

## Dependencies

- None. This is independent of the theme mode API and dropdown stack.

## Validation

- `pnpm -C site exec vitest run --project=unit
src/pages/AgentsPage/components/ChatElements/tools/utils.test.ts`
- Pre-commit hook passed on the branch commit.
2026-05-14 14:11:30 +01:00
Cian Johnston da2fa082bb fix(coderd/httpapi): CloseRead on test conns to ensure pings pong (#25184)
The `websocketPair` test helper was not calling `CloseRead` on either
side of the connection. Without `CloseRead`, the websocket library does
not process control frames (ping/pong), so the heartbeat tests were
passing only because no pings had yet failed, not because pings were
actually succeeding.

Add `CloseRead` on both the client and server connections so that pong
frames are delivered in response to pings.

Split out from #25012.

> 🤖 Generated with [Coder Agents](https://coder.com)
2026-05-14 13:54:59 +01:00
Max Schwenk f3e90b334d fix(cli): show sync wait dependencies (#25089)
## Problem
`coder exp sync want` and `coder exp sync start` both printed generic
success messages, which hid the dependency units involved in startup
coordination.

Before, declaring dependencies with `sync want` printed:

```text
Success
```

Before, `sync start` printed while waiting, then finished with another
generic success message:

```text
Waiting for dependencies of unit 'test-unit' to be satisfied...
Success
```

## Solution
Print the dependency units in both cases, using wording that matches
where the command is in the lifecycle.

After, `sync want` prints the dependencies it declared for the unit:

```text
Unit "test-unit" declared dependencies: [dep-unit]
```

After, `sync start` enumerates the dependencies while it is waiting,
then prints the same dependencies after the unit starts executing:

```text
Unit "test-unit" is waiting for dependencies to be satisfied: [dep-unit, dep-unit-2]
Unit "test-unit" finished waiting for dependencies: [dep-unit, dep-unit-2]
```

The sync golden tests now cover the updated output, including multiple
dependencies for `sync start`.
2026-05-14 14:45:20 +02:00
Michael Suchacz cb37047dce feat: dedicated /prompts endpoint for chat history cycle (#25083)
Follow-up to #25004. The merged change cycles only through messages
already loaded in the in-memory chat store (page size 50). Long chats
and chats whose oldest turns have rolled out of the page lose access to
their earlier prompts in the composer's up/down arrow cycle. This PR
adds a dedicated server endpoint that returns the full prompt history,
newest first, and rewires the composer to use it.

## What changed

### Endpoint

`GET /api/experimental/chats/{chat}/prompts?limit=N`

```go
type ChatPrompt struct { ID int64; Text string }
type ChatPromptsResponse struct { Prompts []ChatPrompt }
```

- `limit`: `0..2000`. `0` (the default) is treated as the server-side
default of 500; out-of-range values return `400`. Negative values are
rejected by the SDK's `PositiveInt32` parser before reaching the
handler.
- Auth: parent-chat read in `dbauthz`, mirroring
`GetChatMessagesByChatID`.
- The SQL filters `role='user'`, `deleted=false`, `visibility IN
('user','both')`, guards the lateral with `jsonb_typeof(content) =
'array'` so legacy V0 scalar-string rows are silently skipped, then
unrolls `content` JSONB with `WITH ORDINALITY` and concatenates only
`type='text'` parts in original order via `string_agg(... ORDER BY
ordinality)`. Messages whose joined text is whitespace-only are dropped
via `HAVING ... ~ '\S'` so cycling never lands on a blank entry.

### Partial index (migration `000494`)

```sql
CREATE INDEX idx_chat_messages_user_prompts
ON chat_messages (chat_id, id DESC)
WHERE deleted = false
  AND role = 'user'
  AND visibility IN ('user', 'both');
```

The partial WHERE matches the query's filter exactly and the key order
matches `ORDER BY id DESC`, so the planner gets both the filter and the
ordering from the index without a sort step.

`EXPLAIN ANALYZE` on a synthetic 51-chat × 5,000-message dataset (≈260k
rows, 10k user prompts in the target chat, `random_page_cost=1.1`):

| | Plan | Buffers hit | Time |
|---|---|---|---|
| Without index | `Index Scan Backward using chat_messages_pkey`,
**250,848 rows removed by filter** | 6,683 | 32.4 ms |
| With index | `Index Scan using idx_chat_messages_user_prompts`, no
filter | 38 | 1.3 ms |

≈25× faster, 175× fewer buffer hits.

### Frontend

- `chatPromptsKey` / `chatPromptsQuery` factories in
`site/src/api/queries/chats.ts` (`staleTime: 30s`, `enabled: chatId !==
""`, asks the server for 500 prompts).
- `ChatPageContent.tsx` replaces the in-memory derivation with
`useQuery(chatPromptsQuery(chatId ?? ""))`. The composer's existing
`cycleHistorySnapshotRef` anchors the in-flight cycle so a refetch
arriving mid-cycle cannot shift the indexed prompt out from under the
user.
- `getEditableUserMessagePayload` now concatenates user-message text
parts verbatim, mirroring the server's `string_agg(part->>'text', ''
ORDER BY ordinality)`, instead of routing through the streaming-oriented
`parseMessageContent` / `appendText` pipeline (which drops
whitespace-only chunks — correct for assistant streams, wrong for a
user's persisted message). This keeps the cycle and the edit path in
agreement on the same message. File blocks are still pulled separately
via
`parseMessageContent(...).blocks.filter(isEditableUserMessageFileBlock)`.
- Cache invalidation in `createChatMessage.onSuccess`,
`editChatMessage.onSettled`, and `useChatStore.upsertCacheMessages`
(only when an upserted message has `role === "user"`).
- Page-level stories pre-seed `chatPromptsKey(CHAT_ID)` from the same
`messagesData` to keep them offline.

## Tests

- New `TestGetChatUserPrompts` in `coderd/exp_chats_test.go` with five
subtests:
- `NewestFirstFiltering` — multi-part concatenation, non-text parts
skipped, whitespace-only filtered, soft-deleted excluded, `model`-only
visibility excluded, assistant-role excluded by `cm.role = 'user'`,
legacy V0 scalar row silently excluded by the `jsonb_typeof` guard,
ordering newest first.
- `LimitClampsResults` — explicit `limit=2` returns the two newest
prompts.
  - `InvalidLimitRejected` — `limit=5000` is `400 Bad Request`.
- `NotFoundForOtherUsers` — a separate user in the same org gets `404`,
not the prompts.
- `EmptyResultIsJSONArray` — zero-message chat and assistant-only chat
both return `Prompts: []` (non-nil, empty).
- New unit test in `messageParsing.test.ts` asserting that
`getEditableUserMessagePayload(["hello", " ", "world"])` returns `"hello
world"`, locking in the agreement with the SQL `string_agg`.
- `dbauthz_test.go` adds the
`MethodTestSuite.TestChats/GetChatUserPromptsByChatID` entry, asserting
parent-chat `policy.ActionRead`.
- `pnpm test src/pages/AgentsPage` — 1159 passed, 2 skipped.
- `make gen` produces no diff.

## Manual verification

Seeded a dev chat with Claude Sonnet 4.6 via the aibridge Anthropic
provider and posted 20 user prompts end-to-end. Verified that the
`/prompts` endpoint returns 20 rows newest-first, that `limit=10` clamps
correctly, that `limit=0` uses the server default of 500, and that the
up/down keyboard cycle in the composer walks the same sequence (and
reverses correctly back to the empty draft).

## Out of scope

- Cross-chat history.
- Per-user opt-out for the cycle.
- File-reference / attachment cycling — the cycle continues to reproduce
plain text only, by design.

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

# CODAGT-319 Follow-up — Dedicated `/prompts` endpoint

## Context

The merged feature ([#25004](https://github.com/coder/coder/pull/25004)
/ [d32842f](https://github.com/coder/coder/commit/d32842f)) cycles only
through messages already loaded in the in-memory chat store, which is
capped at the first 50 messages of the current page. Long chats and
chats whose oldest turns have rolled out of the page can no longer
recall their full prompt history. This follow-up exposes a dedicated
server endpoint that returns the user-authored prompts in a chat, newest
first, and rewires the composer to use it.

## Design

### Endpoint

`GET /api/experimental/chats/{chat}/prompts?limit=N`

Returns:

```go
type ChatPrompt struct {
    ID   int64
    Text string
}
type ChatPromptsResponse struct {
    Prompts []ChatPrompt
}
```

- `limit`: `0..2000`. `0` (the default) → server-side default of 500.
The wire-level default is encoded in SQL as `COALESCE(NULLIF($limit, 0),
500)`. Negatives are rejected upstream by `PositiveInt32`; the handler
only caps the upper bound.
- Auth: parent-chat read in `dbauthz`, mirroring
`GetChatMessagesByChatID`.
- Listed under the experimental router so we can iterate without API
guarantees.

### SQL

The query lives in `coderd/database/queries/chats.sql` as
`GetChatUserPromptsByChatID`:

- Filters `role='user'`, `deleted=false`, `visibility IN
('user','both')` to mirror the composer's "what the user actually typed
and can re-send" contract.
- Guards the lateral with `jsonb_typeof(content) = 'array'` so legacy V0
rows whose content is a scalar JSON string (predates migration `000434`)
are silently excluded instead of raising `"cannot extract elements from
a scalar"`.
- Unrolls `content` JSONB with `jsonb_array_elements WITH ORDINALITY`
and concatenates only `type='text'` parts, preserving original order via
`string_agg(... ORDER BY ordinality)`.
- Casts the result to `text` so sqlc emits a `string` field instead of
`[]byte`.
- Drops whitespace-only prompts via `HAVING string_agg(...) ~ '\S'` so
cycling never lands on a blank entry.
- Orders by `cm.id DESC` (`id` is a sequence, so this is "newest first"
without relying on `created_at`).

### Index

New partial index added in migration `000494`:

```sql
CREATE INDEX idx_chat_messages_user_prompts
ON chat_messages (chat_id, id DESC)
WHERE deleted = false
  AND role = 'user'
  AND visibility IN ('user', 'both');
```

The partial WHERE clause matches the query's filter exactly, so the
planner can use the index for both filtering and ordering without a sort
step.

### Frontend

- `chatPromptsKey(chatId)` and `chatPromptsQuery(chatId)` factories in
`site/src/api/queries/chats.ts`. `staleTime: 30s`, `enabled: chatId !==
""`. Asks the server for 500 prompts (well below the 2000 max, plenty
for the cycle).
- `ChatPageContent.tsx` replaces the in-memory derivation with
`useQuery(chatPromptsQuery(chatId ?? ""))`. The composer's
`cycleHistorySnapshotRef` already takes a stable snapshot at cycle
entry, so a refetch arriving mid-cycle cannot shift the indexed prompt
out from under the user.
- `getEditableUserMessagePayload` extracts the edit-path text from raw
user-message parts (filter `type === "text"`, join verbatim) instead of
going through `parseMessageContent` / `appendText`, which is built for
assistant streams and intentionally drops whitespace-only chunks.
Without this, cycling and clicking Edit on the same message could
produce different draft text for messages with whitespace-only
interleaved text parts.
- Cache invalidation: `createChatMessage.onSuccess`,
`editChatMessage.onSettled`, and `useChatStore.upsertCacheMessages`
(when at least one upserted message has `role === "user"`) all
invalidate `chatPromptsKey(chatId)`.

### Tests

- `TestGetChatUserPrompts` (`coderd/exp_chats_test.go`) covers:
- `NewestFirstFiltering` — multi-part concatenation, non-text parts
skipped, whitespace-only filtered, soft-deleted excluded, `model`-only
visibility excluded, assistant-role excluded by `cm.role = 'user'`,
legacy V0 scalar row silently excluded by the `jsonb_typeof` guard,
ordering newest first.
- `LimitClampsResults` — explicit `limit=2` returns the two newest
prompts.
  - `InvalidLimitRejected` — `limit=5000` is `400 Bad Request`.
- `NotFoundForOtherUsers` — a separate user in the same org gets `404`,
not the prompts.
- `EmptyResultIsJSONArray` — zero-message chat and assistant-only chat
both return `Prompts: []` (non-nil, empty).
- `messageParsing.test.ts` adds a unit test asserting that
`getEditableUserMessagePayload(["hello", " ", "world"])` returns `"hello
world"`, locking in the agreement with the SQL `string_agg`.
- `dbauthz_test.go` adds the
`MethodTestSuite.TestChats/GetChatUserPromptsByChatID` entry, asserting
the parent-chat `policy.ActionRead`.

## Out of scope

- Cross-chat history.
- Per-user opt-out for the cycle.
- File-reference / attachment cycling — the cycle still reproduces plain
text only, by design.

</details>

<details>
<summary>coder-agents-review history</summary>

Four review rounds, eight unique findings, all addressed in this PR
(approved twice). Rebased onto `main` twice after R4: first to pick up
new migrations `000491` / `000492`, then again for
`000493_idx_chat_diff_statuses_url_lower`. The prompts-index migration
was renumbered `000491 → 000493 → 000494` via
`coderd/database/migrations/fix_migration_numbers.sh`; no other diff
changes.

| Round | Head | Outcome |
|---|---|---|
| R1 | `725422ab` | `COMMENTED` — 7 findings (DEREM-1..7) |
| R2 | `ab2a8936` | `COMMENTED` — 1 new (DEREM-10) + 1 reraised
(DEREM-5) |
| R3 | `648c5d1f` | **`APPROVED`** — 7 fixed, DEREM-5 deferred via
#25125 |
| R4 | `93b6f450` | **`APPROVED`** — DEREM-5 also fixed in-PR, #25125
closed |

| ID | Where | Resolution |
|---|---|---|
| DEREM-1 | `chats.sql` | Added `jsonb_typeof(content) = 'array'` guard
against V0 scalar rows |
| DEREM-2 | `exp_chats.go` | Removed dead `limit < 0` branch (SDK
rejects upstream) |
| DEREM-3 | `useChatStore.ts` | Rewrote misleading invalidation comment
|
| DEREM-4 | `exp_chats_test.go` | `NewestFirstFiltering` now inserts an
assistant-role message so the `role='user'` filter is exercised
end-to-end |
| DEREM-5 | `messageParsing.ts` | Rewrote
`getEditableUserMessagePayload` to concatenate text parts verbatim,
mirroring the SQL `string_agg` |
| DEREM-6 | `exp_chats.go` | Tightened swagger doc + error message to
spell out the 0–2000 range |
| DEREM-7 | `exp_chats_test.go` | Added `EmptyResultIsJSONArray` subtest
|
| DEREM-10 | `exp_chats_test.go` | `NewestFirstFiltering` now inserts a
raw V0 scalar-content row; verified locally that removing the guard
makes the test fail |

</details>

---

This PR was created on behalf of @ibetitsmike by Coder Agents.
2026-05-14 12:43:12 +02:00
Thomas Kosiewski f71bccf53f ci(.github/actions/setup-node): verify active Node version (#25143)
Updates the shared setup-node composite action to current Node 24 based
releases of `pnpm/action-setup` and `actions/setup-node`. This avoids
the deprecated Node 20 action runtime seen in CODAGT-178 while keeping
the third-party actions pinned by SHA.

Adds an explicit post-setup check that fails inside Setup Node when
`node --version` is not `v22.19.0`, so self-hosted runner/toolcache
mismatches are surfaced before `pnpm install` reports a dependency
engine error.

Closes https://github.com/coder/internal/issues/1457

Generated by Coder Agents.
2026-05-14 12:07:09 +02:00
Danielle Maywood f7d1ecaece refactor(site): inline single-use class string constant in AgentSetupNotice (#25086) 2026-05-14 10:18:50 +01:00
Cian Johnston 581f3bdd14 fix(coderd/httpapi): stop writing websocket frames to ResponseRecorder in test (#25284)
The `mockEventSenderWrite` function in `newOneWayWriter()` wrote
WebSocket frame data to both the `net.Pipe` and the
`httptest.ResponseRecorder`. After `websocket.Accept()` calls
`WriteHeader(101)`, the recorder rejects body writes with `"response
status code does not allow body"`. When `HeartbeatClose` sends a ping,
the control frame flush routes through the recorder, producing an
ERROR-level log that `slogtest` catches as a test failure.

Removed the `recorder.Write(b)` call from the write function. The
recorder is only needed for header/status inspection; WebSocket frame
data should only go through the `net.Pipe`.

Closes https://github.com/coder/internal/issues/1521

> 🤖 Generated by Coder Agents
2026-05-14 09:15:14 +01:00
Jaayden Halko 024132e8a4 feat: add theme_mode, theme_light, theme_dark to UserAppearanceSettings (#25076)
Part 1: Backend portion of a change broken into 2 PRs.
Part 2: #25077 

Adds three new UserAppearanceSettings fields (theme_mode, theme_light,
theme_dark) on top of the existing theme_preference and terminal_font.
Replaces GetUserThemePreference and GetUserTerminalFont with a single
GetUserAppearanceSettings aggregate query. The PUT handler is wrapped in
db.InTx so sync-mode's mode + slot writes can never half-apply.
2026-05-14 05:44:05 +01:00
Ethan d147dd3bdd feat(site/src/pages/AgentsPage/components): show workspace quota in usage indicator (#25168)
This updates the Agents sidebar usage indicator to surface workspace
quota alongside AI spend limits. When both signals are active, the
compact trigger renders stacked bars in the same order as the dropdown
instead of collapsing them into a single percent.

The dropdown still shows the full labels, percentages, and details for
each usage section, and Storybook coverage now exercises the combined
sidebar state.


<img width="315" height="261" alt="image"
src="https://github.com/user-attachments/assets/e5cfc276-2cc0-4dc9-9400-6d1b829e75e2"
/>

<img width="320" height="243" alt="image"
src="https://github.com/user-attachments/assets/506ae8ad-3d93-4857-9cdb-b3cf4142772d"
/>

<img width="314" height="353" alt="image"
src="https://github.com/user-attachments/assets/5af3644f-f155-43a4-bae9-91b33a0a4333"
/>

<img width="322" height="349" alt="image"
src="https://github.com/user-attachments/assets/9ae4ae55-55aa-4a2f-856e-f462793f389e"
/>




Relates to CODAGT-197
2026-05-14 11:59:00 +10:00
Ethan a35f71cd8a fix(coderd/x/chatd): retry HTTP/2 stream resets (#25170)
Mid-stream HTTP/2 peer resets from LLM providers can arrive after a 200
streaming response has already emitted provisional parts. Previously
those resets fell through as generic non-retryable errors because
`stream ID` messages did not match retryable transport signals, and
stream IDs could be misread as HTTP statuses.

Classify retryable HTTP/2 RST_STREAM codes as transient timeout
failures, ignore stream IDs during status extraction, and keep the
existing `retry` event as the rollback boundary for provisional message
parts so replacement attempts do not replay failed-attempt output.

Closes CODAGT-382
2026-05-14 11:40:43 +10:00
Kayla はな 2943bf5f21 fix(site): use ExternalImage for icon URLs (#25315) 2026-05-13 17:52:05 -06:00
Danielle Maywood ef1093d0dd fix(site): hide sticky metadata user messages (#25316) 2026-05-13 22:27:38 +01:00
Nick Vigilante 7aaa8485db docs: update screenshot to point to generic URL (#25314)
At present, the docs point to an internal URL, so I'm updating the
screenshot to point to a ficticious address.

Fixes DOCS-59
2026-05-13 17:20:09 -04:00
Michael Suchacz d1a471e29e fix(coderd/x/chatd): retune subagent selection guidance (#25311)
> Mux working on behalf of Mike.

## Summary

- retune chatd subagent guidance to prefer `general` for substantial
delegated work, including read-only synthesis and planning support
- narrow `explore` guidance to repository-local code lookup and bounded
tracing
- add regression tests for planning, spawn tool, and Plan Mode guidance
text

## Tests

- `go test ./coderd/x/chatd -run
'Test(DefaultSystemPromptPlanningGuidance_SteersSubagentSelection|SpawnAgent_DescriptionSteersGeneralForSubstantialResearch|SpawnAgent_PlanModeDescriptionOmitsComputerUse|PlanningOverlaySubagentGuidance_UsesPlanModeSafeDescriptions|ExploreSubagentIsReadOnly)$'`
- `make lint`
- `make test TEST_PACKAGES=./coderd/x/chatd RUN=Guidance && make test
TEST_PACKAGES=./coderd/x/chatd RUN=Description`
- pre-commit hook during `git commit`
2026-05-13 23:10:21 +02:00
Kayla はな 341051ceee fix: exclude service accounts from license seat count (#24401) 2026-05-13 13:55:53 -07:00
Zach e0be9bf213 feat: surface missing coder_secret requirements on resolve-autostart (#25081)
Adds `dynamicparameters.EvaluateSecretMismatch` as a shared helper on
top of the existing renderer, then wires it into the resolve-autostart
handler so the UI can surface unsatisfied `coder_secret` requirements in
a template alongside parameter mismatch for autostart.

The lifecycle executor changes will land in a follow-up that depend
on this helper. The UI changes that consume the new `secret_mismatch`
field is also a follow-up.

Generated with assistance from Coder Agents.
2026-05-13 14:20:02 -06:00
Steven Masley 0f505aa4da chore: unhide flag to force unix filepaths in config-ssh (#25142)
Docs now include this flag. This flag is now also viewable in linux/mac
despite it effectively being a `no-op`.

Closes https://github.com/coder/coder/issues/24205
2026-05-13 14:59:33 -05:00
Michael Suchacz 38f586107d refactor: remove agents TUI (#25190) 2026-05-13 21:30:11 +02:00
Kayla はな 660fa9478f style(site): use shorthand for boolean JSX props (#25096) 2026-05-13 10:56:50 -06:00
George K 49c6191bbe fix(coderd/azureidentity): add Azure IMDS G2 chain certificates (#25243)
Azure IMDS attested data signatures can now chain through
Microsoft TLS G2 RSA CA OCSP intermediates, then through the
cross-signed Microsoft TLS RSA Root G2 certificate, before reaching
DigiCert Global Root G2.

coderd did not bundle the new G2 OCSP intermediates or the
cross-signed Microsoft TLS RSA Root G2 bridge certificate, so it could
fail to build a trusted chain for affected IMDS signatures.

Related to:
https://linear.app/codercom/issue/PLAT-205/bug-azure-instance-identity-verification-is-broken
2026-05-13 09:07:44 -07:00
Danielle Maywood 7fe4d97fd0 fix(site): align streaming thinking spacing (#25291) 2026-05-13 17:05:34 +01:00
Thomas Kosiewski b9b8d763e3 refactor(site/src/pages/AgentsPage): break AgentChatPage circular dep (#25287)
`AgentChatPageView.tsx` imported `getPersistedSidebarTabId` /
`savePersistedSidebarTabId` from `AgentChatPage.tsx`, which already
imports `AgentChatPageView`, closing a cycle that `pnpm run
lint:circular-deps`
reports but doesn't fail on (dpdm defaults to exit code 0; the script
is missing `--exit-code circular:1`).

Move the three sidebar-tab localStorage helpers and the key prefix into
`utils/sidebarTabStorage.ts` alongside `draftStorage.ts` and the other
per-chat storage modules. Pure code move, no behavior change.

After this change, `pnpm run lint:circular-deps` reports zero cycles.

---------

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 17:13:32 +02:00
Jaayden Halko 36200b625e fix: fix flaky storybook test (#25272) 2026-05-13 16:08:18 +01:00
Kyle Carberry 5040ab6fca feat: filter chats by diff URL via the q search parameter (#24970)
Adds a `diff_url:` term to the `q` search parameter on `GET
/api/experimental/chats` so callers can look up the chat associated with
a particular pull request, merge request, or any other URL persisted on
the chat's diff status.

```
q=diff_url:"https://github.com/coder/coder/pull/123"
```

Match is case-insensitive. When the URL lives on a delegated sub-agent's
diff status, the parent chat is returned so the relationship surfaces
from a single lookup.

<details>
<summary>Design notes</summary>

- **Forge-agnostic.** Reuses the existing `chat_diff_statuses.url`
column rather than introducing a `pr:` vocabulary, since the SDK already
documents the URL as "may point to a pull request or a branch page
depending on whether a PR has been opened." Works for GitHub PRs, GitLab
MRs, branch pages, etc.
- **Composes with `archived:`.** The two terms can be combined:
`q=archived:true diff_url:"..."`.
- **Case handling.** The parser used to lowercase the entire `q` string
up front, which would mangle URL path segments. Switched to lowercasing
only the field key inside `searchTerms` (already happens there) and
keeping the value as the caller typed it. The SQL comparison lowercases
on both sides.
- **Validation.** `diff_url` must be a syntactically valid HTTP(S) URL
with a non-empty host. No forge-specific validation.
- **Index.** Adds `idx_chat_diff_statuses_url_lower` on `LOWER(url)` so
the lookup is cheap even on large datasets.
- **Sub-agent fan-in.** `EXISTS` clause matches when the URL lives on
the chat itself or any chat with `root_chat_id` equal to the chat's id,
so a delegated sub-agent's PR pulls in its parent.
- **Deferred.** Sentinels like `pr:any` / `pr:none` and a forge-agnostic
state filter (`diff_state:open|merged|closed`) were intentionally left
out of this change. They couple cleanly to a second forge or a clearer
product call, and shipping them now would lock in vocabulary we may want
to revisit.

</details>

## Tests

- `coderd/searchquery`: parser tests for valid URLs, case handling (key
insensitive, value preserved), composition with `archived:`, and
validation errors (non-HTTP scheme, missing host, malformed URL).
- `coderd/exp_chats_test.go`: end-to-end coverage hitting `ListChats`.
Verifies a root chat matches its own URL, a parent chat surfaces when
only a sub-agent has the URL, lookups are case-insensitive, non-matching
URLs return empty, and invalid URLs return `400`.

---

_This PR was authored by a Coder Agent on behalf of @kylecarbs._
2026-05-13 11:06:42 -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
Jakub Domeracki 1a1f06aa79 fix: verify PKCS7 signature on Azure instance identity tokens (#25286)
Migrates Azure instance identity verification from
`go.mozilla.org/pkcs7` and `github.com/fullsailor/pkcs7` to
`github.com/smallstep/pkcs7`, using `VerifyWithChainAtTime` to validate
both the PKCS7 signature and the certificate chain in one call. The
previous code only verified the signer certificate against a set of
intermediates/roots but did not verify that the PKCS7 signature itself
covered the content, meaning tampered payloads could be accepted.

The `Options` struct is restructured to accept `Roots`, `Intermediates`,
and `CurrentTime` as explicit fields instead of embedding
`x509.VerifyOptions`. The test helper `NewAzureInstanceIdentity` now
builds a realistic 3-level certificate chain (Root CA -> Intermediate CA
-> Signing Cert) matching real Azure trust hierarchy. New tests
(`TestValidate_TamperedContent`,
`TestValidate_UntrustedCertWithValidSignature`) confirm tampered and
untrusted envelopes are rejected.

Addresses GHSA-6x44-w3xg-hqqf.

> [!NOTE]
> This PR was authored by Coder Agents.

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

### Files Changed

| File | Summary |
|------|---------|
| `coderd/azureidentity/azureidentity.go` | Replace `signer.Verify()`
with `VerifyWithChainAtTime`; restructure `Options` struct; add
`ParseCertificates()` helper |
| `coderd/azureidentity/azureidentity_test.go` | Add `testCertChain`
builder, tampered-content and untrusted-cert tests; update existing
tests for new `Options` API |
| `coderd/coderd.go` | Change `AzureCertificates` field from
`x509.VerifyOptions` to `azureidentity.Options` |
| `coderd/workspaceresourceauth.go` | Pass `api.AzureCertificates`
directly instead of wrapping |
| `coderd/coderdtest/coderdtest.go` | Migrate to `smallstep/pkcs7`;
build 3-level cert chain in test helper |
| `go.mod` / `go.sum` | Add `github.com/smallstep/pkcs7`; remove
`fullsailor/pkcs7` and `go.mozilla.org/pkcs7` |

</details>
2026-05-13 14:14:07 +00:00
Danielle Maywood b52c0bdb56 fix(site/src/pages/AgentsPage/components): unify live thinking spacing and sizing (#25192) 2026-05-13 12:51:49 +01:00
Jakub Domeracki 57b11d405f fix(coderd): harden Azure identity certificate fetch (#25274)
Security improvements:
- Restrict cert fetches to a host+port allowlist (Microsoft and DigiCert
on 80/443).
- Route requests through a dedicated `http.Client` that resolves the
host once and dials the validated IP directly, preventing DNS rebinding.
- Reject loopback, private (RFC 1918 / IPv6 ULA), link-local, multicast,
unspecified, CGNAT, benchmarking, and IPv4-mapped IPv6 addresses.
- Cap the certificate response body at 1 MiB.
- Log the underlying error via slog and return a generic detail to the
caller to prevent information disclosure.
2026-05-13 12:51:44 +02:00
Jakub Domeracki 9400eaa957 revert(coderd): "Merge commit from fork" (#25273)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:10:27 +02:00
Mathias Fredriksson 5b87d7b74f feat(agent/agentcontextconfig): discover skills from ~/.coder/skills (#25271)
The default skills lookup only scanned the project-relative
.agents/skills directory, so personal skills had to be repeated
per project or wired in via CODER_AGENT_EXP_SKILLS_DIRS. Now the
default is the comma-separated list ~/.coder/skills,.agents/skills,
which lets discoverSkills's existing first-occurrence-wins policy
prefer home-scoped skills over project ones with the same name.

The change is additive when ~/.coder/skills is absent
(missing directories are silently skipped in discoverSkills) and
unaffects users who set the env var explicitly.

Closes CODAGT-403
2026-05-13 12:56:24 +03:00
Jakub Domeracki fb3aef1883 Merge commit from fork
* fix(coderd): Harden Azure identity certificate fetch

- Restrict cert fetches to a host+port allowlist (Microsoft and
  DigiCert on 80/443).
- Route requests through a dedicated `http.Client` that resolves
  the host once and dials the validated IP directly.
- Reject loopback, private (RFC 1918 / IPv6 ULA), link-local,
  multicast, unspecified, CGNAT, benchmarking, and IPv4-mapped
  IPv6 addresses.
- Cap the certificate response body at 1 MiB.
- Log the underlying error via slog and return a generic detail
  to the caller.
- Add unit tests for the URL allowlist, IP classification, and
  dialer.

* fix(coderd/azureidentity): add IPv6 special-use ranges to SSRF blocklist

The extraBlockedNetworks list only contained IPv4 CIDRs. Add IPv6
equivalents that Go's stdlib classification methods do not cover:

  - 64:ff9b:1::/48  RFC 8215 NAT64 translation
  - 100::/64         RFC 6666 discard-only
  - 2001:2::/48      RFC 5180 benchmarking
  - 2001:db8::/32    RFC 3849 documentation

IPv6 ranges already handled by stdlib (unchanged):

  - ::1/128   (IsLoopback)
  - fc00::/7  (IsPrivate, ULA)
  - fe80::/10 (IsLinkLocalUnicast)
  - ff00::/8  (IsMulticast)
  - ::/128    (IsUnspecified)
2026-05-13 11:55:41 +02:00
Danielle Maywood 5be959e111 fix(agent): retry devcontainer sub-agent rejection test (#25187) 2026-05-13 10:22:51 +01:00
Ethan 8955599bd0 fix: bump sqlc fork to v1.31.1 merge, strip pg_dump meta-commands (#25105)
Closes https://github.com/coder/internal/issues/965

Recent `pg_dump` patch releases (13.22+ / 14.19+ / 15.14+ / 16.10+ /
17.6+) emit `\restrict` / `\unrestrict` psql meta-commands at the head
and tail of schema dumps. These broke both `sqlc` and our
`scripts/migrate-test` schema-equality check. PR #19696 worked around it
by pinning `pg_dump` to a Docker image.

This change unpins the workaround now that `sqlc` handles the
meta-commands:

* Bumps the coder/sqlc fork pin to [`337309b` on
coder/sqlc:main](https://github.com/coder/sqlc/commit/337309bfb9524f38466a5090e310040fc7af0203),
the merge of upstream v1.31.1 (coder/sqlc#6). v1.31.1 includes
[sqlc-dev/sqlc#4390](https://github.com/sqlc-dev/sqlc/pull/4390), the
upstream `\restrict` / `\unrestrict` parser fix. Updated in three places
that pin the fork SHA: `flake.nix` (`sqlc-custom`),
`.github/actions/setup-sqlc/action.yaml`, and the
`dogfood/coder/ubuntu-{22,26}.04` Dockerfiles. The flake's `sha256` /
`vendorHash` are reset to `pkgs.lib.fakeSha256`; Nix will surface the
real hashes on first build, per the existing comment block.
* Reverts #19696's Docker pin in `coderd/database/dbtestutil/db.go`.
Local `pg_dump` (13+) and the `postgres:13` Docker fallback both work
again.
* Strips `\restrict` / `\unrestrict` lines in `normalizeDump` so
`scripts/migrate-test`'s schema comparison is stable across `pg_dump`
versions (the token in those lines is randomized per run).
`TestNormalizeDumpStripsRestrict` locks the behavior in.
* Regenerates with v1.31.1, picking up the version stamp and one
upstream correctness fix in `DeleteLicense`
([sqlc-dev/sqlc#4383](https://github.com/sqlc-dev/sqlc/pull/4383): don't
shadow the input parameter when scanning a single-column return).
2026-05-13 18:55:24 +10:00
dependabot[bot] eedde58b55 chore: bump protobufjs from 7.5.5 to 7.5.6 in /site (#25222)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.5.5
to 7.5.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/releases">protobufjs's
releases</a>.</em></p>
<blockquote>
<h2>protobufjs: v7.5.6</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.5...protobufjs-v7.5.6">7.5.6</a>
(2026-04-27)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Backport input hardening and CLI fixes to 7.x (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2173">#2173</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/75392ea1b78bdc4faba027b5db44ad7c50e9c454">75392ea</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/blob/protobufjs-v7.5.6/CHANGELOG.md">protobufjs's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.5...protobufjs-v7.5.6">7.5.6</a>
(2026-04-27)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Backport input hardening and CLI fixes to 7.x (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2173">#2173</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/75392ea1b78bdc4faba027b5db44ad7c50e9c454">75392ea</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.4">7.5.4</a>
(2025-08-15)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760">5a3769a</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.2...protobufjs-v7.5.3">7.5.3</a>
(2025-05-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>descriptor extensions handling post-editions (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2075">#2075</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6e255d4ad6982cc857f26e1731c2cedcf5796f68">6e255d4</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.1...protobufjs-v7.5.2">7.5.2</a>
(2025-05-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>ensure that types are always resolved (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2068">#2068</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/4b51cb2b8450b77f9f5de1c562e7fae93b19d040">4b51cb2</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.0...protobufjs-v7.5.1">7.5.1</a>
(2025-05-08)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>optimize regressions from editions implementations (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2066">#2066</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6406d4c18afae309fc7b5f4a24d9674d85da180b">6406d4c</a>)</li>
<li>reserved field inside group blocks fail parsing (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2058">#2058</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/56782bff0c4b5132806eb1a6bc4d08f930c4aaad">56782bf</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.0">7.5.0</a>
(2025-04-15)</h2>
<h3>Features</h3>
<ul>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/f04ded3a03a3ddd383f0228e2fe2627a51f31aa3">f04ded3</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/ac9a3b9fe3134d48187e41b08d54ffaceddc6c1b">ac9a3b9</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/e5ca5c84e326699e10258367883a54934e0bfe14">e5ca5c8</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a84409b47f9ba0dba56da1af8054fb54f85d85a1">a84409b</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/9c5a178c4b59e0aa65ecac0bd7420171213b2ff9">9c5a178</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/b2c686721e3b63d092419fa1cbe58e1deb89534e">b2c6867</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/60f3e51087ca2c247473410f39331e1c766aefef">60f3e51</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a6563617de04d510d6e8865eb6c5067f10247f64">a656361</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/869a95b1e5f553c76243aac45619061407a41084">869a95b</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/2189e5beeca6a70e4c104dfdb9fb8200bc5f81fe"><code>2189e5b</code></a>
chore: release protobufjs-v7.x (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2174">#2174</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/75392ea1b78bdc4faba027b5db44ad7c50e9c454"><code>75392ea</code></a>
fix: Backport input hardening and CLI fixes to 7.x (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2173">#2173</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/8af8d7c0e9800879625f7d0d4a7fb51beb4410cd"><code>8af8d7c</code></a>
chore(ci): Fix 7.x release please configuration (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2169">#2169</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/e92ca42244ad67203b48d836290062dae037ead6"><code>e92ca42</code></a>
chore(ci): Enable release-please for 7.x (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2166">#2166</a>)</li>
<li>See full diff in <a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.5...protobufjs-v7.5.6">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for protobufjs since your current version.</p>
</details>
<br />


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

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

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

---

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

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/coder/coder/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 20:29:06 +00:00
Seth Shelnutt f355e010e8 fix(coderd/database): clean up org memberships when user is soft-deleted (#25149)
The soft-delete cleanup trigger (`delete_deleted_user_resources`)
removed `api_keys`, `user_links`, and `user_secrets` but left
`organization_members` rows intact. When a new user was created with a
previously-deleted user's email, both user IDs had org membership rows
in the same organization, producing duplicate-email members.

Extend the trigger to also delete `organization_members` for the
soft-deleted user. This cascades through the existing
`trigger_delete_group_members_on_org_member_delete`, which cleans up
group memberships automatically. The migration backfills by removing
zombie rows for already-deleted users.

Fixes ENG-831

> [!NOTE]
> 🤖 Generated by Coder Agents

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

**Root cause**: `GetOrganizationIDsByMemberIDs` does not join on
`users.deleted = false`, so stale org membership rows for soft-deleted
users were visible to internal queries. Even the filtered queries
(`OrganizationMembers`, `PaginatedOrganizationMembers`) could surface
duplicate emails when a new active user reused a deleted user's email.

**What changed**:
- Migration 000491 extends `delete_deleted_user_resources()` to `DELETE
FROM organization_members WHERE user_id = OLD.id`
- Backfill removes existing zombie org memberships for soft-deleted
users
- `TestOrgMembersSoftDeleteTrigger` covers org membership removal, raw
row cleanup, and cascading group membership cleanup
</details>
2026-05-12 16:20:25 -04:00
Kayla はな 9810d299d2 chore: make dynamic parameters TemplateEmbedPage the default (#25069) 2026-05-12 18:28:36 +00:00
Nick Vigilante 36d52ba504 feat(.github/workflows): trigger Algolia, ISR, and Vercel deploy on docs/** changes (#25049)
Folds the Algolia/ISR sync trigger and surgical-reindex path computation
into the existing `deploy-docs.yaml` workflow so a single `docs/**` push
fires every update path the docs site needs.

One preflight job feeds two parallel sibling jobs:

- **`changes`** (preflight): diffs `github.event.before` against
`github.sha` to compute `manifest_changed` and `paths_json` (a JSON
array of `{path, status}` objects derived from `git diff --name-status
-z`, capped at 50 entries). The mapping is `A → added`, `M/T →
modified`, `D → deleted`, `R<n> → renamed` (indexed by the new path).
Falls back to whole-branch (emits `paths_json: "[]"`) on
`workflow_dispatch`, the first push to a new branch, fetch failure,
manifest changes (route restructuring would orphan records), or >50
markdown files.
- **`algolia-and-isr`** (always, parallel with `vercel-rebuild`):
HMAC-signed POST to `coder.com/api/algolia-docs-sync` with the
`paths_json` array as part of the body. Refreshes the Algolia `docs`
slice for the `(corpus, ref)` pair and ISR-revalidates every navigable
route the handler touched. Markdown-only edits surface in seconds with
no full rebuild. The step summary line `Mode: \`surgical\` (N path(s))`
lets operators verify which path ran without scrolling through the curl
output.
- **`vercel-rebuild`** (parallel with `algolia-and-isr`, only when
`docs/manifest.json` changed): fires the existing Vercel deploy hook for
a full build. Manifest changes can register or remove routes that
Next.js's `getStaticPaths` only re-evaluates on a full build, so
ISR-per-existing-path is not enough.

Trigger expanded from "main + manifest.json" to "main and `release/*` +
any `docs/**`" so release-branch docs edits also flow through the same
pipeline. The Vercel rebuild path stays gated on manifest changes
regardless of branch.

The pure shell + curl + openssl + jq + awk pipeline is preserved
verbatim. Zero Algolia or Node dependencies in CI.

## Why one workflow instead of two

The original split (a standalone Algolia workflow + the existing
`deploy-docs.yaml`) would have run twice per manifest push, with two
parallel concurrency groups, two GitHub Actions step summaries, and two
ways to forget to add a secret. Folding into one file makes the trigger
story symmetrical: "docs change → all docs surfaces refresh," with the
rebuild path being a strict superset of the ISR path, and the surgical
path strictly cheaper than whole-branch when computable.

## Pre-merge testing

The companion handler PR (coder/coder.com#741) supports an
`ALGOLIA_DOCS_INDEX` env-var override, scoped to `docs_smoke` on the
Vercel preview deploy, so this workflow can be exercised end-to-end
against a disposable index without touching production records. The
smoke harness at `~/audit/smoke/run.sh` (workspace-only) signs and posts
the same body shape this workflow does, so it covers the same crypto
path. To exercise the workflow itself, push a docs-only commit to a
throwaway branch and watch the step summary; the `algolia-and-isr` job
will print the resolved mode.

## Prerequisites before this can do anything useful

1. `secrets.ALGOLIA_DOCS_SYNC_SECRET` must be added as an Actions secret
on this repo. The same value goes on `coder.com`'s Vercel env. The
workflow logs a clear error and aborts with no network call if the
secret is missing.
2. The handler at coder/coder.com#741 must be merged and deployed.
Without it, the POST will 404.
3. `secrets.DEPLOY_DOCS_VERCEL_WEBHOOK` is already in place from the
existing `deploy-docs.yaml`; this PR does not change its usage.

## Demo, validation, and design

- Front-end-only fixes (modal layout, scroll-shadow, rank-order
preservation): coder/coder.com#749 ships these against production today,
independent of this PR.
- Companion handler PR on `coder.com`: coder/coder.com#741. Includes the
surgical-mode plumbing this workflow's `paths_json` output drives.
- Full design lives in the workspace at
`~/plans/algolia-search-revamp.md`. Key sections:
  - §6.0–6.2: why the indexer lives in `coder.com`, not here.
  - §6.7: per-version add/remove mechanics.
  - §6.8: ISR revalidate rationale and same-time refresh.
- §6.9: surgical per-page reindex (workflow + handler + planning rules).

---

This PR was generated by Coder Agents.
2026-05-12 14:18:31 -04:00
Ben Potter 5e44c71305 docs: call out coder/skills setup skill on install and quickstart pages (#25194)
<!--

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-05-12 12:36:00 -05:00
dependabot[bot] 4b54925abc chore: bump the x group across 1 directory with 7 updates (#25198)
Bumps the x group with 4 updates in the / directory:
[golang.org/x/crypto](https://github.com/golang/crypto),
[golang.org/x/mod](https://github.com/golang/mod),
[golang.org/x/net](https://github.com/golang/net) and
[golang.org/x/tools](https://github.com/golang/tools).

Updates `golang.org/x/crypto` from 0.50.0 to 0.51.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/crypto/commit/b8a14a8d65f88c0c79c139171f1354c69a6cdb8a"><code>b8a14a8</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/crypto/commit/9d9d5078968ddb8a279092c665a24e7de4178778"><code>9d9d507</code></a>
x509roots/fallback/bundle: fix bundle test with Go 1.27+</li>
<li><a
href="https://github.com/golang/crypto/commit/fd0b90d21f9ab4b5dd398e9526b570bfea86e370"><code>fd0b90d</code></a>
acme: include Problem in OrderError.Error</li>
<li><a
href="https://github.com/golang/crypto/commit/b9e53593a6073e6a786c49e9ad27956a9b77e54e"><code>b9e5359</code></a>
pbkdf2: turn into a wrapper for crypto/pbkdf2</li>
<li><a
href="https://github.com/golang/crypto/commit/cc0e4fc1d49127130b0d00612a2eeed2ab745d40"><code>cc0e4fc</code></a>
hkdf: forward Extract to the standard library</li>
<li><a
href="https://github.com/golang/crypto/commit/a8e9237a216b050e1b11e041863825104a6811db"><code>a8e9237</code></a>
x509roots/fallback: update bundle</li>
<li>See full diff in <a
href="https://github.com/golang/crypto/compare/v0.50.0...v0.51.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/mod` from 0.35.0 to 0.36.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/mod/commit/643da9ba74f1165d8cae1505d453b3de3cf21b7b"><code>643da9b</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/mod/commit/ccc3cdf529d1eee2a832437eb1b85240044d21cb"><code>ccc3cdf</code></a>
zip: include 'but content has correct sum' note in TestVCS</li>
<li><a
href="https://github.com/golang/mod/commit/ab3031803214705d2c9f1102318b083e7086a155"><code>ab30318</code></a>
zip: update zip hashes for new flate compression</li>
<li>See full diff in <a
href="https://github.com/golang/mod/compare/v0.35.0...v0.36.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/net` from 0.53.0 to 0.54.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/net/commit/b138e06246cb323f2f380c2b7f7dd91f581dd56b"><code>b138e06</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/net/commit/689f70a42abd350f3a1aaa70b0d13eb9543d927a"><code>689f70a</code></a>
quic: fix wrong final size being used for RESET_STREAM frame</li>
<li><a
href="https://github.com/golang/net/commit/208f306b2f0fd008b388bee2c2644be279778e94"><code>208f306</code></a>
http3: increase handshake timeout</li>
<li><a
href="https://github.com/golang/net/commit/49810da71b9026da9e0d028a6ad8c7730c52d9c4"><code>49810da</code></a>
http2: enable net/http wrapping when go &gt;= 1.27</li>
<li><a
href="https://github.com/golang/net/commit/5e11a5ab891c117eda83b4304d60dd13286c1c76"><code>5e11a5a</code></a>
quic: fix data race in streamForFrame</li>
<li><a
href="https://github.com/golang/net/commit/8c63081cd380ea768db5651941614b73472160ff"><code>8c63081</code></a>
http2: use empty Transport rather than DefaultTransport in
http2wrap</li>
<li><a
href="https://github.com/golang/net/commit/fc7b466ca49cb204039630533ece4fc557eb35cd"><code>fc7b466</code></a>
http2: add http2wrap test</li>
<li><a
href="https://github.com/golang/net/commit/15c2cb1875fd727313dc4de909b3ee149422fbe2"><code>15c2cb1</code></a>
http2: avoid overflowing 32-bit int when http2wrap enabled</li>
<li><a
href="https://github.com/golang/net/commit/64651885c2f2d745d77af2d7af2edbf568c179af"><code>6465188</code></a>
http2: add wrapped Server</li>
<li><a
href="https://github.com/golang/net/commit/72f419a894cb0597dd5b6bcf119086bf2af41231"><code>72f419a</code></a>
http2: add wrapped ClientConn</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/net/compare/v0.53.0...v0.54.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/sys` from 0.43.0 to 0.44.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/sys/commit/fb1facd76f95fa87c151018200ea5e4892ff115d"><code>fb1facd</code></a>
windows: avoid uint16 overflow in NewNTUnicodeString</li>
<li><a
href="https://github.com/golang/sys/commit/94ad893e1e59c1d079221324d38945d2aad8703f"><code>94ad893</code></a>
windows: add GetIfTable2Ex, GetIpInterface{Entry,Table},
GetUnicastIpAddressT...</li>
<li><a
href="https://github.com/golang/sys/commit/54fe89f8411576c06b345b341ca79a77d878a4ad"><code>54fe89f</code></a>
cpu: use IsProcessorFeaturePresent to calculate ARM64 on windows</li>
<li><a
href="https://github.com/golang/sys/commit/df7d5d7b60641d17d87e2b50911124cb65f954fd"><code>df7d5d7</code></a>
unix: automatically remove container created by mkall.sh</li>
<li><a
href="https://github.com/golang/sys/commit/68a4a8e945b22751c1a619261b1d755372a1d5f7"><code>68a4a8e</code></a>
unix: avoid nil pointer dereference in Utime</li>
<li><a
href="https://github.com/golang/sys/commit/690c91f6ecf3b3ef141ad2aedb1306a868b3a176"><code>690c91f</code></a>
unix: add CPUSetDynamic for systems with more than 1024 CPUs</li>
<li>See full diff in <a
href="https://github.com/golang/sys/compare/v0.43.0...v0.44.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/term` from 0.42.0 to 0.43.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/term/commit/3c3e4855f7d2eb06c3e48933554add9ec6b599b5"><code>3c3e485</code></a>
go.mod: update golang.org/x dependencies</li>
<li>See full diff in <a
href="https://github.com/golang/term/compare/v0.42.0...v0.43.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/text` from 0.36.0 to 0.37.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/text/commit/3ef517e623a4bfc08d6457f87d73afda7af7d8e1"><code>3ef517e</code></a>
go.mod: update golang.org/x dependencies</li>
<li>See full diff in <a
href="https://github.com/golang/text/compare/v0.36.0...v0.37.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/tools` from 0.44.0 to 0.45.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/tools/commit/2aabba0e4be44cc8f254ced118a7156d04bbc9f3"><code>2aabba0</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/tools/commit/ef989b3f45baff2849e87f4a70d9a189be5a6959"><code>ef989b3</code></a>
go/types/internal/play: show Info.Instances[Ident]</li>
<li><a
href="https://github.com/golang/tools/commit/21d44f2f2bb3f3a8e06e35523d14bb70cb275c89"><code>21d44f2</code></a>
go/analysis/passes/inline: document skipping of TestF-&gt;F calls</li>
<li><a
href="https://github.com/golang/tools/commit/ec83c2190d81a18bbd472cc1498575b168017e5d"><code>ec83c21</code></a>
go/analysis/passes/modernize: minmax: only remove exact userdefined</li>
<li><a
href="https://github.com/golang/tools/commit/5625353d39195f1deb9261c5ee983abbdc4a15ca"><code>5625353</code></a>
go/analysis/passes/modernize: improve value variable name
generation</li>
<li><a
href="https://github.com/golang/tools/commit/15a3bd5d4ce0651f5cf43ea125db2110c67b257b"><code>15a3bd5</code></a>
gopls/internal/analysis/errorsastype: imporove example clarity</li>
<li><a
href="https://github.com/golang/tools/commit/cd57ef8f8dd7a30ef500bfe1eef0779223cbdfc3"><code>cd57ef8</code></a>
go/packages: include dependency errors when CompiledGoFiles is
missing</li>
<li><a
href="https://github.com/golang/tools/commit/053fdbcef55e8f977d8decc0fde2920c61eb5374"><code>053fdbc</code></a>
go/analysis/passes/modernize: minmax: fix pure operands only</li>
<li><a
href="https://github.com/golang/tools/commit/bf84681c4a0185014c089cffd533e22bbeffcb49"><code>bf84681</code></a>
go/analysis/passes/errorsas: add example of invalid errors.As use</li>
<li><a
href="https://github.com/golang/tools/commit/23921d1decfe5da40309ac183353c8cb38b03dfa"><code>23921d1</code></a>
gopls: add errorsastype analyzer</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/tools/compare/v0.44.0...v0.45.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 17:33:46 +00:00