mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
29775edf9598c876adf438da3f77f75eb00e052d
14285 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
29775edf95 |
docs(.claude/skills/svg-docs-diagrams): add programmatic overlap checker
The skill now leads with a programmatic overlap-and-overflow check that runs in under a second and catches the failures that the eyeball pass kept missing: text bleeding past a card, two cards intersecting, an arrow label sitting on top of a card title or zone subtitle, two texts colliding. The checker loads the SVG in headless Chrome and uses real getBBox() measurements via puppeteer-core, so the verdict matches what readers see at render time. Exit code 0 means clean; non-zero lists each finding with element coordinates and the rule it violated, which is what you need to fix it without screenshotting. Updated SKILL.md to put the programmatic check first in the test loop, with the eyeball pass as the backup. Added the checker to the pre-commit checklist and the Related files section. |
||
|
|
f6088d3b52 |
docs(.claude/skills/svg-docs-diagrams): skill for authoring SVG docs diagrams
Captures the conventions learned while iterating on the Claude Code self-hosted runners diagrams: * viewBox sizing for the ~657 CSS-pixel docs prose column, with a table mapping viewBox font sizes to on-page font sizes. * The 'paint-order: stroke' white halo pattern for arrow labels so they stay readable over zone-tinted backgrounds. * Card title wrapping rules so titles don't overflow a 144 px card. * Locked-to-one-user badge and per-instance suffix conventions for surfacing the things readers most need to see. * A reproducible test loop: render the docs page (not the raw SVG) with a copy-pastable headless Chrome script, then verify the click-through full-size view with a computer_use subagent. * Pitfalls: subagents reusing stale screenshots, Next.js asset caching, and headless Chrome rendering SVGs at sub-natural width when the file is opened directly. Ships with two reference files: 'render-diagram.sh' (a cache-busting docs-page screenshot script) and 'template.svg' (a starter SVG with all conventions baked in). |
||
|
|
2943bf5f21 | fix(site): use ExternalImage for icon URLs (#25315) | ||
|
|
ef1093d0dd | fix(site): hide sticky metadata user messages (#25316) | ||
|
|
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 |
||
|
|
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` |
||
|
|
341051ceee | fix: exclude service accounts from license seat count (#24401) | ||
|
|
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. |
||
|
|
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 |
||
|
|
38f586107d | refactor: remove agents TUI (#25190) | ||
|
|
660fa9478f | style(site): use shorthand for boolean JSX props (#25096) | ||
|
|
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 |
||
|
|
7fe4d97fd0 | fix(site): align streaming thinking spacing (#25291) | ||
|
|
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> |
||
|
|
36200b625e | fix: fix flaky storybook test (#25272) | ||
|
|
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._ |
||
|
|
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> |
||
|
|
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> |
||
|
|
b52c0bdb56 | fix(site/src/pages/AgentsPage/components): unify live thinking spacing and sizing (#25192) | ||
|
|
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. |
||
|
|
9400eaa957 |
revert(coderd): "Merge commit from fork" (#25273)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
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) |
||
|
|
5be959e111 | fix(agent): retry devcontainer sub-agent rejection test (#25187) | ||
|
|
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). |
||
|
|
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 /> [](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> |
||
|
|
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>
|
||
|
|
9810d299d2 |
chore: make dynamic parameters TemplateEmbedPage the default (#25069)
|
||
|
|
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.
|
||
|
|
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. --> |
||
|
|
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 >= 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->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> |
||
|
|
0234422a55 |
chore: bump google.golang.org/api from 0.277.0 to 0.278.0 (#25201)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.277.0 to 0.278.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's releases</a>.</em></p> <blockquote> <h2>v0.278.0</h2> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.277.0...v0.278.0">0.278.0</a> (2026-05-05)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3582">#3582</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/76b1187e506ac0f48caac67907dd0805b253f74c">76b1187</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3584">#3584</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/e36c88361d11545583325c3ac6bdbd9cf1f1a7d0">e36c883</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.277.0...v0.278.0">0.278.0</a> (2026-05-05)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3582">#3582</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/76b1187e506ac0f48caac67907dd0805b253f74c">76b1187</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3584">#3584</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/e36c88361d11545583325c3ac6bdbd9cf1f1a7d0">e36c883</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/googleapis/google-api-go-client/commit/07c758daacbc24e32753c3f1b537c7f6cce626f0"><code>07c758d</code></a> chore(main): release 0.278.0 (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3583">#3583</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/e36c88361d11545583325c3ac6bdbd9cf1f1a7d0"><code>e36c883</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3584">#3584</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/76b1187e506ac0f48caac67907dd0805b253f74c"><code>76b1187</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3582">#3582</a>)</li> <li>See full diff in <a href="https://github.com/googleapis/google-api-go-client/compare/v0.277.0...v0.278.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
969da320ec |
feat: export Coder Agents debug logs (#25039)
Adds JSON export actions to the Coder Agents Debug panel so users can download either the current chat's recent debug runs or one expanded run for support sharing. The export reuses the existing chat debug endpoints and react-query cache, adds Storybook and unit coverage for the JSON envelope, and updates the chat debug logging docs with UI and cURL instructions. Refs CODAGT-280. Generated by Coder Agents. <details> <summary>Implementation notes</summary> - Chat-level export fetches full detail for each listed debug run with `queryClient.fetchQuery(chatDebugRun(chatId, run.id))` and writes a single JSON file. - Run-level export uses the already-loaded detail query data from an expanded run card. - The JSON envelope includes `version`, `scope`, `exported_at`, `chat_id`, and either `runs` or `run`. - The chat-level export reflects the current backend list endpoint behavior, up to the 100 newest debug runs. - Agent-browser dogfooding verified files were downloaded and that `jq` validated the chat-level and run-level JSON contents. </details> |
||
|
|
147f50c5e8 |
fix(agent/x/agentmcp): watch MCP config files for late-appearing or rewritten config (#25172)
## Bug `agent/x/agentmcp/Manager` resolves its config paths once at boot, calls `Reload`, and then only re-stats them lazily when a `GET /api/v0/mcp/tools` request arrives (PR #24700). If any of the manager's MCP config files (`~/.mcp.json` by default, or whatever paths `agentcontextconfig.MCPConfigFiles()` resolves from `CODER_AGENT_EXP_MCP_CONFIG_FILES`) is created, atomically rewritten, or removed _after_ that initial `Reload` and _before_ the next tools HTTP request, the manager keeps serving the stale (often empty) snapshot. `parseAndDedup` silently swallows `fs.ErrNotExist`, so a late-appearing file looks indistinguishable from "no config" until something pokes the manager again. This affects any workspace where the file lands after `MarkStartupSettled` fires, including: - a startup script that writes `~/.mcp.json` after MCP init - a user creating or editing the file mid-session - an installer, dotfiles step, or sync tool writing the file later in startup - another agent process (Claude Code, etc.) producing the file out-of-band - editor rewrites that land as `Write + Chmod + Rename` bursts ### Concrete repro (dual-agent workspace) The race is easiest to reproduce on dual-agent workspaces (inner sandbox + outer host), where the inner agent's `scriptRunner` has `script_count=0` and `mcpManager.Reload` fires at ~t+0.3 s while the host agent writes `~/.mcp.json` ~21 s later. Timeline from `workspace-otto-aa16`: - agent up `20:23:38.918` - lifecycle Ready `20:23:39.200` - MCP config file Birth `20:24:00.460` (~21 s gap) - no MCP log lines for 8 minutes - first `GET /api/v0/mcp/tools` at `20:32:11.812` logs `[warn] mcp: mcp reload canceled by caller`, takes 4946 ms; subsequent turns are cached at 2 ms. The single-agent case has the same race; it's just usually narrow enough that the next HTTP request masks it, at the cost of a multi-second stall on the first call that has to do the lazy reload itself. PR #25034's `MarkStartupSettled` does not help: "settled" fires before the file is necessarily on disk. ## Fix Add an fsnotify-backed `configWatcher` to `agent/x/agentmcp/Manager`. The watcher consumes whatever paths the manager is told to reload, which is the same `[]string` returned by `agentcontextconfig.MCPConfigFiles()`. For each path the watcher: - Watches the **parent directory** of the path, not the file itself. This handles late creation, atomic rewrite (rename + create), and deletion uniformly because inotify watches on individual non-existent files return `ENOENT` and are lost across renames. The pattern matches `agent/agentcontainers/watcher`. - Walks up to the first existing **ancestor directory** when the parent does not yet exist, and re-arms deeper on `Create` events that promote an unrealized path. - Refcounts directory watches so multiple configured paths sharing a parent dir only register one inotify watch. - Resolves symlinks **once at arming time** via `filepath.EvalSymlinks`; never chases arbitrary symlink targets on events. - Debounces multi-event editor writes through a single `quartz.AfterFunc` timer so a `Write + Chmod + Rename` burst produces one reload. - Fires a debounced callback that calls `Manager.Reload`, which routes through the existing singleflight so concurrent triggers coalesce. - Re-syncs on every `Reload` call so a future path-list change is picked up. Lifecycle: the watcher is armed lazily on the first `Reload` (no goroutine cost for unit tests that never reload). `Manager.Close` marks the manager closed and closes its `closedCh` before tearing down the watcher, so any in-flight watcher-driven reload observes the close via `waitReload` and returns `ErrManagerClosed` instead of blocking `firesWG.Wait()` on a stuck connect. The watcher then waits for its goroutine and any in-flight debounced `fire` callback before returning. `parseAndDedup` behavior is unchanged: `fs.ErrNotExist` still records an empty snapshot. With the watcher armed before that snapshot is committed, any `Create` event that races `parseAndDedup` is still delivered. This is the agent-side complement to PR #25169, which fixes chatd's mid-turn workspace MCP discovery. `MarkStartupSettled` semantics are not changed. ## Tests (`agent/x/agentmcp/configwatcher_internal_test.go`) All new tests pass with the fix and fail without it. No `time.Sleep`; synchronization uses `testutil.Eventually` for fsnotify-driven assertions and the quartz mock clock for debounce assertions. - `TestWatcher_LateFileTriggersReload` - the late-file regression: empty dir, settle startup, `Reload` sees no file, write the file later, watcher reloads, tools appear. - `TestWatcher_RewriteTriggersReload` - existing file overwritten with a new server list, watcher reloads, cache reflects new server. - `TestWatcher_RemovalTransitionsToEmpty` - delete the file, watcher reloads, manager transitions to empty cleanly. - `TestWatcher_DebouncesBurst` - quartz mock clock; three back-to-back `scheduleFire` calls produce exactly one `onChange` after `AdvanceNext`. - `TestWatcher_CloseStopsGoroutine` - construct/Reload/Close five times to surface goroutine or fd leaks under `-race`. - `TestWatcher_DualAgentHTTPNoStall` - integration: write file after `Reload`, wait for watcher reload, then `GET /tools` returns the MCP tools in less than `testutil.WaitShort` instead of the multi-second "reload canceled" stall. - `TestWatcher_LateParentDirTriggersReload` - parent dir doesn't exist at `Reload` time; create the dir then the file; watcher re-arms deeper and reloads. - `TestWatcher_SharedParentRefcount` - two configured paths share a parent dir; only one inotify watch is registered and both reload on changes. - `TestWatcher_CloseDoesNotStallOnInFlightReload` - installs a `connectStartedHook` to block a watcher-driven reload mid-`connectAll`, then asserts `Close()` returns within `WaitMedium`. Regression-verified: reverting the close-ordering causes the test to time out. ## Acceptance checklist - [x] `go test ./agent/x/agentmcp/... -race -count=1` passes (also `-count=5`). - [x] All `./agent/...` tests pass under `-race -short`. - [x] No emdash, endash, or ` -- `; `scripts/check_emdash.sh` clean. - [x] No `time.Sleep` in tests. - [x] New tests fail without the fix and pass with it (verified by temporarily disabling `m.armWatcher(paths)` and by reverting `Close()` ordering). ## Out of scope No changes to chatd's mid-turn workspace MCP discovery (PR #25169) or `MarkStartupSettled` semantics. --- <sub>This pull request was prepared by a [Coder Agents](https://coder.com/docs/admin/ai-coder) run.</sub> |
||
|
|
e6e2d9789e |
docs: mention making the GitHub App public and APP_INSTALL_URL (#25188)
## Summary The GitHub App walkthrough in `docs/admin/external-auth/index.md` stops after \"install the app for your organization,\" which is enough for the admin who created the app but not for anyone else. Every other Coder user hitting **Link GitHub** lands on a GitHub 404 (`This is not the web page you are looking for`) because: 1. New GitHub Apps default to **\"Only on this account\"** / not public. GitHub returns 404 from the OAuth-authorize URL for any user other than the owner. 2. `CODER_EXTERNAL_AUTH_0_APP_INSTALL_URL` — the env var that makes Coder render an \"Install GitHub App\" link in the UI — is undocumented today. This PR adds one extra step at the end of the GitHub App configuration walkthrough covering both. ## Test plan - [x] \`make fmt/markdown\` clean - [x] Doc reviewer eyes |
||
|
|
b5e1ea33d8 |
feat: add AI budget policy and period deployment config (#25122)
Closes https://linear.app/codercom/issue/AIGOV-283/add-deployment-config-for-ai-budget-policy-and-period Adds `CODER_AI_BUDGET_POLICY` and `CODER_AI_BUDGET_PERIOD` deployment options for AI Governance cost controls. |
||
|
|
fabf7d31fc |
test: use default provider in TestPatchChatMessage/ChangesModel (#25189)
`TestPatchChatMessage/ChangesModel` hardcoded `"openai"` as the provider for the override model config. After #25171, the shared chat test harness registers a single `"openai-compat"` provider by default, so calling `createAdditionalChatModelConfig(..., "openai", ...)` fails with HTTP 400 `Chat provider is not configured` before the test can exercise the model-change path. The subtest was added in #25084 after #25171 was reviewed, so the harness change and the new hardcoded provider only met on `main`. Use `defaultModel.Provider` so the override always matches whatever provider the harness registered. This mirrors every other call site of `createAdditionalChatModelConfig` in the file. Closes https://github.com/coder/internal/issues/1530 |
||
|
|
38091f1d82 |
fix(site/src/pages/AgentsPage/components/ChatConversation): remove attachment copy actions (#25119)
Messages with chat file attachments showed a `Copy message` action even though the action only copied `parsed.markdown` and omitted the attachment content. Hide the message copy action whenever a parsed message contains file attachments, and add regression coverage for both user and assistant attachment messages. Refs https://linear.app/codercom/issue/CODAGT-344/remove-or-fix-copy-buttons-on-file-attachments Generated by Coder Agents. |
||
|
|
97ee54a8c1 |
fix(site): clarify deleted workspace actions (#25186)
## Summary Updates the deleted workspace banner so its CTA recreates from the original template instead of sending users to the generic templates list. ## Changes - Change the CTA to `Create another from <template>`. - Link the CTA to the original template workspace create flow. - Shorten the banner copy to `This workspace has been deleted.` ## Validation - `pnpm exec biome check --error-on-warnings src/pages/WorkspacePage/Workspace.tsx src/pages/WorkspacePage/WorkspaceDeletedBanner.tsx src/pages/WorkspacePage/WorkspaceDeletedBanner.stories.tsx` - `pnpm run lint:types` - `git diff --check` - `git commit` pre-commit hooks > 🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑💻 |
||
|
|
cc001ccaf0 |
docs(docs/ai-coder/ai-gateway/clients): fix enable_aibridge -> enable_ai_gateway (#25098)
The Claude Code and Codex CLI registry modules expose the variable as `enable_ai_gateway`, not `enable_aibridge`. Templates using the docs as written fail Terraform init with `An argument named "enable_aibridge" is not expected here.` Verified in [`registry/coder/modules/claude-code/main.tf`](https://github.com/coder/registry/blob/main/registry/coder/modules/claude-code/main.tf) and [`registry/coder-labs/modules/codex/main.tf`](https://github.com/coder/registry/blob/main/registry/coder-labs/modules/codex/main.tf), where the variable is declared as `enable_ai_gateway` and gates the `ANTHROPIC_BASE_URL` / `ANTHROPIC_AUTH_TOKEN` injection. _Generated with the help of Coder Agents._ |
||
|
|
96333acda3 |
fix(coderd): filter build instance agents in SQL (#25031)
Replaces the per-agent Go-side template-version filter in
`handleAuthInstanceID` with a purpose-built SQL query.
`GetWorkspaceBuildAgentsByInstanceID` joins `workspace_agents ->
workspace_resources -> workspace_builds -> provisioner_jobs ->
workspaces` and excludes:
- non-`workspace_build` provisioner jobs (template-version-import,
dry-run)
- deleted agents and sub-agents
- deleted workspaces
The handler:
- drops the per-candidate `GetWorkspaceResourceByID` /
`GetProvisionerJobByID` lookups
- drops the `provisioner_jobs.input` JSON parsing and the follow-up
`GetWorkspaceBuildByID` call
- compares `latestHistory.ID` against `selected.WorkspaceBuildID`
returned directly from the query
- preserves the existing recycled-instance safety check and matching
response codes
One intentional behavior tightening: agents whose workspace is deleted
now return 404 (previously they could reach the recycled-instance check
and return 400, or 200 if the stale build was still latest). This
matches the existing token-auth path, which already refuses to
authenticate against deleted workspaces.
The original `GetWorkspaceAgentsByInstanceID` query is intentionally
untouched. It remains the generic raw lookup used elsewhere in tests and
helpers.
The dbauthz wrapper for the new query uses the system-read fast path
with `fetchWithPostFilter` for non-system reads, with `RBACObject()`
delegating to the embedded `WorkspaceTable`.
Tests:
- new `TestGetWorkspaceBuildAgentsByInstanceID` covering newest-first
ordering, exclusion of deleted/sub agents, exclusion of template-import
and dry-run jobs, and exclusion of deleted workspaces
- new dbauthz mock test for `GetWorkspaceBuildAgentsByInstanceID`
- new `TestPostWorkspaceAuthAWSInstanceIdentity/RecycledInstanceID`
exercising the recycled-instance rejection branch (HTTP 400 when the
agent's build is no longer latest)
- existing `TestPostWorkspaceAuth{AWS,Azure,Google}InstanceIdentity`
continue to cover the handler end to end (including the template-version
+ workspace-build same-instance-ID scenario via
`setupInstanceIDWorkspace`)
> Mux is acting on Mike's behalf.
|
||
|
|
b0b07536fc | feat: add opt-in Coder identity headers for MCP servers (#25153) | ||
|
|
f1d160c7f4 |
fix: allow changing model when editing earlier chat message (#25084)
Editing a previous user message and selecting a different model in the
picker silently kept using the original model: the selection was dropped
on the frontend, in the SDK, and in the backend, so both the replacement
user message and the assistant turn that followed ran against the old
model.
Plumb the selected model through all three layers (`AgentChatPage`,
`codersdk.EditChatMessageRequest`, `chatd.EditMessageOptions` /
`Server.EditMessage`), defaulting to the original message's model when
the client does not specify one. The existing `InsertChatMessages` CTE
already advances `chats.last_model_config_id` when the inserted
message's model differs, so the assistant turn picks up the new
selection without further changes. The new model is validated inside the
transaction, so an unknown ID rolls the edit back and returns a 400
`Invalid model config ID.`, mirroring the `SendMessage` path.
Refs: CODAGT-345
This change was generated by a Coder agent.
<details>
<summary>Implementation plan</summary>
# CODAGT-345: Editing an earlier message cannot change model
## Problem
When editing a previous user message in a chat, the user can change the
model in the model picker, but the backend keeps using the original
message's model. The model selection is dropped at three layers:
1. **Frontend:** `AgentChatPage.tsx`'s edit branch builds an
`EditChatMessageRequest` that omits `model_config_id`. The new-message
branch (a few lines below) does include it.
2. **SDK:** `codersdk.EditChatMessageRequest` has no `ModelConfigID`
field at all.
3. **Backend:** `chatd.EditMessageOptions` has no model field, and
`Server.EditMessage` always copies the original message's
`ModelConfigID` into the replacement message.
Once the replacement user message is inserted with the original model,
the `InsertChatMessages` CTE leaves `chats.last_model_config_id`
unchanged, so the assistant turn that follows runs against the old
model.
## Fix
Plumb the selected model through all three layers, defaulting to the
original message's model when the client doesn't override it. This
mirrors the `SendMessage` path, which already accepts a
`model_config_id` and validates it via
`resolveSendMessageModelConfigID`.
### Backend
- `codersdk/chats.go`: add `ModelConfigID *uuid.UUID` to
`EditChatMessageRequest`.
- `coderd/x/chatd/chatd.go`:
- Add `ModelConfigID uuid.UUID` to `EditMessageOptions`.
- In `EditMessage`, after fetching the edited message, resolve the
model: if `opts.ModelConfigID != uuid.Nil`, validate it exists with
`tx.GetChatModelConfigByID` (using `chatdModelConfigLookupContext`),
otherwise keep `editedMsg.ModelConfigID.UUID`. Pass the resolved ID into
`newChatMessage(...)`.
- Reuse the existing `ErrInvalidModelConfigID` sentinel.
- `coderd/exp_chats.go` (`patchChatMessage`):
- Read `req.ModelConfigID` (nil-safe), pass into
`chatd.EditMessageOptions`.
- Add a `case xerrors.Is(editErr, chatd.ErrInvalidModelConfigID)` arm
returning 400 `Invalid model config ID.`, matching the
`postChatMessages` handler.
### Frontend
- `site/src/pages/AgentsPage/AgentChatPage.tsx`:
- In the edit branch, set `model_config_id: effectiveSelectedModel ||
undefined` on the `EditChatMessageRequest`.
- On success, persist the chosen model to `lastModelConfigIDStorageKey`
so the next chat from this browser keeps the same default. Mirrors the
new-message branch.
### Generated
- `make site/src/api/typesGenerated.ts` and `make
coderd/apidoc/swagger.json` produce the updated `EditChatMessageRequest`
schema in `typesGenerated.ts`, `coderd/apidoc/{docs.go,swagger.json}`,
and `docs/reference/api/{chats.md,schemas.md}`.
## Tests
- `coderd/x/chatd/chatd_test.go`:
- `TestEditMessageWithModelConfigOverride`: edit with a different model
-> replacement message and `chats.LastModelConfigID` use the new model.
- `TestEditMessagePreservesModelConfigByDefault`: edit without
`ModelConfigID` -> original model preserved.
- `TestEditMessageRejectsUnknownModelConfig`: passes a random UUID ->
`ErrInvalidModelConfigID`, original message still present,
`LastModelConfigID` unchanged (rollback).
- `coderd/exp_chats_test.go` (under `TestPatchChatMessage`):
- `ChangesModel`: end-to-end via SDK; `edited.Message.ModelConfigID` and
`chat.LastModelConfigID` both match the new model.
- `InvalidModelConfigID`: random UUID -> 400 `Invalid model config ID.`.
</details>
|
||
|
|
f847ff3731 |
test(coderd/x/chatd): skip stale notification flakes (#25177)
Skip the chatd tests that currently flake because the control notification flow cannot distinguish stale wake/status NOTIFY payloads from real interrupt requests. Each skipped test includes a TODO to re-enable it after the chatd notification flow refactor handles stale notifications correctly. Supersedes #25133, #25134, #25135, and #25139. Refs [CODAGT-353](https://linear.app/coder/issue/CODAGT-353), [CODAGT-356](https://linear.app/coder/issue/CODAGT-356), [CODAGT-360](https://linear.app/coder/issue/CODAGT-360), and [CODAGT-361](https://linear.app/coder/issue/CODAGT-361). > Mux working on behalf of Mike. |
||
|
|
4e08543ace |
test(coderd): centralize chat test harness and stabilize flakes (#25171)
Chat tests previously constructed a real `openai` provider with a fake API key and no `BaseURL`, so background title generation hit `api.openai.com` and timed out under `-race`. The same root cause produced several distinct flakes: title regeneration races with synchronous `UpdateChat`/`ProposeChatTitle`, and pagination races against `updated_at` bumps from real-network processing. This moves the fake OpenAI-compatible provider and the chat-settle wait into first-class `coderdtest` capabilities. `coderd.Options.ChatProviderAPIKeys` is the new seam tests use to redirect chat traffic to a local `httptest.Server`. `coderdtest.WaitForChatSettled` replaces per-test waiters and drains tracked chat-daemon work after the chat row leaves `pending`/`running`. The `newChatClient*` constructors funnel through one options builder that installs the fake provider before the coderd test server so cleanup ordering is deterministic. Closes https://github.com/coder/internal/issues/1528 & Closes ENG-2659 Closes https://github.com/coder/internal/issues/1480 & Closes CODAGT-359 Closes https://github.com/coder/internal/issues/1507 & Closes CODAGT-368 Relates to https://github.com/coder/internal/issues/1397 & Relates to CODAGT-374 |
||
|
|
8ba24e0e54 |
feat(site): add collapsible agent sections (#25173)
closes CODAGT-395 <img width="426" height="480" alt="Screenshot 2026-05-12 at 19 04 03" src="https://github.com/user-attachments/assets/ba336ecf-3e90-48b0-b5d3-b10499909953" /> Adds collapsible section headers to the Agents sidebar, including visible counts and chevrons for pinned and time-grouped chats. The section header toggle keeps nested chat expansion state independent, preserves the existing filter dropdown behavior, and adds Storybook coverage for counts, collapse or expand interactions, and filter menu behavior. |
||
|
|
a55430b8fd | fix(site/src/pages/AgentsPage): suppress last-message spacer during active stream (#25120) | ||
|
|
caabb3c4ab |
fix(site): show Organizations in admin dropdown for single-org OSS deployments (#25175)
Fixes https://linear.app/codercom/issue/CODAGT-350 On OSS or no-license single-org deployments, the Organizations admin link was hidden because `canViewOrganizationSettings` was gated on `showOrganizations`, which requires either a multi-org entitlement or >1 org. The page was still reachable via direct URL, but the members view displayed a raw "Template RBAC is a Premium feature. Contact sales!" error from the groups API. Two fixes: 1. Always render the Organizations link inside the `DeploymentDropdown`. The dropdown itself is only shown to users with admin-level permissions, so Organizations is effectively gated on having admin access. 2. Remove `groupsByUserIdQuery.error` from the error chain on the members page. The groups endpoint is gated behind `templateRBACEnabledMW` on enterprise, returning a 403 on OSS. The groups data is already optional, so the page renders fine without it. > Generated by Coder Agents |
||
|
|
5c3b59151e |
feat: add Cmd/Ctrl+Enter send setting (#25062)
Adds an Agents General setting to require Cmd/Ctrl+Enter before sending
chat messages. When enabled, plain Enter inserts a newline in agent chat
inputs while the send button remains available.
The preference is now persisted server-side through
`/api/v2/users/{user}/preferences`, alongside the existing user
preference settings, and is applied to both the create-agent input and
existing chat composer. Storybook and API coverage verify the setting,
keyboard behavior, validation, and persistence.
<details>
<summary>Coder Agents notes</summary>
Generated by Coder Agents from a Slack request. Dogfooded with
agent-browser against the Storybook settings and chat input stories.
</details>
|
||
|
|
376fc80451 |
fix(coderd/x/chatd): discover workspace MCP tools mid-turn after create_workspace (#25169)
## Problem In `coderd/x/chatd/chatd.go` `runChat`, workspace MCP discovery is gated on `chat.WorkspaceID.Valid` at the start of each turn. New chats that bind their workspace mid-turn (via `create_workspace` or `start_workspace`) get an empty workspace tool list on the first step, and the model falls back to `execute` (bash) because no workspace MCP tools are advertised. **Repro:** new chat → "create a workspace and use MCP tools". No `/api/v0/mcp/tools` request hits the agent on turn 1; turn 2 in the same chat works fine. ## Fix - Add a `PrepareTools` callback to `chatloop.RunOptions`, analogous to `PrepareMessages`. It is invoked once before each LLM step with the current tool list. When it returns non-nil, the chatloop replaces `opts.Tools`, rebuilds the per-step tool definitions, and appends new tool names to `opts.ActiveTools` so newly injected tools are callable immediately. - Wire `PrepareTools` in `runChat` to trigger workspace MCP discovery the first time the chat snapshot reports a valid `WorkspaceID`. The previous top-of-turn discovery path is unchanged for chats that start with a workspace. - Extract the discovery logic into `Server.discoverWorkspaceMCPTools` so the top-of-turn and mid-turn paths share identical behavior (cache, agent resolution, `ListMCPTools` timeout, invalidation). Mid-turn discovery stays disabled in plan-mode turns and Explore subagents, matching the existing top-of-turn gate. The `workspaceMCPDiscovered` flag prevents redundant dials after the first successful discovery. ## Tests - `coderd/x/chatd/chatloop/chatloop_test.go`: two new `TestRun_PrepareTools*` cases covering injection on the next step and active-set merging when `ActiveTools` is non-empty. - `coderd/x/chatd/chatd_test.go`: `TestRunChat_WorkspaceMCPDiscoveryAfterMidTurnCreateWorkspace` drives `runChat` through a `create_workspace` tool call against a real Postgres + mocked agent conn and asserts the second streamed LLM request advertises the workspace MCP tool. Verified that the test fails (and pinpoints the missing tool) when the `PrepareTools` wiring is disabled. ## Validation ``` go test ./coderd/x/chatd/chatloop/... -count=1 go test ./coderd/x/chatd/... -count=1 make lint/emdash ``` <details> <summary>Decision log</summary> - Chose a per-step `PrepareTools` callback over mutating `opts.Tools` in place because `chatloop.Run` builds the `fantasy.Tool` definitions once at start; a hook is required to let the LLM see new tools on the next step. - Returned `[]fantasy.AgentTool` (not also active-tool-names) and let the chatloop derive name merges via `mergeNewToolNames`. This avoids leaking plan-mode gating decisions into the callback contract. - Kept the existing top-of-turn discovery path so chats that already have a workspace at turn start pay no extra latency. - Skipped reusing `ReloadMessages` (history reload) since this is purely a tool-availability concern; coupling it to a history reload would defeat the chatloop cache prefix optimizations. </details> --- _This pull request was generated by Coder Agents._ |