mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
6e07e2610f42fac83e3b09d9e9fee85ef2f63df0
15723
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6e07e2610f |
feat: add paginated API endpoint for groups (#27603)
backend-only changes from #27271; see that PR for summary of changes + implementation details |
||
|
|
ddb2799009 | fix: hide the favorite button for workspaces you don't own (#28000) | ||
|
|
09b0d8e108 | chore: update stale Chromatic comments (#27714) | ||
|
|
b29af7f64a | fix: improve layout of CLI install page (#27998) | ||
|
|
baa1e3a6c5 |
fix(site): make delete dialog confirmation text use primary color (#28002)
## Summary In the workspace delete confirmation dialog, the text typed into the "Workspace name" confirmation field rendered in the same secondary color as the placeholder, making it hard to distinguish entered text from the placeholder. The shared `Input` component uses `text-inherit`, so it picked up the dialog description's secondary text color. This sets the confirmation input's text to `text-content-primary` (white on dark), while the placeholder remains `text-content-secondary`. ## Changes - `WorkspaceDeleteDialog.tsx`: add `className="text-content-primary"` to the confirmation `Input`. ##### Before https://github.com/user-attachments/assets/88dbb230-feb6-416c-b516-9cc92950a0b8 ##### After https://github.com/user-attachments/assets/74296b9e-cbdf-40fe-ba3d-6fbcf5d4a9d5 --- _This PR was generated by Coder Agents on behalf of @jeremyruppel._ |
||
|
|
053b38944d |
fix(coderd): render collected_at as UTC RFC3339 in the agent metadata aggregate (#27991)
Follow-up to #27934; this fix was pushed to the branch after the squash-merge and missed it. `jsonb_build_object` renders timestamptz in the session `TimeZone`, which Coder never pins, and `collected_at` defaults to year 1 until the agent's first report. On a non-UTC Postgres session a registered-but-never-collected item renders with an LMT second-offset (even `BC`, e.g. `0001-12-31T19:03:58-04:56:02 BC`), which Go's RFC3339 parsing rejects - a 500 for the entire list page whenever `include_agent_metadata` is used. - `to_char(... AT TIME ZONE 'UTC', ...)` pins the rendering; never-collected items round-trip as Go's zero time. - The test now runs against a named-zone database (`dbtestutil.WithTimezone("America/Caracas")`) and requests a registered but never-collected key; it reproduces the 500 without the fix. Also contains the failure mode Go-side: an unparsable aggregate now degrades to missing metadata for that workspace (with a warning log) instead of failing the entire page. The SQL fix prevents the known cause; the containment covers any future one. The test still catches regressions because it asserts the metadata values, not just a 200. --- Authored by Coder Agents on behalf of @Emyrk. |
||
|
|
66b065323b |
feat: log rate-limited external auth token validation (#26754)
When `ValidateToken` keeps a token because the external auth validation
endpoint was rate-limited (a `403` with rate-limit headers or a `429`),
it returns `valid=true` without provider confirmation. Previously this
happened silently, so operators couldn't tell a provider-confirmed token
from one kept optimistically during a rate limit.
This adds a `Logger` to `externalauth.Config` and emits a `Warn` (with
`provider_id`, `provider_type`, `status_code`, and `reason`) on those
rate-limit branches. It also adds a
`coderd_oauth2_external_requests_rate_limited_total{name, source,
status_code}` counter, incremented in the instrumented round tripper
whenever a provider returns a rate-limited response. The rate-limit
detection is the shared `xhttp.IsRateLimited` (in `coderd/util/xhttp`),
used by both the tripper and `ValidateToken` so the metric and the
validation decision share one definition; no extra wiring is needed
since `ValidateToken` already routes through the instrumented client
with `source="ValidateToken"`.
One deliberate behavioral change rides along: rate-limit detection now
also recognizes the unprefixed `RateLimit-Remaining` header (GitLab, and
the IETF draft rate-limit headers), so a `403` with
`RateLimit-Remaining: 0` is treated as optimistically valid where it was
previously treated as revoked. All other valid/invalid decisions are
unchanged. `TestValidateToken` asserts the warning's fields on the
rate-limited cases and no warning for revocations, `401`, and confirmed
responses; `promoauth` and `xhttp` tests cover the detector and the new
counter.
<details>
<summary>Manual testing</summary>
The signals fire on the external-auth status check (`GET
/api/v2/external-auth/{id}`), which calls `ValidateToken`. To force a
rate-limited response, point a provider's `validate_url` at a mock that
returns the rate-limit shape:
1. Run a mock returning `429` on one path and `403` +
`X-RateLimit-Remaining: 0` on another.
2. Start `coder server` with `--prometheus-enable` and external auth
providers whose `validate_url` point at those mock paths (e.g.
`CODER_EXTERNAL_AUTH_0_VALIDATE_URL=http://127.0.0.1:5599/429`).
3. Create a stored link, either complete the OAuth flow, or insert a row
into `external_auth_links` with a future `oauth_expiry` (token contents
are irrelevant; the mock rejects regardless).
4. `curl` the status endpoint with a session token, then check:
- coderd logs for the `Warn` (`reason=status_code` for `429`,
`reason=rate_limit_headers` for `403`),
- the metrics endpoint for
`coderd_oauth2_external_requests_rate_limited_total{...,status_code="429"|"403"}`.
Notes: `scripts/testidp -429` only rate-limits `/oauth2/userinfo`, not
the `/external-auth-validate/...` path, so it does not exercise this;
use a mock `validate_url`. The default Prometheus port `2112` may
already be taken on dogfood workspaces, set `CODER_PROMETHEUS_ADDRESS`
to a free port.
</details>
🤖 Generated with the help of Coder Agents on behalf of @jscottmiller.
|
||
|
|
bd693ad4ae |
fix: raise test-go-pg timeout budget, lower macOS parallelism (#27997)
`test-go-pg (macos-latest)` has recurred three times on [coder/internal#1365](https://github.com/coder/internal/issues/1365), most recently as the `cli` package hitting its own `go test -timeout 20m` after several minutes of runner-side scheduling delay, which marks hundreds of in-flight subtests as failed instead of surfacing the actual cause. Raise `GOTEST_FLAGS -timeout` from `20m` to `25m` and the matching `timeout-minutes` on every job that shares it (`test-go-pg`, `test-go-pg-17`, `test-go-race-pg` in `ci.yaml`; `flake_go` in `flake-go.yaml`; `test-go-pg` in `nightly-gauntlet.yaml`) from `25` to `30`, preserving the 5-minute margin that lets `go test`'s own timeout fire before GitHub cancels the job and produce a goroutine dump for a genuine hang. Also lower macOS `test-parallelism-tests` from `16` to `8`, matching Linux, to test whether the 2x core oversubscription is contributing scheduler contention. Windows keeps `16`; nothing in the current evidence implicates it. This is a mitigation, not a confirmed root cause; the runner scheduling delay itself is still unexplained. Refs coder/internal#1365 ## AI disclosure Per [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING): this PR was primarily authored by Claude Code, directed by @BobbyHo, based on triage of the linked ticket's CI-flake-bot comments and a review of the current `Makefile`/`ci.yaml`/`flake-go.yaml`/`nightly-gauntlet.yaml` timeout configuration. **Verification:** - `make lint/actions/actionlint` and `make lint/actions/zizmor` both pass clean on the three edited workflow files. - `make pre-commit` passes (includes `make gen`, `make fmt`, `make lint`, and a full local build). - All three edited workflow YAMLs parse (`ruby -ryaml`) and `make -n test TEST_PACKAGES="./cli/..."` confirms `GOTEST_FLAGS` resolves to `-timeout 25m` as intended. - This is a config-only change (no application code touched); the intended effect can only be confirmed by watching real `test-go-pg` (macOS) runs on this PR and on `main` after merge, since the underlying runner-stall failure is intermittent. |
||
|
|
16c58770f8 |
feat: constrain the OAuth2 client type column (#27931)
Extracted from #27873 so the schema change can be reviewed for migration safety on its own. #27873 will rebase onto this. `client_type` decides whether the token endpoint validates a client secret at all, and the column accepts any text: nullable, no `CHECK`, no enum. No Go path can write a bad value today, and `IsPublic` fails closed on anything unrecognized, so the read side is safe. What the schema still permits is the problem: a future migration writing `'public'` onto a row that holds a secret turns off client authentication for that app with nothing to catch it, no constraint, no log, no audit entry, no test. `000565` adds `CHECK (client_type IN ('confidential', 'public'))` and `NOT NULL`. The `UPDATE` ahead of it should touch zero rows, since migration `000344` added the column with a default of `'confidential'` and backfilled with `COALESCE`; it is there so `SET NOT NULL` cannot fail on an unexpected row. Both `ALTER`s take `ACCESS EXCLUSIVE` and scan a table holding one row per registered OAuth2 client, so the lock is brief. ## The second migration, and why it aligns the way it does Two columns describe the same fact and can currently contradict each other. `token_endpoint_auth_method` is the client's own declaration: registered client metadata under RFC 7591 §2, where `"none"` is defined to mean the client is public and has no secret. `client_type` is Coder's derived copy, and it is what the token endpoint enforces on. RFC 7591 defines no `client_type` metadata field; the column exists only as a denormalization. Registration used to persist the declaration verbatim while hardcoding `client_type` to `'confidential'`, so rows exist declaring `"none"` on a client stored confidential that was issued, and still requires, a real secret. A client that reads its own metadata and believes it is public will drop that secret and stop being able to exchange codes. `000566` aligns the declaration to what is enforced, not the reverse. Deriving enforcement from the declaration would reclassify every such client as public and stop requiring the secret it holds, which is a silent authentication downgrade. The down migration is deliberately empty: the previous values are not recorded, and restoring them would only reinstate metadata that tells a client to authenticate in a way the server rejects. ## Application changes `SET NOT NULL` changes the generated field from `sql.NullString` to `string`, so the three write sites are updated to match. That is the entire application diff and no behavior depends on it. Refs https://linear.app/codercom/issue/ENG-3029/oauth2-support-public-client --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2f34e1abd0 |
ci: add scheduled audit-docs-paths workflow (#27245)
## What Adds `.github/workflows/audit-docs-paths.yaml`, a scheduled workflow that runs the docs-URL drift audit (`site/scripts/audit-docs-paths.mjs`, added in #25740) on a weekly cron and on demand, so drift is caught automatically instead of only when someone runs the script by hand. Scheduling was suggested by @bpmct on #25740. ## How it works - **Triggers:** `schedule` (weekly, Monday 09:00 UTC — same cadence as `weekly-docs`) and `workflow_dispatch`. - **Checks out both repos:** `coder/coder` (root) and `coder/coder.com` (into `coder.com/`, read with the `cdrci` CI-bot token). The audit covers references in both repos. - **Runs the audit** with absolute `--roots` (required, otherwise the report can't classify findings by repo). - **Always** uploads the dated report as the `audit-docs-paths-report` artifact and writes it to the run summary. - **On findings:** opens or updates a single deduplicated tracked issue with the report, and fails the run (red check). **On a clean run:** closes that issue. ## Enabling (dormant until then) The audit reads **coder/coder.com, a private repo**, which the default `GITHUB_TOKEN` can't read, so the coder.com checkout uses the existing **`cdrci`** CI-bot token (`secrets.CDRCI_GITHUB_TOKEN`) — already used for cross-repo checkouts in `release.yaml`/`tag-and-release.yaml`, and `cdrci` is a coder.com collaborator (verified). No new App to stand up. The job is gated behind `vars.AUDIT_DOCS_PATHS_ENABLED` so it merges dormant and can be validated before going live. To turn it on: 1. Set `vars.AUDIT_DOCS_PATHS_ENABLED = 'true'`. 2. Run once via `workflow_dispatch` to confirm the end-to-end run. ## Also in this PR Removes the dormant `audit-docs-paths` job embedded in `weekly-docs.yaml` (added in #25740, gated off pending the same credential). The new dedicated workflow supersedes it; the `weekly-docs.yaml` diff is exactly that job removal. ## Validation - `actionlint -shellcheck= -ignore set-output` passes locally; PR `title`, `lint-actions`, and `lint-docs` are green. - **Credential check:** `cdrci` is a collaborator on coder/coder.com (read access confirmed); `secrets.CDRCI_GITHUB_TOKEN` already exists in this repo. (Note: `cdrci2` is *not* a coder.com collaborator, so an earlier `CDRCI2_` attempt was corrected to `CDRCI_`.) - **Pre-flight audit against current `main` (both repos): 0 findings** — 148 `/docs/*` redirect rules indexed; 1846 coder/coder + 432 coder.com TS/TSX files scanned. So a `workflow_dispatch` on `main` today passes green with no issue filed (the "empty audit succeeds" criterion). The failure path can be checked by injecting a stale path on a throwaway branch. ## Decisions for review - **Mechanism** = tracked issue + failed check + artifact ("both" from the issue). Easy to narrow to issue-only or fail-only. - Reused `AUDIT_DOCS_PATHS_ENABLED` and removed the embedded job rather than adding a second gate. - Named the file `.yaml` to match the repo's other docs workflows (the issue text said `.yml`). Linear: https://linear.app/codercom/issue/DOCS-366 |
||
|
|
ad100452d4 |
fix(aibridge): use latest streaming chat usage instead of cross-chunk sum (#27967)
## Problem CODAGT-906: chats using OpenAI-compatible backends (e.g. poolside) through the AI Bridge persist token usage inflated 105x-640x, which falsely triggers automatic chat compaction on every turn. The chat-completions streaming interceptor summed usage across every SSE chunk of one upstream stream and rewrote each relayed usage-bearing chunk with that running sum. Spec-compliant OpenAI emits usage once (final chunk with `stream_options.include_usage`), so the sum equals the final value. vLLM-style backends emit cumulative usage snapshots on every chunk, so the relayed final usage becomes roughly `N_chunks x prompt_tokens` (e.g. 417,012 persisted for a ~6,000-token context). chatd persists that value per assistant message and its compaction trigger reads it as context occupancy. ## Fix Track the latest usage-bearing chunk's raw usage (last-wins) in the stream processor, updating only when a chunk actually carries usage so a trailing usage-less chunk cannot zero it. `marshalChunk` relays that value and `recordTokenUsage` records the same value, unifying relayed and recorded usage. Last-wins is correct for both shapes: a single final usage chunk, and cumulative snapshots where each snapshot already includes all prior tokens. Per-iteration semantics are unchanged: each tool-loop iteration has its own processor, and the final iteration's usage is what the client sees. ## Tests - `TestStreamProcessorUsage` (internal): cumulative snapshots with a trailing usage-less chunk, and the spec-compliant final-only shape; asserts relayed and recorded usage equal the last snapshot. - New txtar fixture `streaming_cumulative_usage_injected_tool.txtar` with per-chunk cumulative usage plus an injected tool call; asserts client-visible final usage through the full interceptor. - Red-green verified: with the fix reverted, the internal test reports zeroed usage (trailing chunk overwrite) and the fixture test reports 18000 summed prompt tokens instead of 6000. The blocking (non-streaming) path deliberately keeps its cross-iteration summation for external clients and is untouched. Remote dogfood UAT validated chat streaming, tool calls, plausible usage numbers, and zero spurious compactions. > Mux acted on Mike's behalf to author this change. |
||
|
|
5efa7abe7d |
fix: only write AI model prices that changed (#27923)
Previously, the AI Gateway price seeder rewrote every row of `ai_model_prices` on each server start, because `ON CONFLICT` fires on a key conflict rather than on a value difference. `updated_at` therefore recorded when the server last restarted rather than when a price last changed. Guard the `DO UPDATE` branch so a conflicting row is only rewritten when one of its four prices differs. The comparison uses `IS DISTINCT FROM` rather than `<>` because the price columns are nullable, and `<>` yields NULL when either side is NULL, which would skip the update and leave a stale price in place. Related to https://linear.app/codercom/issue/AIGOV-567/experimental-cli-command-to-set-prices-for-unpriced-ai-models > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
27414788f7 |
chore: use 'AI spend' and 'approximate' in budget UI (#27977)
The "AI budget" column shows spend against the configured limit, not the limit itself, so "AI spend" describes what it actually displays. Renamed in both the groups table and the group members table. Also replaces "estimated" with "approximate" in the surrounding spend copy, which reads more plainly as a signal that the amount isn't exact. The user dropdown now keeps the date range on a single line, so the label wraps above it instead of the dates splitting across two lines. Before: <img width="250" height="89" alt="Screenshot 2026-08-10 at 12 55 55" src="https://github.com/user-attachments/assets/428f7032-0ead-44ac-987d-563e20c97d12" /> After: <img width="248" height="92" alt="Screenshot 2026-08-10 at 12 57 09" src="https://github.com/user-attachments/assets/cf0704ba-d0ab-4132-b207-a15ab2ea4f37" /> Related to internal slack thread: https://codercom.slack.com/archives/C096PFVBZKN/p1786051712464009 > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
84f4a8bb17 | fix(site/src): prevent protocol-relative login redirects (#27363) | ||
|
|
9a57dfa642 |
feat: include agent metadata in workspace list responses (#27934)
Closes #27933. Related: #27897 (single-agent GET). Agent metadata is only readable via a per-agent watch stream, so reading it across N workspaces costs N+1 requests. This adds a batch read to the list endpoint: ```text GET /api/v2/workspaces?q=param:"pool=demo" include_agent_metadata:task_status ``` - New `include_agent_metadata` search key, repeatable and key-scoped. It expands the response, it does not filter workspaces. - `GetWorkspaces` aggregates the requested keys as JSON behind a `CASE`: without opt-in the response is unchanged and the subquery never runs. Runs only for the returned page, inside the same authorized query. - Agents in the response gain `metadata` (`[]codersdk.WorkspaceAgentMetadata`, `omitempty`), mapped by the `workspace_agent_id` each element carries. The collection script is omitted; it can be long. - `codersdk.WorkspaceFilter` gains `IncludeAgentMetadata []string`. - No wildcard, no schema change, no migration. --- Authored by Coder Agents on behalf of @Emyrk. |
||
|
|
a3a51228ee |
chore(site): remove Beta tag from agents navigation (#27986)
## Summary Removes the `Beta` feature stage badge from the `/agents` page navigation: - **`ChatsPanel.tsx`**: removed the badge from the desktop left sidebar header - **`AgentPageHeader.tsx`**: removed the badge from the mobile top header Both instances rendered `<FeatureStageBadge contentType="beta" size="xs" />` next to the Coder product logo. The `FeatureStageBadge` imports were removed as they are no longer used in these files. ## Sidebar summary - Removed Beta badge from desktop sidebar (`ChatsPanel.tsx`) - Removed Beta badge from mobile header (`AgentPageHeader.tsx`) - Removed unused `FeatureStageBadge` imports from both files - No behavioral or logic changes, badge-only removal --- PR generated with Coder Agents |
||
|
|
8c2f7adeb1 |
revert: "fix: markdown rendering improvements" (#27979)
This reverts commit
|
||
|
|
cfeae56bed |
chore(docs): update release docs for v2.35.4 (#27972)
Automated docs update for v2.35.4 release. Created by `releasetui`. |
||
|
|
95e8b71d03 |
fix(coderd): start test AI bridge after config in automatic title tests (#27971)
Fixes the reopened flake tracked in CODAGT-876 / coder/internal#1629. ## Problem The Aug 10 recurrence was not the previously fixed subtests failing again: the nightly-gauntlet macos run ([job log](https://github.com/coder/coder/actions/runs/31355808516/job/93355150162)) flaked in the sibling test `TestPostChats_AutomaticTitleGenerationPasteOnly`, which the flake investigator matched to the existing issue. Both `TestPostChats_AutomaticTitleGeneration*` tests still used `newChatClientWithAPI`, which starts the in-process AI Gateway daemon before the test creates its provider/model config. The daemon's synchronous initial provider load therefore sees zero providers, and route availability depends on the asynchronous pubsub-driven reload racing the one-shot automatic title generation that `CreateChat` kicks off. When the reload loses (initial load at `.575` with `provider_count=0`, title request at `.907` hitting `route not supported`, reload landing at `1.029`), the title candidate fails without retry and the test times out waiting for the `propose_title` request. ## Fix Convert both tests to the pattern #27564 established for the `TestRegenerateChatTitle`/`TestProposeChatTitle` subtests: `newChatClientWithoutAIBridge`, create the model config, then `aibridgedtest.StartTestAIBridgeDaemon`, so the daemon's synchronous initial load already contains the route. The existing `NoPubsubDelivery` subtest guards that initial-load invariant, so no new guard test is added. ## Validation - Deterministic red-green via the isolated-pubsub technique: old ordering with the pubsub leg removed reproduces the exact CI signature (`provider_count=0`, `route not supported`, timeout at the `titleRequested` wait); the new ordering passes with the pubsub leg still removed, proving the synchronous initial load alone provides the route. - `go test ./coderd -run 'TestPostChats_AutomaticTitleGeneration' -count=10` - `go test ./coderd -run 'TestRegenerateChatTitle|TestProposeChatTitle' -count=1` - `make lint` and `make pre-commit` via hooks. > Opened by Mux on Mike's behalf. |
||
|
|
07f79af65b |
fix: markdown rendering improvements
Improvements to markdown rendering in notification emails: - More consistent escaping of values interpolated into notification templates - Stricter link handling in the notification email renderer, scoped to the notification rendering path - HTML escaping of values interpolated into the outer email template - Expanded unit and end-to-end coverage of the notification rendering pipeline - `make gen` run to regenerate golden files for SMTP and webhook notification templates |
||
|
|
192842c8f2 | fix(site/src): treat chat deleted watch events as archive instead of eviction (#27921) | ||
|
|
19fdc23d63 | fix(site/src): fan chat message upserts out to every containing page (#27912) | ||
|
|
0414948454 |
chore(docs): update release docs for v2.34.8 (#27970)
Automated docs update for v2.34.8 release. Created by `releasetui`. |
||
|
|
bab9963a9a |
fix(site): defer external app API key generation to on-click (#27907)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell. Resolves [DEVEX-460](https://linear.app/codercom/issue/DEVEX-460/defer-api-key-generation-in-useapplink-to-on-click-instead-of-page). ## Problem `useAppLink` minted a session key on mount via a `useQuery`: ```ts const { data: apiKeyResponse } = useQuery({ ...apiKey(), enabled: isExternalApp(app) && needsSessionToken(app), }); ``` Whenever any page mounted `useAppLink` for an external app that embeds `$SESSION_TOKEN` in its URL (JetBrains Gateway, Coder Desktop, etc.), it fired `POST /api/v2/users/me/keys` on render, even if the user never clicked the link. Each call minted a fresh session key and produced a `created token` audit-log entry. Simply navigating the dashboard generated a stream of `created token` entries with no real connection activity. This is the follow-up to #22318 (AIGOV-24), which only fixed the built-in VS Code / VS Code Insiders buttons in `WorkspacesTable`. ## Change Mirror the on-click minting pattern from #22318, applied to the shared `useAppLink` hook: - Replace the eager `useQuery(apiKey())` with a `useMutation(() => API.getApiKey())` that runs only when the user clicks a token-bearing external app. `onClick` mints the key, builds the final URL, and navigates via `location.href` (these are always custom-protocol, non-HTTP external apps). - The returned `href` no longer embeds a token; the hook owns opening for token apps. - Replace the `hasToken` field with `isLoading` (mint in-flight) and update call sites so token apps are always clickable, with a loading affordance while a key is being minted. - `TaskApps` external-app menu items now render an anchor with the hook's `onClick` (instead of a `RouterLink` that bypassed it), so the deferred mint runs there too. No API key is minted until the user actually opens an external app. ## Affected call sites - `site/src/modules/apps/useAppLink.ts` (core change) - `site/src/modules/resources/AppLink/AppLink.tsx` - `site/src/pages/AgentsPage/components/WorkspacePill.tsx` - `site/src/pages/TaskPage/TaskApps.tsx` ## Testing Added Storybook interaction tests (`play` functions) in `AppLink.stories.tsx` that assert the fix directly: - `ExternalAppDefersSessionToken`: a token-bearing external app mints **no** key on render, and mints exactly one on click. - `ExternalAppWithoutSessionTokenNeverMints`: an external app without `$SESSION_TOKEN` never mints a key, even on click. Also verified: - `tsc -p .` (frontend typecheck) passes - `biome check` on changed files passes - `vitest` for `AppLink` (incl. new stories), `apps`, `WorkspacePill`, `TaskApps`, and `AppStatuses` stories/tests pass - pre-commit hook (gen/fmt/lint/build) passes ## Manual verification checklist (recommended before merge) - With an external app that uses `$SESSION_TOKEN` (e.g. JetBrains Gateway), open DevTools → Network filtered on `users/me/keys`, reload `/workspaces` and the workspace detail page, and confirm **no** `POST` fires on render. - Confirm a `POST` fires only when the app link is clicked, and the app opens correctly. |
||
|
|
1e578a69a4 |
chore: bump github.com/go-git/go-git/v5 from 5.19.1 to 5.19.2 (#27950)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.19.1 to 5.19.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/go-git/go-git/releases">github.com/go-git/go-git/v5's releases</a>.</em></p> <blockquote> <h2>v5.19.2</h2> <h2>What's Changed</h2> <ul> <li>build: Update module golang.org/x/crypto to v0.52.0 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2150">go-git/go-git#2150</a></li> <li>build: Update module github.com/go-git/go-git/v5 to v5.19.1 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2141">go-git/go-git#2141</a></li> <li>build: Update module golang.org/x/net to v0.55.0 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2152">go-git/go-git#2152</a></li> <li>git: Worktree: Add stores index entires with backslashes on Windows by <a href="https://github.com/joshblum"><code>@joshblum</code></a> in <a href="https://redirect.github.com/go-git/go-git/pull/2262">go-git/go-git#2262</a></li> <li>storage: dotgit, reject path traversal in reference names by <a href="https://github.com/pjbgf"><code>@pjbgf</code></a> in <a href="https://redirect.github.com/go-git/go-git/pull/2254">go-git/go-git#2254</a></li> <li>build: Update module golang.org/x/net to v0.56.0 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2267">go-git/go-git#2267</a></li> <li>build: Update module golang.org/x/text to v0.39.0 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2268">go-git/go-git#2268</a></li> <li>[v5] git: worktree, make the filesystem wrapper a symlink-safe boundary by <a href="https://github.com/pjbgf"><code>@pjbgf</code></a> in <a href="https://redirect.github.com/go-git/go-git/pull/2277">go-git/go-git#2277</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/go-git/go-git/compare/v5.19.1...v5.19.2">https://github.com/go-git/go-git/compare/v5.19.1...v5.19.2</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/go-git/go-git/commit/3eeb238da61eb9c7a324f3ee04f990ce89175642"><code>3eeb238</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2277">#2277</a> from go-git/checkout-v5</li> <li><a href="https://github.com/go-git/go-git/commit/008a78f2dd86f52544ddff8b8e8ddeecdf3f7aab"><code>008a78f</code></a> git: worktree, make the filesystem wrapper a symlink-safe boundary</li> <li><a href="https://github.com/go-git/go-git/commit/2263fb5f022dde90b1c2845f028d3e37e161f2b8"><code>2263fb5</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2268">#2268</a> from go-git/renovate/releases/v5.x-go-golang.org-x-t...</li> <li><a href="https://github.com/go-git/go-git/commit/77b76250d93ec83e2c897638d8a3847b1bfaa38d"><code>77b7625</code></a> build: Update module golang.org/x/text to v0.39.0 [SECURITY]</li> <li><a href="https://github.com/go-git/go-git/commit/85ea767be2b2281693e61afe83911e12c86d6eb7"><code>85ea767</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2267">#2267</a> from go-git/renovate/releases/v5.x-go-golang.org-x-n...</li> <li><a href="https://github.com/go-git/go-git/commit/198675a07b3b8f4eb8f51bf188663a13bb0d9e1a"><code>198675a</code></a> build: Update module golang.org/x/net to v0.56.0 [SECURITY]</li> <li><a href="https://github.com/go-git/go-git/commit/4a0e66d555de5f9a30c31e2df64f445f42bd01e7"><code>4a0e66d</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2254">#2254</a> from pjbgf/v5-dotgit-ref-name-containment</li> <li><a href="https://github.com/go-git/go-git/commit/3b306ef83bd05194a30ce820eed7ed61c3084b5f"><code>3b306ef</code></a> storage: dotgit, align reference-name safety with refname_is_safe</li> <li><a href="https://github.com/go-git/go-git/commit/f3d0cc150b39ae1dc47406a5c170464286914610"><code>f3d0cc1</code></a> storage: dotgit, reject path traversal in reference names</li> <li><a href="https://github.com/go-git/go-git/commit/979cfe9c561d3ced778c88d9cde6db3297e6ed1d"><code>979cfe9</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2262">#2262</a> from joshblum/joshblum/to-slash-v5</li> <li>Additional commits viewable in <a href="https://github.com/go-git/go-git/compare/v5.19.1...v5.19.2">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) 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> |
||
|
|
b2cfc4e530 |
refactor(site): move Add users into <SettingsHeader /> (#27906)
Move the Add users action into SettingsHeader on the organization Members page and group detail page, matching the Users page layout. It no longer sits inline with the filters. | Old | New | | --- | --- | | <img width="2934" height="1742" alt="ORGANIZATION_MEMBERS_OLD" src="https://github.com/user-attachments/assets/c09ccb0b-cce5-4b95-a63b-40c42dd2e1ac" /> | <img width="2934" height="1742" alt="ORGANIZATION_MEMBERS_NEW" src="https://github.com/user-attachments/assets/a20089b7-04f0-47dc-8153-8f5cca8999cf" /> | |
||
|
|
ad225269aa |
refactor(site): redesign <AppearanceSettingsPage /> (#27722)
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell. - Redesign Deployment Appearance settings to the standard two-column settings layout (`HorizontalForm` / `FormSection`) for branding, with announcement banners as a secondary `SettingsHeader` + table section (aligned with OAuth2 apps / AI Governance). - Demui `IconField` and reuse it for Logo URL (URL input, preview, emoji picker); thin `IconPickerField` to wrap the shared component. - Clean up announcement banner create/edit (draft-only until save, page-top preview via portal, shadcn `Switch` / menu icons, empty-state CTA) and clarify Premium paywall copy to cover branding and announcement banners. | Old | New | | --- | --- | | <img width="2936" height="2666" alt="appearancesettings_old" src="https://github.com/user-attachments/assets/db11950d-2440-412b-a74d-fcf57f2467e9"/> | <img width="2936" height="2714" alt="appearancesettings_new" src="https://github.com/user-attachments/assets/3f418fb1-7f94-4fd8-bf54-0d63014c6533"/> | |
||
|
|
e751b285ca | chore(site): upgrade pierre diffs to 1.3.3 (#27932) | ||
|
|
ee49107ea9 |
docs: document per-template agents_allowed (#27518)
Relates to CODAGT-713 Depends on #27517 This updates the Coder Agents platform controls documentation for the per-template `agents_allowed` model. It replaces the deployment-wide allowlist instructions with the **Agents allowed** controls in AI Settings and template settings, documents that templates allow agents by default, and explains that disabled templates are excluded from `list_templates`, `read_template`, and `create_workspace`. This is the final PR in the stack and aligns the template routing and optimization guidance with the database, API, frontend, cleanup, and CLI changes in the preceding PRs. |
||
|
|
7a9b4250aa |
refactor(site): demui <IconField /> (#27719)
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell.
Replace MUI `TextField` / Emotion theming in `IconField` with
`InputGroup`, `Popover`, and Tailwind.
`IconPickerField` already had the demui'd `InputGroup` + `Popover`
implementation, so that was ported into the shared `IconField`. Per
review feedback, `IconPickerField` is now removed and its call sites
(the MCP server, provider, and OAuth app forms) use `IconField`
directly.
|
||
|
|
50640063a2 |
feat: DEVEX-732 premium badging (#27847)
Premium badging and gating consistency as a OSS user, I want to be upsold to premium, and tastefully Summary Standardize all base-Premium full-page gates and the two named inline notices. Admins see an in-app “Learn about Premium” path; non-admins are told to contact their deployment administrator. * DEVEX-732 * updates for premium docs pages for consistency * updates for premium badging and paywall components * updates implemented uses of premium badge and premiumpaywall | Before | After | | --- | ----------- | | <img width="1271" height="564" alt="Screenshot 2026-08-04 at 3 02 32 PM" src="https://github.com/user-attachments/assets/027d4bca-3e34-40b2-ad69-28dbaa4a004b" /> | <img width="1273" height="600" alt="Screenshot 2026-08-04 at 3 26 37 PM" src="https://github.com/user-attachments/assets/321083c0-7a4c-4c7e-a19c-059807018d3b" /> | | Before | After | | --- | ----------- | | <img width="1084" height="672" alt="image" src="https://github.com/user-attachments/assets/741e6bd9-93b0-4ae0-97df-027e8aba5716" /> | <img width="1289" height="622" alt="Screenshot 2026-08-04 at 3 20 07 PM" src="https://github.com/user-attachments/assets/b3a8c169-ca6e-439b-8752-9209131fc097" /> | | Before | After | | --- | ----------- | | <img width="1091" height="865" alt="image (1)" src="https://github.com/user-attachments/assets/f7cd92dd-a975-4db0-bc2a-af092ba783ce" /> | <img width="1268" height="680" alt="Screenshot 2026-08-04 at 3 37 06 PM" src="https://github.com/user-attachments/assets/8af8081a-0ec9-4fd3-921c-470127f2328b" /> | |
||
|
|
baed1455cf |
feat(site/src/pages/TemplateBuilder): scroll to module when clicking sidebar row (#27351)
## What Clicking a selected module in the right-hand `SelectionSummary` sidebar now jumps to the module settings step and scrolls that module's card into view. Addresses [DEVEX-587](https://linear.app/codercom/issue/DEVEX-587). This is an isolated slice of #27077 (which bundles several unrelated changes); only the "click a module to scroll to it" behavior is included here. ## Changes - `SelectionSummary`: gains an optional `onNavigateModule` prop. When provided, each selected module row renders as an accessible `<button>` (hover + focus-ring) labeled `Configure <name>`; otherwise rows stay non-interactive. - `ModuleSettingsStep`: each module card wrapper gets a stable `id={module-config-<id>}` scroll anchor plus `scroll-mt-24` so the sticky top nav does not cover the title. - `TemplateBuilderPageView`: adds `navigateToModule`, which switches to the module settings step and scrolls the target module into view once it renders. If the module settings step is skipped (no configurable variables), the click is a no-op. - `SelectionSummary.stories`: adds a `NavigateModuleClick` interaction story and updates `WithLongNameModule` to the new button semantics. ## Explicitly out of scope The rest of #27077 is not included: gallery height/card clamp, sensitive-var banner relocation, trash-icon removal wiring, the scroll-past required-field highlight subsystem, and the broader navigable-sidebar work (step labels, base-row navigation, back-stack semantics). ## Testing - `pnpm check` (biome) clean - `pnpm lint:types` (tsc) clean - `pnpm vitest run --project=unit src/pages/TemplateBuilder` — 46 pass - `pnpm vitest run --project=storybook src/pages/TemplateBuilder` — 34 pass (incl. new `NavigateModuleClick`) <details> <summary>Implementation plan / decision log</summary> ### Goal Open a new PR containing only the changes that satisfy DEVEX-587: clicking a selected module in the right-hand `SelectionSummary` sidebar should jump to the module settings step and scroll that module's card into view. ### Base has moved since #27077 PR #27077 was cut against an older `main`. Today's `main` was refactored: - Steps are URL-driven; `steps.ts` already provides `StepId`, per-step `group` (1/2/3), and `nearestVisible()`. - `TemplateBuilderPageView` already has `navigateToStep(index: number)` and a `useEffect` that resets window scroll on every `currentStep.id` change. - The sidebar no longer has a deselect ("X") button. The PR's entanglement between "make row a nav button" and "move deselect to a trash icon" therefore does not exist on current `main`, so module navigation can be added without removing behavior and without pulling in the trash-icon item. So the isolated diff was written against current `main`, not reused verbatim from the PR. It is smaller than the PR's own hunks and does not include `maxReachedStep`, step-label navigation, or base-row navigation. ### Decisions - Scope for this PR: module-row navigation only. - Skipped-settings fallback: no-op. When no selected module exposes configurable variables, the `module-settings` step is skipped and clicking a module row does nothing (there is no card to scroll to). ### Scroll timing `navigateToStep` triggers a window scroll reset via an existing effect keyed on `currentStep.id`. To cooperate, `navigateToModule` stores the target module id in a ref and a follow-up effect (declared after the scroll-reset effect, so it runs second) calls `scrollIntoView` inside `requestAnimationFrame` once `module-settings` has rendered. When already on `module-settings`, it scrolls immediately. ### Follow-up (deferred): full navigable sidebar Not part of this PR, documented for later. The remainder of #27077's item #2, rebased onto current `main`: - `onNavigateStep?: (stepId: StepId) => void` on `SelectionSummary`. - Clickable step labels: `Base Template` -> `base-infra`, `Modules` -> `module-select`, `Customizations` -> `customizations`. - Clickable selected base-template row -> `base-parameters` (fall back to `base-infra` when that step is skipped for the chosen base). - Back-stack semantics via a `maxReachedStep` prop so steps at or below the furthest-reached group stay `complete` and clickable even after navigating backward, while strictly-higher groups render as inert `upcoming`. - `StepIndicator` and `BaseTemplateSelection` render as `<button>` when a navigation handler is supplied, else stay inert. - Stories: `NavigationClicks`, `BackwardNavigation`, and `UpcomingStepsInert`. </details> --- Coder Agents generated, on behalf of @aqandrew. |
||
|
|
9b27d12929 |
chore: forbid direct response body JSON decode in codersdk (#27859)
Add a ruleguard rule forbidding direct `json.NewDecoder(res.Body).Decode(...)` on `*http.Response` in codersdk packages, so new typed endpoints use `codersdk.ReadBodyAsJSON` and keep returning structured errors for non-JSON bodies. The rule matches both the chained call form and decoders assigned to a variable first. Intentional raw-body paths carry documented `//nolint:gocritic` exceptions: the 16 agent-direct HTTP decodes in `workspacesdk/agentconn.go` route through a single `decodeAgentJSON` helper (agent-direct over tailnet, so `ReadBodyAsJSON`'s reverse proxy/SSO error guidance does not apply), and the Azure IMDS attested-document decode in `agentsdk/azure.go` keeps an inline exception. The two `UseNumber` decoders in `licenses.go` are migrated to a new `codersdk.ReadBodyAsJSONUseNumber`, so `coder licenses add/list` also return structured errors for non-JSON bodies instead of `invalid character '<' looking for beginning of value`. Note for local verification: golangci-lint caches results, so run `golangci-lint cache clean` after modifying `scripts/rules.go` or the rule may silently not fire. Final PR of the stack on #27804, #27857, and #27858. Refs #27044. Stack plan Inventory (full-tree audit): 280 migratable call sites across 47 files; 17 excluded (16 agent-direct HTTP sites in `workspacesdk/agentconn.go`, 1 Azure IMDS decode in `agentsdk/azure.go`). 1. **#27857** `refactor(codersdk): use ReadBodyAsJSON in typed endpoints`: mechanical migration of all sites except `chats.go` (224 sites, 46 files). 2. **#27858** `refactor(codersdk): use shared error helpers in chat endpoints`: migrate the 56 `chats.go` sites and consolidate the duplicated `readRawBodyAsError`/`newResponseError` helpers onto the shared `client.go` error path, with regression tests for the 409 usage-limit flow. 3. **#27859** `chore: forbid direct response body JSON decode in codersdk`: ruleguard rule with documented exceptions for the intentional raw-body paths, plus `ReadBodyAsJSONUseNumber` for the `licenses.go` decoders. Reviewed and updated by Coder Agents on behalf of @dylanhuff-at-coder. |
||
|
|
4e2620d64f |
fix(coderd/x/chatd): classify bedrock credential errors as non-retryable (#27913)
When a Bedrock provider is misconfigured without authentication methods, AWS credential resolution fails and AIBridge writes the error as a plain-text HTTP 500. The fantasy adapter captures the body text in `ProviderError.ResponseBody`, but `Error()` returns only the SDK transport wrapper, not the body. Signal patterns in `chaterror.Classify` checked only `err.Error()` (the wrapper), missing the useful text in `structured.detail` (the body). This caused permanent configuration errors to fall through to the generic 500 rule with `retryable=true`, making the chat worker retry up to 25 times. Introduce `combinedText` (merging the wrapper with `structured.detail`) and widen signal checks that have no dedicated status code to use it: overloaded, auth, config, usage limit, and timeout patterns. The deadline signal stays on `err.Error()` to avoid treating ambiguous body text as a local context deadline. Add a "resolve aws credentials" config pattern so credential resolution failures classify as config, not generic. > Generated by Coder Agents |
||
|
|
2d320de71e |
docs(docs/.style/style-guide): adopt STE-derived prose rules (#27852)
Stacked on #27849. Incorporates the transferable rules from [ASD-STE100 Simplified Technical English](https://www.asd-ste100.org/) (Issue 9, 2025) into the prose style guide, with per-rule attribution to the source rule numbers. STE is the controlled-language standard for aerospace maintenance documentation; this PR adopts its procedure-level discipline and clarity rules, not its controlled dictionary or grammar restrictions, which target a different audience. - New **Procedural writing** page: one instruction per step, condition before instruction, 20-word step budget, "callouts inform, steps instruct" (with the delete-the-callouts test), and warnings must state the consequence. - **Voice and tone**: sentence and paragraph budgets, verbs over noun forms, one clear referent per pronoun, and an explicit acknowledgment of the contractions trade-off for international readers. - **Word choice**: one term per concept, anchored on the glossary. - **Accessibility and inclusion**: the idioms rule now covers developer figurative verbs (spin up, tear down, stand up). - **README**: registers the new page and adds ASD-STE100 to the third-party references. All new rules are documentation-only (no Vale rule) because they need editorial judgment rather than pattern matching. --- 🤖 Built with AI assistance. |
||
|
|
aa039479ed |
docs: add style-guide rule against "whose" for non-person antecedents (#27866)
## What Adds a Word choice entry to the docs style guide, **"Whose for people, not things"**. It restricts "whose" to people and points writers to "with", "where", or "that has" for inanimate objects and abstract concepts, since "whose" implies personhood. ## Where `docs/.style/style-guide/word-choice.md`, inserted right after **Phrasal verbs and their noun forms**, the closest existing grammar/usage rule. Formatting matches the surrounding entries: sentence-case H2, a two-sentence rationale (one sentence per line), `**Do**` / `**Don't**` blockquotes, and a documentation-only enforcement note. ## Rule > "Whose" is the possessive of "who", so it implies the antecedent is a person. > When the antecedent is an inanimate object or an abstract concept, prefer "with", "where", or "that has". Example: - Don't: A chat whose gateway records have been pruned reports no cost. - Do: A chat with pruned gateway records reports no cost. ## Notes - Docs-only change (Markdown under `docs/`, no CI or build config), so it's out of scope for `/coder-agents-review`; the doc-check agent covers docs-only PRs. - The style-guide subpages are Vale-exempt, so no Vale rule ships with this. The enforcement note reads "Documentation-only. No Vale rule.", matching the other documentation-only entries. Linear: [DOCS-612](https://linear.app/codercom/issue/DOCS-612/style-guide-avoid-whose-for-non-person-antecedents) > This PR was created with AI assistance (Coder Agents). |
||
|
|
d9d6ce9ddf |
perf(coderd/rbac): build span role attributes only when recording (#27310)
`rbacTraceAttributes` materialized the subject's role names (one string allocation per role) and was passed into every `Filter`, `Authorize`, and `Prepare` span at creation time, so the O(roles) work ran even when no tracer was recording. It also called `SafeRoleNames()` twice. Replace it with `setRBACAttributes`, which attaches the same attributes *after* the span is created and only when `span.IsRecording()` is true, reading `SafeRoleNames()` once. Recorded spans are unchanged; untraced and unsampled calls skip the per-role work. This originated from #27309: once `/authcheck` checks are batched through `rbac.Filter`, each below-threshold group paid the role-attribute build for the `Filter` span *and* for every per-object `Authorize` span, so the redundant per-call work showed up as extra allocations per request. ## Benchmarks `AMD EPYC 9575F`, `benchstat`, no tracer configured (exercises the `IsRecording()==false` path). **`BenchmarkRBACManyOrgs`** (general RBAC eval), before vs after: wall time flat (geomean −0.04%), allocations strictly lower everywhere (geomean B/op −0.52%; `Authorize` −1.0 to −1.3% B/op), no regressions. **Authcheck path** (`BenchmarkAuthcheckGrouping`, #27309 vs #27310, back-to-back): this change is an **allocation reduction and is time-neutral**. On the endpoint (`Grouped`) path, per-request allocations drop ~4-5% B/op at common org counts (1-10); on the pure per-object path the reduction grows with org count (B/op −2.6% → −7.3% at 100 orgs). Wall time is flat within noise: low-org deltas sit inside this host's ±10-23% run-to-run variance, so no wall-time claim is made. Net: same speed, less garbage per request, which also lowers GC pressure under real concurrent load. <details> <summary>Decision log</summary> - The `Filter` span wraps the whole filtering routine (total latency + `num_objects`); it is the valuable span and is kept. The costly part was `rbacTraceAttributes`, not the span itself. - `rbacTraceAttributes` was O(roles): it allocated a string per role for the `subject_roles` attribute and called `SafeRoleNames()` twice. On `Filter`'s below-threshold fallback it ran once for the `Filter` span and again for each per-object `Authorize` span, so a group of N objects paid N+1 builds vs the old loop's N. Benchmarks confirm this as real per-call allocation; its wall-time cost is below the authcheck benchmark's noise floor. - Deferring attribute construction behind `IsRecording()` requires the span object, so the three callsites moved from `StartSpan(ctx, rbacTraceAttributes(...))` to `StartSpan(ctx)` then `setRBACAttributes(span, ...)`. No spans were removed or renamed; recorded output is identical. - Tradeoff: when a span is not recording, `subject_roles`/`num_subject_roles`/etc. are not computed. Unsampled spans emit nothing anyway, so there is no observable output change. </details> --- Authored with Coder Agents. |
||
|
|
51a9aa1bfc |
perf(coderd): batch authcheck permissions via rbac.Filter (#27309)
`POST /api/v2/authcheck` evaluated every check with a full policy evaluation in a serial loop. A subject in many organizations (100+) produced hundreds of full evaluations, taking seconds on a cold cache (DEVEX-608). Group the checks by `(action, resource type)` and authorize each group with the existing `rbac.Filter`, which amortizes a single partial evaluation across the group once it is large enough. Each check is wrapped in a small value struct that carries its response key, so `Filter`'s returned subset maps back to keys by reading a field rather than relying on element identity. `Filter` now takes an explicit `prepareThreshold`; existing callers pass the new `rbac.DefaultFilterThreshold` (10), and `checkAuthorization` passes 50, above the ~35-group crossover measured for this workload, so subjects with few objects of a given type keep the per-object path and cannot regress. ## Stacking This is stacked on top of #27244. `Filter` runs `Prepare` (partial evaluation), and those residuals are only compact once #27244's set-membership residuals land. On plain `main` the existing O(N) residual fanout means batching can regress at high org counts, so this change should land with or after #27244. <details> <summary>Decision log</summary> ### Bottleneck - `site/src/modules/permissions/organizations.ts` defines ~14 permission checks per org; `organizationsPermissions()` flattens them across all orgs into one `POST /api/v2/authcheck`. A 100-org request is ~1400 checks. - `checkAuthorization` looped serially, calling `Authorizer.Authorize` (full eval) once per check. - The endpoint's `maxFetch = 10` only caps checks that carry a `resource_id`, not total checks, so it does not bound this workload. ### Approach - Group checks by `(action, resource type)` and run each group through `rbac.Filter`, which does one partial evaluation (`Prepare`) and reuses it across the group. - Carry the response key as data in a small value struct implementing `RBACObject()`, so allowed results map back to keys without pointer identity: ```go type authorizeCheck struct { key string object rbac.Object } func (c authorizeCheck) RBACObject() rbac.Object { return c.object } ``` - `Filter` takes a required `prepareThreshold int` (no functional options). Generic callers pass `rbac.DefaultFilterThreshold = 10`; `/authcheck` passes 50 because the measured crossover for this workload is ~35 groups. ### Alternatives rejected - **Bounded `errgroup` parallelism**: reduced wall time at high org counts but not aggregate work (allocations flat). Discarded in favor of reducing work via partial evaluation. - **Symmetric-deny Rego simplification** (on the #27244 branch): replacing the known-org deny-fold with symmetric `org := -1` / `scope_org := -1` rules failed existing SQL-compile tests. A `-1` known-org vote gated by `not org = -1` produces a negated membership test over the unknown org id, which OPA emits as an unconvertible support rule. #27244's fold (`member_allow - org_deny`, a positive set-difference membership test) is therefore load-bearing, not incidental. </details> --- Authored with Coder Agents. --------- Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com> |
||
|
|
7e708b24ce |
perf(coderd/rbac): collapse org authorization to a set-membership test (#27244)
## Problem Authorization for users who belong to many organizations is slow. On the list <br>endpoints (`/api/v2/organizations`, `/users`, `/groups`) a user in hundreds of <br>orgs saw multi-second page loads <br>([DEVEX-608](https://linear.app/codercom/issue/DEVEX-608/performance-degrades-for-users-in-many-organizations-across-multiple) <br>/ coder/coder#21890 / Pylon [#2758](<https://github.com/coder/coder/issues/2758>)). This is partial-evaluation bound: `rbac.Prepare` <br>scales with the number of org-scoped roles the subject carries. ## Root cause The known-org path in `check_org_permissions` indexed an N-entry vote map by the <br>object's org id: ```rego vote := allow_map[input.object.org_owner] ``` `input.object.org_owner` is unknown during partial evaluation. Indexing a map by <br>an unknown key cannot reduce to a single expression, so OPA emits one residual <br>query per org membership, and `newPartialAuthorizer` then calls `PrepareForEval` <br>once per residual, making `Prepare` O(N) in org count. The list endpoints <br>intentionally use partial eval; the fan-out is in partial eval itself. ## Change Test the object's org id for membership in a set that is fully known at <br>partial-evaluation time, so the query collapses to a single <br>`organization_id = ANY(ARRAY[...])` residual instead of N residuals: * The known-org clause only ever votes to allow, tested via <br>`org_owner in org_ids_with_vote(role_org_votes, 1)`. * Org-level denies are folded into the org-member level as a ground set <br>difference (`member_allow - org_deny`), so the unknown org id appears in only <br>one positive membership test and the decision never branches on it. * The per-org vote maps are computed once as memoized zero-arg rules <br>(`role_org_votes`, `role_member_votes`, `scope_org_votes`, <br>`scope_member_votes`) instead of through parametrized functions that OPA <br>re-evaluates at every call site. * `role_allow`/`scope_allow`, the `any_org` path, and full evaluation are <br>unchanged in behavior. Semantics are unchanged (see the equivalence argument below). The only <br>representational change is that a denied known org's intermediate `org` vote is <br>now `0` instead of `-1`, compensated by the set difference and not observable in <br>the final `allow` decision. ## Results Measured with `BenchmarkRBACManyOrgs` (added on `main` in coder/coder#27270). Full tables: <br>[B/op and allocs/op](<https://github.com/coder/coder/pull/27244#issuecomment-4984523720>). * Residual queries: O(N) -> O(1). * `Prepare` / `PrepareAndCompile` memory changes from < />quadratic growth on `main` <br>(176 MiB, 7.08M allocs per op at 100 orgs) to near-linear (6.5 MiB, 258k <br>allocs), a < />96% reduction at 100 orgs, with similar wins in time. * Memoizing the vote maps removed an early single-org regression: at 1 org <br>`Prepare` now allocates < />7% fewer bytes and < />9% fewer objects than `main`. * `Authorize` (full evaluation) memory is marginally higher (+1-8%, largest at <br>1 org) and time-neutral. This is the inherent cost of the set-membership form <br>that keeps partial evaluation from fanning out; full evaluation builds an <br>allow set it would not otherwise need. * `go test ./coderd/rbac/...` passes, including `TestAuthorizeDomain` (full- vs <br>partial-eval equivalence) and the regosql suite. A second, independent bottleneck remains (out of scope here): the vote map is <br>still built in O(N^2) in `check_all_org_permissions` <br>(`roles[_].by_org_id[org_id]` scans all roles per org). Fixing it means <br>pre-merging roles' `by_org_id` into one org->perms map in the OPA input, and is <br>tracked as a follow-up. ## Testing * `OrgDenyBlocksMember` (`TestAuthorizeLevels`): an org-level deny blocks a <br>member-allowed action on an owned in-org object, while a clean org is allowed, <br>including an action-scoped deny. * `ScopeOrgDenyBlocksMember` (`TestAuthorizeScope`): the same fold at the scope <br>level. * The shared harness covers full and partial evaluation and asserts the partial <br>result compiles to SQL with zero support rules. <details><summary>Decision log and equivalence argument</summary> ### Why not deny-via-set-membership The first attempt expressed deny as a second set-membership clause (`:= -1 if org_owner in deny_set`). That makes `org`/`scope_org` multi-valued, and the `not org = -1` checks in `role_allow`/`scope_allow` then cause OPA to emit a `data.partial.__not__` support rule that regosql cannot compile (`TestAuthorizeDomain/UserACLList` failed). It failed even when the deny set was empty, purely because the `-1` clause exists. ### Why not deny-via-enumeration A follow-up enumerated only the (usually empty) deny set. It compiled and passed, but it branches on the unknown org id (one ground residual per denied org), which violates the "do not branch on the unknown" rule in `coderd/rbac/POLICY.md`. ### Final approach: allow-only + ground set difference The known-org clause votes only to allow, and the org-level deny gate is moved into the org-member level as `member_allow - org_deny`, a set difference over fully-known sets. The unknown org id is used only in positive `in` tests, so there is no enumeration, no negated membership, and no branching on the unknown. ### Empty-set residual pruning A naive set-membership left unsatisfiable residuals (`org_owner in set()`) for levels with no matching permissions (e.g. the org level for an org-member role, or scope-org for `ScopeAll`), each still costing a `PrepareForEval`. Guarding each membership with a ground `count(...) > 0` lets OPA drop those branches, flattening the residual count across org sizes. ### Memoized vote maps Profiling the single-org path showed the cost was repeated function evaluation: the parametrized helpers rebuilt the same vote map for the org, member, and scope paths on every check. Hoisting the maps into memoized zero-arg complete rules (which OPA evaluates once per query) removed that overhead and eliminated the single-org `Prepare` regression, while composition keeps the policy readable. ### Equivalence (known-org path, `site != -1`) * A: original `org == 1` <=> `org_owner in org_allow` (unchanged). * B: original `org != -1 and member == 1` <=> `org_owner not in org_deny and org_owner in member_allow` <=> `org_owner in (member_allow - org_deny)` = new `org_member == 1`. The critical case (`org` denies, member allows): old blocks it via `not org = -1`; new blocks it because `org_owner` is removed from `member_allow - org_deny`. Same outcome. Deny-wins aggregation is intact because `check_all_org_permissions` still nets an org to `-1` via `to_vote`, landing it in `org_deny`. </details> --- This PR was generated by Coder Agents on behalf of @jeremyruppel. |
||
|
|
f9047e5836 |
feat(site/src): reconcile chats-by-workspace cache across archive and watch paths (#27901)
Implements Phase 2 item 5 of the chats query architecture: by-workspace cache reconciliation. Stacked on #27892; base branch `feat/chat-search-invalidation`. ## Problem `chatsByWorkspace` mappings (flat `Record<workspaceId, chatId>`, IDs only, archived chats filtered server-side) go stale on archive/unarchive, workspace binding changes, and watch events (FINDINGS 2.3). Because the client cannot re-derive archived state from the cached map, the only correct repair for a stale mapping is synchronous removal plus family invalidation. ## Fix - New `removeChatFromChatsByWorkspace(queryClient, chatId)` in `site/src/api/queries/chats.ts`: value-match removal across the by-workspace family, reference-preserving when nothing is removed (mirrors the `patchChatMessages` no-op pattern). - `archiveChat.onSuccess` and the AgentsPageLayout archive-and-delete `onSuccess` synchronously remove the mapping; the existing `onSettled`/explicit invalidations then reconverge. - Watch handler: `deleted` branch removes then invalidates (remove-before-invalidate ordering); `created` root branch invalidates; merge path invalidates behind a new `shouldInvalidateChatsByWorkspace` predicate (`status_change`, `action_required` only; `created`/`deleted` have their own branches, title/summary/diff/context events do not move `updated_at` ordering); `onOpen` reconnect invalidates for convergence. - `useChatToolInvalidations`: workspace-binding tool completion (`create_workspace`) also invalidates by-workspace; this is the only reconciliation path on the embed route. ## Confirmed exclusions - No optimistic patch in `updateChatWorkspace.onMutate`; the awaited `onSettled` invalidation already converges. - No cancellation guard for the by-workspace family (Phase 2 item 9 territory). - No `createChat` change (already invalidates); no ACL or pin changes. ## Known constraints - Cascade archives remove only the event's own chat ID from the mapping; per-family-member `deleted` events plus family invalidation repair the rest. - The REST `patchChat` workspace-rebind branch publishes no watch event server-side, so cross-session manual rebinds converge only via the acting session's `onSettled` or a WorkspacesPage remount; not fixable client-side. ## Testing - `chats.test.ts`: removal scoping and reference-preservation tests; `it.each` wiring tests (archiveChat/unarchiveChat/updateChatWorkspace onSettled, createChat onSuccess invalidate by-workspace); synchronous-removal assertion for `archiveChat.onSuccess`; negative assertions for `updateChatTitle` and `createChatMessage`. - `AgentsPageLayout.test.ts`: exhaustive `ChatWatchEventKind` table for `shouldInvalidateChatsByWorkspace`. - `useChatToolInvalidations.test.tsx`: create_workspace regression test extended with a seeded by-workspace bystander. PR generated by Coder Agents. |
||
|
|
632eecc090 |
feat(site/src): reintroduce chat search cache invalidation (#27892)
Stacked on `feat/chat-cache-semantic-ops`. ## Bug Chat search results (`chatSearch` queries) were never invalidated, so the search dialog served stale results after archives, renames, deletions, new chats, message edits, and watch-driven status changes. ## Fix Reintroduces `invalidateChatSearches`, a prefix invalidation over the module-private `chatSearchFamilyKey`, and wires it into: - `chats.ts`: `archiveChat.onSettled`, `unarchiveChat.onSettled`, `updateChatTitle.onSettled`, `editChatMessage.onSettled`, `createChat.onSuccess` - `useChatStore.ts`: `upsertCacheMessages` (unconditional; assistant message bodies are indexed too) and `replaceCacheMessages` - `AgentsPageLayout.tsx`: the `deleted` and root `created` watch branches, the merge watch branch (gated by a new exported `shouldInvalidateChatSearches` helper), the `has_unread` clearing effect, the `onOpen` reconnect convergence, and `archiveAndDeleteMutation.onSuccess` The merge-branch gate only invalidates for search-affecting event kinds (`title_change`, `status_change`, `diff_status_change`, `action_required`). `summary_change`, `chat_summary_change`, and `context_dirty` are excluded: stale `last_turn_summary` subtitles are accepted until reconciliation lands. ## Backend constraint Message bodies only enter full-text search via the dbpurge backfill (`search_tsv` starts NULL and is populated every 10 minutes). Frontend invalidation fixes removals, ordering, and rendered fields immediately, but a chat that newly matches on message body will not appear until the next backfill. This is a server-side eventual-consistency limit we accept. ## Scope decisions (confirmed) - No invalidation in `createChatMessage.onSuccess`: the send path already routes through `useChatStore.upsertCacheMessages`; adding both would double-invalidate every send. - No invalidation for `pinChat`/`unpinChat`/`reorderPinnedChat` (ordering-only, self-heals). - ACL mutations out of scope. - No coalescing/debouncing; that belongs to a later reconciler PR. ## Tests - Prefix invalidation: multiple distinct `q` params invalidated, bystanders (list, by-workspace, entity, messages, cost tree) untouched. - Mutation wiring: settlement of `archiveChat`, `unarchiveChat`, `updateChatTitle`, `editChatMessage`, and `createChat` invalidates a seeded search key; `createChatMessage` asserted NOT to. - `shouldInvalidateChatSearches` unit-tested over all `ChatWatchEventKind` values. PR generated by Coder Agents. |
||
|
|
4b7494be72 |
feat: harden chat generation runtime instrumentation for billing (#27451)
Closes CODAGT-835 ## Summary `chat_messages.runtime_ms` becomes the billing source of truth for Coder Agents runtime (summed hourly by #27312), but it was built for debugging: the June refactor (#26270) silently stopped recording tool-step runtime, compaction was never measured, and interrupted turns lost their partial runtime entirely. This PR defines the billable metric, closes the paths that dropped it, and documents the definition where the data lives. ## The billable definition **`runtime_ms` is the wall-clock duration of the model invocation that produced the persisted message content**, measured from just before the provider stream opens until it is fully consumed. What counts: - Assistant generation steps, in top-level and sub-agent chats (sub-agents are ordinary chats on the same generation path). - Compaction summarization calls, persisted on the compaction assistant message (**new**). - Interrupted attempts: the message-part episode's lifetime is persisted on the partial assistant message committed by `FinishInterruption`, so partial generation time survives interruption (**new**; measured via a new `Buffer.EpisodeDuration`, which works even though the generation goroutine and the interrupt task are different tasks). What deliberately does not count (each is documented in code and docs): - **Local tool execution.** Tool wall time includes idle waits, most importantly `wait_agent` polling a sub-agent chat that already bills its own model invocations; billing the batch would double count, and excluding one tool from a concurrent batch's wall time is ill-defined. Pre-refactor instrumentation did include tool time; this makes the exclusion an explicit product definition instead of a silent regression. - **Failed model calls whose output is discarded** (retried attempts, terminal errors, content-filter refusals). They persist no content, so they bill nothing; billing errs toward undercounting. Notably a stream-silence timeout can burn 10 idle minutes before a retry, which should not be billable "active generation". If product later wants failed attempts billed, that needs a place to persist runtime on error turns (`FinishError` inserts no rows today) and is a deliberate follow-up, not instrumentation drift. - **Ancillary calls that produce no chat messages** (title generation, advisor, turn summaries) and all idle/parked time (`requires_action`, queueing). The definition is documented as `COMMENT ON COLUMN chat_messages.runtime_ms` (migration 000551, surfacing as a Go doc comment on `ChatMessage.RuntimeMs`), on `chatloop.PersistedStep.Runtime`, in the chatd architecture doc, and in the Spend Management docs page. ## Index for the hourly scan None needed: `GetTotalChatMessageRuntimeMsInRange` (#27312) filters an hour-wide `created_at` range, which the existing `idx_chat_messages_created_at` b-tree already serves; the residual `runtime_ms IS NOT NULL` filter applies to one hour of rows. A partial index would add permanent write amplification for a query that runs once an hour. > [!NOTE] > Migration 000551 is also claimed by #27312; whichever merges second renumbers via `fix_migration_numbers.sh`. ## Tests - End-to-end: the existing full-server generation test now asserts `RuntimeMs.Valid` on the committed assistant row (it previously read `.Int64` without checking `.Valid`, so it passed on NULL). - Interrupted turn: full task-level test (real DB, mock clock) asserting the partial assistant message persists the attempt's runtime. - Errored stream: asserts a failed invocation yields no step and no runtime. - Tool-using turn: asserts runtime lands on the assistant row only and tool rows stay NULL. - Compaction: asserts the summarization call duration is recorded and lands on the compaction assistant message only. - `messagepartbuffer.EpisodeDuration` unit coverage. Blocks: CODAGT-843 (B3), CODAGT-838 (D8). --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Hugo Dutka <hugo@coder.com> |
||
|
|
f96671d588 | refactor(site/src): centralize chat cache operations in semantic cache functions (#27869) | ||
|
|
3e0b943333 |
docs: note bulk stop confirmation (#27908)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell. ## What Restores the docs change that was reverted out of #27631. The bulk **Stop** action now shows a confirmation dialog (shipped in #27631), so the workspace management docs should reflect that stop, alongside update and delete, prompts for confirmation. ## How Updates the Bulk operations section of `docs/user-guides/workspace-management.md` to note that stop is now included in the actions that prompt for confirmation before running. <details> <summary>Reverted change being restored</summary> Before: > For update and delete, the user will be prompted for confirmation before any action is taken. After: > For update, delete, and stop, the user is prompted for confirmation before any action is taken. This content was originally added in #27631 (commit `e6a0aff`) and reverted in commit `2378960` before merge. </details> |
||
|
|
abd330702b |
chore: bump the vite group across 1 directory with 4 updates (#27735)
Bumps the vite group with 4 updates in the /site directory: [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react), [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite), [vite-plugin-checker](https://github.com/fi3ework/vite-plugin-checker) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). Updates `@vitejs/plugin-react` from 6.0.1 to 6.0.4 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite-plugin-react/releases">@vitejs/plugin-react's releases</a>.</em></p> <blockquote> <h2>plugin-react@6.0.4</h2> <h3>Fixed <code>$RefreshSig$ is not defined</code> error when running <code>vite dev</code> with <code>NODE_ENV=production</code></h3> <p>When running <code>vite dev</code> with <code>NODE_ENV=production</code>, the app errored with <code>$RefreshSig$ is not defined</code>. This error is now fixed.</p> <h2>plugin-react@6.0.3</h2> <p>No release notes provided.</p> <h2>plugin-react@6.0.2</h2> <h3>Allow all options in reactCompilerPreset (<a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/1189">#1189</a>)</h3> <p>This is a type only change. Only <code>compilationMode</code> and <code>target</code> options were available for <code>reactCompilerPreset</code>.</p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md">@vitejs/plugin-react's changelog</a>.</em></p> <blockquote> <h2>6.0.4 (2026-07-22)</h2> <h3>Fixed <code>$RefreshSig$ is not defined</code> error when running <code>vite dev</code> with <code>NODE_ENV=production</code></h3> <p>When running <code>vite dev</code> with <code>NODE_ENV=production</code>, the app errored with <code>$RefreshSig$ is not defined</code>. This error is now fixed.</p> <h2>6.0.3 (2026-06-23)</h2> <h3>Improve the react compiler preset filter to reduce false-positives (<a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/1138">#1138</a>)</h3> <p>Improved the filter in the react compiler babel preset to reduce the false-positives so that less modules are processed by the react compiler.</p> <h2>6.0.2 (2026-05-14)</h2> <h3>Allow all options in reactCompilerPreset (<a href="https://redirect.github.com/vitejs/vite-plugin-react/pull/1189">#1189</a>)</h3> <p>This is a type only change. Only <code>compilationMode</code> and <code>target</code> options were available for <code>reactCompilerPreset</code>.</p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/f4b549822ec239799d746c030abb0b9a7d8f0a04"><code>f4b5498</code></a> release: plugin-react@6.0.4</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/7a4065906e07e616aee23c4fcc76a76b74a7d694"><code>7a40659</code></a> fix(react): <code>$RefreshSig$ is not defined</code> with NODE_ENV=production vite dev ...</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/98b32d47a3f2517d52e8a51d8e28ff2ed13678a2"><code>98b32d4</code></a> fix(deps): update react 19.2.8 (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/1298">#1298</a>)</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/8ae5449be23079dd17fdefc64064a3d94be6fc39"><code>8ae5449</code></a> fix: babel-plugin-react-compiler cannot be imported when used in a framework ...</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/f09ea01b0b66a4900c3e42cef2aa0147e78b097c"><code>f09ea01</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/1282">#1282</a>)</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/640fd358a0e82393acfce4e92e19a6ac6e1641a7"><code>640fd35</code></a> release: plugin-react@6.0.3</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/889efb02cdc4ec978a5e177a37e0213cfded38a4"><code>889efb0</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/1249">#1249</a>)</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/6c57dd4c5d71075b48039df2532804e72880da21"><code>6c57dd4</code></a> fix(plugin-react): use '/' base in bundledDev preamble to fix non-root base p...</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/3cc33a703636b558a1c1c99e787ddc6bd64aab2d"><code>3cc33a7</code></a> fix(deps): update react-related dependencies (<a href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/1245">#1245</a>)</li> <li><a href="https://github.com/vitejs/vite-plugin-react/commit/c0f7c7ff709dc9d88bc1f29f1b27c1b3e2bfcfca"><code>c0f7c7f</code></a> docs: mention the Biome rule in the "Consistent components exports" section (...</li> <li>Additional commits viewable in <a href="https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.4/packages/plugin-react">compare view</a></li> </ul> </details> <br /> Updates `vite` from 8.0.10 to 8.1.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/releases">vite's releases</a>.</em></p> <blockquote> <h2>v8.1.5</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.5/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.4</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.4/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.3</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.3/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.2</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.2/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>create-vite@8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/create-vite@8.1.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.1.0-beta.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0-beta.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.0-beta.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.0-beta.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.16</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.16/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.15</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.15/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.14</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.14/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.13</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.13/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.12</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.12/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.0.11</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.0.11/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's changelog</a>.</em></p> <blockquote> <h2><!-- raw HTML omitted --><a href="https://github.com/vitejs/vite/compare/v8.1.4...v8.1.5">8.1.5</a> (2026-07-16)<!-- raw HTML omitted --></h2> <h3>Bug Fixes</h3> <ul> <li><strong>bundled-dev:</strong> avoid duplicated <code>buildEnd</code> (<a href="https://redirect.github.com/vitejs/vite/issues/22931">#22931</a>) (<a href="https://github.com/vitejs/vite/commit/810032097079be1a7da0e2b09ec9d92dd07ec13f">8100320</a>)</li> <li><strong>client:</strong> overlay error message format align rolldown (<a href="https://redirect.github.com/vitejs/vite/issues/22869">#22869</a>) (<a href="https://github.com/vitejs/vite/commit/5a72b8780705b575026617e86b0b92dea63a56a5">5a72b87</a>)</li> <li><strong>deps:</strong> update all non-major dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/22921">#22921</a>) (<a href="https://github.com/vitejs/vite/commit/fef682d3f067d534a559faf6fd9baedda2e9f8f1">fef682d</a>)</li> <li><strong>deps:</strong> update rolldown-related dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/22922">#22922</a>) (<a href="https://github.com/vitejs/vite/commit/3c345e475a5546a1cc6374682af89caebfe9c593">3c345e4</a>)</li> <li><strong>module-runner:</strong> don't crash stack-trace source mapping when globalThis.Buffer is absent (<a href="https://redirect.github.com/vitejs/vite/issues/22945">#22945</a>) (<a href="https://github.com/vitejs/vite/commit/f8b38e316bcefbf29f762f90ee49c88cd52c43b5">f8b38e3</a>)</li> <li><strong>optimizer:</strong> respect importer module format for dynamic import interop with CJS deps (<a href="https://redirect.github.com/vitejs/vite/issues/22951">#22951</a>) (<a href="https://github.com/vitejs/vite/commit/6c08c39ac4fb5868d080a51ff976a44693fc56ab">6c08c39</a>)</li> <li><strong>ssr:</strong> scope switch-case declarations to the switch, not the function (<a href="https://redirect.github.com/vitejs/vite/issues/22893">#22893</a>) (<a href="https://github.com/vitejs/vite/commit/b59a73f76f5557492d83d097bb33b3dd02f27d51">b59a73f</a>)</li> </ul> <h3>Documentation</h3> <ul> <li><strong>build:</strong> fix incorrect <code>@default</code> for build.cssMinify (<a href="https://redirect.github.com/vitejs/vite/issues/22948">#22948</a>) (<a href="https://github.com/vitejs/vite/commit/c88c236186d8e2384653e382dd0960ca1ff5b24c">c88c236</a>)</li> <li><strong>build:</strong> fix incorrect <code>@default</code> for build.lib.formats (<a href="https://redirect.github.com/vitejs/vite/issues/22911">#22911</a>) (<a href="https://github.com/vitejs/vite/commit/369ed609a4aace3aee4e4194a54990694aa4e7ac">369ed60</a>)</li> </ul> <h3>Tests</h3> <ul> <li>avoid scanner scanning all files under <code>__tests__</code> (<a href="https://redirect.github.com/vitejs/vite/issues/22912">#22912</a>) (<a href="https://github.com/vitejs/vite/commit/c961cae2868cc1521457ec60583867f0440e6949">c961cae</a>)</li> </ul> <h2><!-- raw HTML omitted --><a href="https://github.com/vitejs/vite/compare/v8.1.3...v8.1.4">8.1.4</a> (2026-07-09)<!-- raw HTML omitted --></h2> <h3>Features</h3> <ul> <li><strong>legacy:</strong> prefer oxc as minifier (fix <a href="https://redirect.github.com/vitejs/vite/issues/21973">#21973</a>) (<a href="https://redirect.github.com/vitejs/vite/issues/22468">#22468</a>) (<a href="https://github.com/vitejs/vite/commit/ab5dafa8e66296ef201f615489fb57954bb740ce">ab5dafa</a>)</li> </ul> <h3>Bug Fixes</h3> <ul> <li><strong>build:</strong> add workaround for building on stackblitz (<a href="https://redirect.github.com/vitejs/vite/issues/22840">#22840</a>) (<a href="https://github.com/vitejs/vite/commit/575c32c29925c554f4ef4068738ab89c6878f615">575c32c</a>)</li> <li><strong>build:</strong> keep <code>import.meta.url</code> in preload function as-is (<a href="https://redirect.github.com/vitejs/vite/issues/22839">#22839</a>) (<a href="https://github.com/vitejs/vite/commit/f1f90ed4742b3cf453428c7e581a6016a4d47321">f1f90ed</a>)</li> <li><strong>deps:</strong> update all non-major dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/22865">#22865</a>) (<a href="https://github.com/vitejs/vite/commit/d4295a9ffce428c0e51892373e00c07fccc0498a">d4295a9</a>)</li> <li><strong>deps:</strong> update rolldown-related dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/22866">#22866</a>) (<a href="https://github.com/vitejs/vite/commit/7cf07e4c5f7a6af276012e0c2ec06e08499e951e">7cf07e4</a>)</li> <li><strong>html:</strong> avoid backtracking in import-only check (<a href="https://redirect.github.com/vitejs/vite/issues/22848">#22848</a>) (<a href="https://github.com/vitejs/vite/commit/b5868c01a124d345664450aaebd677bfba964c05">b5868c0</a>)</li> <li><strong>optimizer:</strong> avoid optimizer run for transform request before init (<a href="https://redirect.github.com/vitejs/vite/issues/22852">#22852</a>) (<a href="https://github.com/vitejs/vite/commit/72a5e2192506f51a5efd09c059815a5c43a9eacb">72a5e21</a>)</li> <li><strong>ssr:</strong> align named export function call stacktrace column with Node (<a href="https://redirect.github.com/vitejs/vite/issues/22829">#22829</a>) (<a href="https://github.com/vitejs/vite/commit/173a1b648c321e0f836e5a94fc47c4fa9b081bfc">173a1b6</a>)</li> <li>strip pure CSS chunk imports when chunkImportMap is enabled (<a href="https://redirect.github.com/vitejs/vite/issues/22841">#22841</a>) (<a href="https://github.com/vitejs/vite/commit/648bd04933093d0aac9565f21a49811437776886">648bd04</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>fix incorrect <code>@default</code> for <code>server.cors</code> (<a href="https://redirect.github.com/vitejs/vite/issues/22859">#22859</a>) (<a href="https://github.com/vitejs/vite/commit/70435b2551ee4fe3a0d55c8a3bb61b96f44d2763">70435b2</a>)</li> </ul> <h3>Miscellaneous Chores</h3> <ul> <li><strong>deps:</strong> update dependency postcss-modules to v9 (<a href="https://redirect.github.com/vitejs/vite/issues/22867">#22867</a>) (<a href="https://github.com/vitejs/vite/commit/a9539d69efc7a4ccf988bbf5da31c2b416ba990e">a9539d6</a>)</li> </ul> <h3>Code Refactoring</h3> <ul> <li>eliminate ineffectiveDynamicImport warn (<a href="https://redirect.github.com/vitejs/vite/issues/22876">#22876</a>) (<a href="https://github.com/vitejs/vite/commit/ea22fb352aad9a42c0a9d08f39d8a0bae8c111a5">ea22fb3</a>)</li> </ul> <h3>Tests</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitejs/vite/commit/5e7fe129a4dde4f41934083b25e490059985f4e6"><code>5e7fe12</code></a> release: v8.1.5</li> <li><a href="https://github.com/vitejs/vite/commit/6c08c39ac4fb5868d080a51ff976a44693fc56ab"><code>6c08c39</code></a> fix(optimizer): respect importer module format for dynamic import interop wit...</li> <li><a href="https://github.com/vitejs/vite/commit/5a72b8780705b575026617e86b0b92dea63a56a5"><code>5a72b87</code></a> fix(client): overlay error message format align rolldown (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22869">#22869</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/f8b38e316bcefbf29f762f90ee49c88cd52c43b5"><code>f8b38e3</code></a> fix(module-runner): don't crash stack-trace source mapping when globalThis.Bu...</li> <li><a href="https://github.com/vitejs/vite/commit/810032097079be1a7da0e2b09ec9d92dd07ec13f"><code>8100320</code></a> fix(bundled-dev): avoid duplicated <code>buildEnd</code> (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22931">#22931</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/c88c236186d8e2384653e382dd0960ca1ff5b24c"><code>c88c236</code></a> docs(build): fix incorrect <code>@default</code> for build.cssMinify (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22948">#22948</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/b59a73f76f5557492d83d097bb33b3dd02f27d51"><code>b59a73f</code></a> fix(ssr): scope switch-case declarations to the switch, not the function (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22">#22</a>...</li> <li><a href="https://github.com/vitejs/vite/commit/fef682d3f067d534a559faf6fd9baedda2e9f8f1"><code>fef682d</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22921">#22921</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/3c345e475a5546a1cc6374682af89caebfe9c593"><code>3c345e4</code></a> fix(deps): update rolldown-related dependencies (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22922">#22922</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/369ed609a4aace3aee4e4194a54990694aa4e7ac"><code>369ed60</code></a> docs(build): fix incorrect <code>@default</code> for build.lib.formats (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22911">#22911</a>)</li> <li>Additional commits viewable in <a href="https://github.com/vitejs/vite/commits/v8.1.5/packages/vite">compare view</a></li> </ul> </details> <br /> Updates `vite-plugin-checker` from 0.13.0 to 0.14.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/fi3ework/vite-plugin-checker/releases">vite-plugin-checker's releases</a>.</em></p> <blockquote> <h2>vite-plugin-checker@0.14.1</h2> <h3> 🚨 Breaking Changes</h3> <ul> <li>Remove support for vue2/vls - by <a href="https://github.com/danielroe"><code>@danielroe</code></a> in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/708">fi3ework/vite-plugin-checker#708</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/bbf2aa3"><!-- raw HTML omitted -->(bbf2a)<!-- raw HTML omitted --></a></li> <li><strong>deps</strong>: Update dependency chokidar to v5 - in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/688">fi3ework/vite-plugin-checker#688</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/814f22b"><!-- raw HTML omitted -->(814f2)<!-- raw HTML omitted --></a></li> </ul> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>deps</strong>: <ul> <li>Update dependency tinyglobby to ^0.2.16 - in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/693">fi3ework/vite-plugin-checker#693</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/198d23c"><!-- raw HTML omitted -->(198d2)<!-- raw HTML omitted --></a></li> <li>Update react monorepo - in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/703">fi3ework/vite-plugin-checker#703</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/af01fd7"><!-- raw HTML omitted -->(af01f)<!-- raw HTML omitted --></a></li> <li>Update dependency <code>@babel/code-frame</code> to ^7.29.0 - in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/702">fi3ework/vite-plugin-checker#702</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/9b0b81a"><!-- raw HTML omitted -->(9b0b8)<!-- raw HTML omitted --></a></li> <li>Update dependency vue to ^3.5.32 - in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/694">fi3ework/vite-plugin-checker#694</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/f673a4f"><!-- raw HTML omitted -->(f673a)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>eslint</strong>: <ul> <li>Lazily import eslint - by <a href="https://github.com/danielroe"><code>@danielroe</code></a> in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/709">fi3ework/vite-plugin-checker#709</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/83adffe"><!-- raw HTML omitted -->(83adf)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>oxlint</strong>: <ul> <li>File format not being found - by <a href="https://github.com/H4ad"><code>@H4ad</code></a> in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/714">fi3ework/vite-plugin-checker#714</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/3e4ab68"><!-- raw HTML omitted -->(3e4ab)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>tsc</strong>: <ul> <li>Force <code>noEmit</code> when <code>tsconfig.json</code> can't be parsed - by <a href="https://github.com/danielroe"><code>@danielroe</code></a> in <a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/721">fi3ework/vite-plugin-checker#721</a> <a href="https://github.com/fi3ework/vite-plugin-checker/commit/590dcf5"><!-- raw HTML omitted -->(590dc)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5> <a href="https://github.com/fi3ework/vite-plugin-checker/compare/vite-plugin-checker@0.13.0...vite-plugin-checker@0.14.1">View changes on GitHub</a></h5> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/5ab7cbb167453d35360ff24ddad718b827eec3f1"><code>5ab7cbb</code></a> v0.14.5</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/bdd5c4d3b2333e98c259cca8c9656a15ddae811f"><code>bdd5c4d</code></a> feat(eslint,stylelint,biome,oxlint): schedule lint runs across checkers (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/707">#707</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/4ebec51d0e7583d1e0a1e2b00c58278207ee23a2"><code>4ebec51</code></a> fix(typescript): import absolute typescriptPath via file URL on Windows</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/d33d281f134228c00ffc6c93e22ae39fdce3c2f2"><code>d33d281</code></a> feat(typescript): add experimental support for TypeScript 7 (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/779">#779</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/7026910c9766e38bd53f37f3e4471df1608814d5"><code>7026910</code></a> fix(oxlint): guard <code>runOxlint</code> against spawn errors (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/730">#730</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/e31fb72859d291464c8b2b83e2bc72324f68fd05"><code>e31fb72</code></a> fix(eslint): fix path resolution for changed files (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/778">#778</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/15960c4e921de49615224572390e1767c26cc00a"><code>15960c4</code></a> fix(checker): don't crash when a watched file is removed mid-lint (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/773">#773</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/132b9bdc98d1295777f4f5b762f5442066e15336"><code>132b9bd</code></a> fix: emit un-based runtime specifier for virtual entry with custom base (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/782">#782</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/9ec07682ddaf9e5b684b3452f1d76da57942c2c3"><code>9ec0768</code></a> chore(deps): update dependency lint-staged to v17.1.0 (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/772">#772</a>)</li> <li><a href="https://github.com/fi3ework/vite-plugin-checker/commit/5253f482323c2cb2ccf31a63a13eccc84a37206c"><code>5253f48</code></a> chore(deps): update actions/cache digest to caa2961 (<a href="https://redirect.github.com/fi3ework/vite-plugin-checker/issues/775">#775</a>)</li> <li>Additional commits viewable in <a href="https://github.com/fi3ework/vite-plugin-checker/compare/vite-plugin-checker@0.13.0...v0.14.5">compare view</a></li> </ul> </details> <br /> Updates `vitest` from 4.1.5 to 4.1.10 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitest-dev/vitest/releases">vitest's releases</a>.</em></p> <blockquote> <h2>v4.1.10</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: Check fs access in builtin commands [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a>, <strong>Hiroshi Ogawa</strong> and <strong>OpenCode (claude-opus-4-8)</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a> <a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li> <li><strong>vm</strong>: Fix external module resolve error with deps optimizer query for encoded URI [backport to v4] - by <a href="https://github.com/SveLil"><code>@SveLil</code></a> and <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a> <a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View changes on GitHub</a></h5> <h2>v4.1.9</h2> <h3>🐞 Bug Fixes</h3> <ul> <li>Fix <code>importOriginal</code> with optimizer and query import [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>David Harris</strong>, <strong>Codex</strong>and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10546">vitest-dev/vitest#10546</a> <a href="https://github.com/vitest-dev/vitest/commit/a5180190c"><!-- raw HTML omitted -->(a5180)<!-- raw HTML omitted --></a></li> <li><strong>browser</strong>: <ul> <li>Wait for orchestrator readiness before resolving browser sessions [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10555">vitest-dev/vitest#10555</a> <a href="https://github.com/vitest-dev/vitest/commit/7fb29651a"><!-- raw HTML omitted -->(7fb29)<!-- raw HTML omitted --></a></li> <li>Wait for iframe tester readiness before preparing [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10497">vitest-dev/vitest#10497</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10556">vitest-dev/vitest#10556</a> <a href="https://github.com/vitest-dev/vitest/commit/fbc626c40"><!-- raw HTML omitted -->(fbc62)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>mocker</strong>: <ul> <li>Hoist vi.mock() for vite-plus/test imports [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>LongYinan</strong>, <strong>Claude Opus 4.8</strong> and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10548">vitest-dev/vitest#10548</a> <a href="https://github.com/vitest-dev/vitest/commit/2c9559c02"><!-- raw HTML omitted -->(2c955)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>pool</strong>: <ul> <li>Prevent test run hang on worker crash [backport to v4] - by <strong>Ari Perkkiö</strong> and <strong>Jattioui Ismail</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10543">vitest-dev/vitest#10543</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10564">vitest-dev/vitest#10564</a> <a href="https://github.com/vitest-dev/vitest/commit/934b0f587"><!-- raw HTML omitted -->(934b0)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5><a href="https://github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9">View changes on GitHub</a></h5> <h2>v4.1.8</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: <ul> <li>Disable client <code>cdp</code> API when <code>allowWrite/allowExec: false</code> [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> and <strong>Codex</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10450">vitest-dev/vitest#10450</a> <a href="https://github.com/vitest-dev/vitest/commit/e4067b3b1"><!-- raw HTML omitted -->(e4067)<!-- raw HTML omitted --></a></li> <li>Remove orphaned Playwright route when same module is mocked via multiple ids [backport to v4] - by <a href="https://github.com/toxik"><code>@toxik</code></a> and <a href="https://github.com/Zelys-DFKH"><code>@Zelys-DFKH</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10474">vitest-dev/vitest#10474</a> <a href="https://github.com/vitest-dev/vitest/commit/675b4343f"><!-- raw HTML omitted -->(675b4)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.7...v4.1.8">View changes on GitHub</a></h5> <h2>v4.1.7</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>runner</strong>: Limit concurrency per task branch in addition to per leaf callbacks (backport) - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10384">vitest-dev/vitest#10384</a> <a href="https://github.com/vitest-dev/vitest/commit/4f0f2a1ee"><!-- raw HTML omitted -->(4f0f2)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.6...v4.1.7">View changes on GitHub</a></h5> <h2>v4.1.6</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: Provide project reference in <code>ToMatchScreenshotResolvePath</code> - by <a href="https://github.com/macarie"><code>@macarie</code></a> and <a href="https://github.com/sheremet-va"><code>@sheremet-va</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10138">vitest-dev/vitest#10138</a> <a href="https://github.com/vitest-dev/vitest/commit/31882607c"><!-- raw HTML omitted -->(31882)<!-- raw HTML omitted --></a></li> <li>Global <code>sequence.concurrent: true</code> with top-level <code>test(..., { concurrent: false })</code> + depreacte <code>sequential</code> test API and options - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a>, <strong>Codex</strong> and <a href="https://github.com/sheremet-va"><code>@sheremet-va</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10196">vitest-dev/vitest#10196</a> <a href="https://github.com/vitest-dev/vitest/commit/2847dfa2a"><!-- raw HTML omitted -->(2847d)<!-- raw HTML omitted --></a></li> <li><strong>browser</strong>: Simplify orchestrator otel carrier - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10285">vitest-dev/vitest#10285</a> <a href="https://github.com/vitest-dev/vitest/commit/18af98cee"><!-- raw HTML omitted -->(18af9)<!-- raw HTML omitted --></a></li> </ul> <h3> 🏎 Performance</h3> <ul> <li>Stringify diff objects only once - by <a href="https://github.com/sheremet-va"><code>@sheremet-va</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10276">vitest-dev/vitest#10276</a> <a href="https://github.com/vitest-dev/vitest/commit/9f7b1528c"><!-- raw HTML omitted -->(9f7b1)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.5...v4.1.6">View changes on GitHub</a></h5> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitest-dev/vitest/commit/db616d227b6e0cb07a94f5d1bba262ee95db7e46"><code>db616d2</code></a> chore: release v4.1.10 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10718">#10718</a>)</li> <li><a href="https://github.com/vitest-dev/vitest/commit/bae52b5112a6fd8200101b88bf8af9685d077295"><code>bae52b5</code></a> fix(vm): fix external module resolve error with deps optimizer query for enco...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/a7a61e78c7d0718f00173cff6800a91a344457d4"><code>a7a61e7</code></a> chore: release v4.1.9 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10598">#10598</a>)</li> <li><a href="https://github.com/vitest-dev/vitest/commit/934b0f587cb61d8338d83f525295322692a2db40"><code>934b0f5</code></a> fix(pool): prevent test run hang on worker crash (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10543">#10543</a>) [backport to v4] (#...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/7fb29651afbae2a9b0cefe6c031a9308f168ac60"><code>7fb2965</code></a> fix(browser): wait for orchestrator readiness before resolving browser sessio...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/a5180190c1be7089e3705e3dd9e84fea118d09d3"><code>a518019</code></a> fix: fix <code>importOriginal</code> with optimizer and query import [backport to v4] (#...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/e61f2dd2a0ba0a266c1c5e0334aad3799fee527f"><code>e61f2dd</code></a> chore: release v4.1.8</li> <li><a href="https://github.com/vitest-dev/vitest/commit/e4067b3b150005fd42cf75f994300119245806b9"><code>e4067b3</code></a> fix(browser): disable client <code>cdp</code> API when <code>allowWrite/allowExec: false</code> [ba...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/a09d47236e19fd3151351080c667036ca6164dc4"><code>a09d472</code></a> chore: release v4.1.7</li> <li><a href="https://github.com/vitest-dev/vitest/commit/a8fd24c1cad2320b19fcc651413c7d928423bdc1"><code>a8fd24c</code></a> chore: release v4.1.6</li> <li>Additional commits viewable in <a href="https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/vitest">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> |
||
|
|
8ebdc50b77 |
chore: bump @vitest/browser-playwright from 4.1.7 to 4.1.10 in /site (#27743)
Bumps [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright) from 4.1.7 to 4.1.10. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitest-dev/vitest/releases">@vitest/browser-playwright's releases</a>.</em></p> <blockquote> <h2>v4.1.10</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: Check fs access in builtin commands [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a>, <strong>Hiroshi Ogawa</strong> and <strong>OpenCode (claude-opus-4-8)</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a> <a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li> <li><strong>vm</strong>: Fix external module resolve error with deps optimizer query for encoded URI [backport to v4] - by <a href="https://github.com/SveLil"><code>@SveLil</code></a> and <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a> <a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View changes on GitHub</a></h5> <h2>v4.1.9</h2> <h3>🐞 Bug Fixes</h3> <ul> <li>Fix <code>importOriginal</code> with optimizer and query import [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>David Harris</strong>, <strong>Codex</strong>and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10546">vitest-dev/vitest#10546</a> <a href="https://github.com/vitest-dev/vitest/commit/a5180190c"><!-- raw HTML omitted -->(a5180)<!-- raw HTML omitted --></a></li> <li><strong>browser</strong>: <ul> <li>Wait for orchestrator readiness before resolving browser sessions [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10555">vitest-dev/vitest#10555</a> <a href="https://github.com/vitest-dev/vitest/commit/7fb29651a"><!-- raw HTML omitted -->(7fb29)<!-- raw HTML omitted --></a></li> <li>Wait for iframe tester readiness before preparing [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10497">vitest-dev/vitest#10497</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10556">vitest-dev/vitest#10556</a> <a href="https://github.com/vitest-dev/vitest/commit/fbc626c40"><!-- raw HTML omitted -->(fbc62)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>mocker</strong>: <ul> <li>Hoist vi.mock() for vite-plus/test imports [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>LongYinan</strong>, <strong>Claude Opus 4.8</strong> and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10548">vitest-dev/vitest#10548</a> <a href="https://github.com/vitest-dev/vitest/commit/2c9559c02"><!-- raw HTML omitted -->(2c955)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>pool</strong>: <ul> <li>Prevent test run hang on worker crash [backport to v4] - by <strong>Ari Perkkiö</strong> and <strong>Jattioui Ismail</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10543">vitest-dev/vitest#10543</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10564">vitest-dev/vitest#10564</a> <a href="https://github.com/vitest-dev/vitest/commit/934b0f587"><!-- raw HTML omitted -->(934b0)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5><a href="https://github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9">View changes on GitHub</a></h5> <h2>v4.1.8</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: <ul> <li>Disable client <code>cdp</code> API when <code>allowWrite/allowExec: false</code> [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> and <strong>Codex</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10450">vitest-dev/vitest#10450</a> <a href="https://github.com/vitest-dev/vitest/commit/e4067b3b1"><!-- raw HTML omitted -->(e4067)<!-- raw HTML omitted --></a></li> <li>Remove orphaned Playwright route when same module is mocked via multiple ids [backport to v4] - by <a href="https://github.com/toxik"><code>@toxik</code></a> and <a href="https://github.com/Zelys-DFKH"><code>@Zelys-DFKH</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10474">vitest-dev/vitest#10474</a> <a href="https://github.com/vitest-dev/vitest/commit/675b4343f"><!-- raw HTML omitted -->(675b4)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.7...v4.1.8">View changes on GitHub</a></h5> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitest-dev/vitest/commit/db616d227b6e0cb07a94f5d1bba262ee95db7e46"><code>db616d2</code></a> chore: release v4.1.10 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright/issues/10718">#10718</a>)</li> <li><a href="https://github.com/vitest-dev/vitest/commit/5c18dd267ff7f47f24cab2f615a16b37d90feb7f"><code>5c18dd2</code></a> fix(browser): check fs access in builtin commands [backport to v4] (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright/issues/10680">#10680</a>)</li> <li><a href="https://github.com/vitest-dev/vitest/commit/a7a61e78c7d0718f00173cff6800a91a344457d4"><code>a7a61e7</code></a> chore: release v4.1.9 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright/issues/10598">#10598</a>)</li> <li><a href="https://github.com/vitest-dev/vitest/commit/e61f2dd2a0ba0a266c1c5e0334aad3799fee527f"><code>e61f2dd</code></a> chore: release v4.1.8</li> <li><a href="https://github.com/vitest-dev/vitest/commit/675b4343fd82e094f0bed9c2b28489ce815f9c28"><code>675b434</code></a> fix(browser): remove orphaned Playwright route when same module is mocked via...</li> <li><a href="https://github.com/vitest-dev/vitest/commit/e4067b3b150005fd42cf75f994300119245806b9"><code>e4067b3</code></a> fix(browser): disable client <code>cdp</code> API when <code>allowWrite/allowExec: false</code> [ba...</li> <li>See full diff in <a href="https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/browser-playwright">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> |
||
|
|
78b5a0f5a2 |
feat(cli): add --agents-allowed to template commands (#27517)
Relates to CODAGT-713 Depends on #27515 This adds `--agents-allowed` to `coder templates create` and `coder templates edit`. Template creation defaults the option to true, matching the per-template API and database default, while template editing only changes the value when the flag is explicitly supplied so unrelated edits preserve the existing setting. The generated CLI help and reference documentation include the new option. #27518 updates the Coder Agents platform controls documentation to describe the completed per-template model. |
||
|
|
6c8a8647f6 |
fix(site): name template versions in promote/archive dialogs and toasts (#27633)
> [!NOTE] > These were previously returning as typed values in the `api.ts`, however, they were not actually typed in this way and updating them wouldn't have worked for the `promotion` as it would fall back to needing to validate against the template. Archive toasts showed `"undefined"` because the API does not return a `TemplateVersion`. Toast/dialog copy now comes from the selected version. - Hold the full `TemplateVersion` for promote/archive confirms (global pattern elsewhere) - Name the version in confirm dialogs and success/error toasts - Type archive/unarchive API helpers as `Promise<void>` <img width="772" height="152" alt="image" src="https://github.com/user-attachments/assets/0063ebdc-09a3-4041-bfa0-d4c70b57159b" /> |
||
|
|
2484f4b047 |
chore: bump @tailwindcss/typography from 0.5.19 to 0.5.20 in /site (#27754)
Bumps [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography) from 0.5.19 to 0.5.20. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tailwindlabs/tailwindcss-typography/releases">@tailwindcss/typography's releases</a>.</em></p> <blockquote> <h2>v0.5.20</h2> <h3>Fixed</h3> <ul> <li>Support installing with stable versions of Tailwind CSS v4 (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/424">#424</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/tailwindlabs/tailwindcss-typography/blob/main/CHANGELOG.md">@tailwindcss/typography's changelog</a>.</em></p> <blockquote> <h2>[0.5.20] - 2026-06-08</h2> <h3>Fixed</h3> <ul> <li>Support installing with stable versions of Tailwind CSS v4 (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/424">#424</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/e3714a3fe55551ce9d51eec4721183ed6b1d5cd1"><code>e3714a3</code></a> 0.5.20</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/f34283d2961e18dd0dc2a849702e0dfd45fc80cb"><code>f34283d</code></a> Update tailwindcss peer dependency version (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/424">#424</a>)</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/543de4274390e90c4aab5d216729b46a3ba5541b"><code>543de42</code></a> bump Node.js</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/881b0488df9fd05e5361276b66a9ee8e7f39a3a7"><code>881b048</code></a> Setup OIDC (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/423">#423</a>)</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/74a3da779bb43e4e68f446395224c768704c1fb6"><code>74a3da7</code></a> Fix typo in README.md (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/413">#413</a>)</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/3963dfede4845f46451db1863fd5321f4cdea03b"><code>3963dfe</code></a> Bump js-yaml from 3.14.1 to 3.14.2 (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/410">#410</a>)</li> <li><a href="https://github.com/tailwindlabs/tailwindcss-typography/commit/abf85cc6e1b4f9b914b0f66453e5a97a9899a15c"><code>abf85cc</code></a> className instead of classname (<a href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/406">#406</a>)</li> <li>See full diff in <a href="https://github.com/tailwindlabs/tailwindcss-typography/compare/v0.5.19...v0.5.20">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 <code>@tailwindcss/typography</code> since your current version.</p> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
d2f9280138 |
chore: remove legacy chat template allowlist (#27515)
Relates to CODAGT-713 Depends on #27514 Removes the legacy deployment-wide allowlist now that the API and frontend use per-template `agents_allowed`: the experimental `/template-allowlist` routes, SDK methods and generated types, site config queries, frontend bindings, and the now-unused `xjson` utility. Migration `000563` deletes the obsolete `agents_template_allowlist` value. It's irreversible for deployments that configured an allowlist, which I think is fine, since `000562` already drops `agents_allowed` on the way down, and this release ships `000548` and `000555` with the same property. Two side effects of the model change worth writing down, both from #27514 rather than here. The value used to need `ActionRead` on `ResourceDeploymentConfig` to read and deployment config update to write. `AgentsAllowed` is now a plain field on the template response, readable by anyone who can read the template, and it's set with a template update, so org admins manage it themselves. That's the delegation we wanted, and it's tracked in the audit log. The rest of the stack adds `--agents-allowed` to the CLI and updates the platform controls docs. |