Spotted on main: https://github.com/coder/coder/actions/runs/14179449567/job/39721999486
```
=== FAIL: coderd TestOIDCDomainErrorMessage/MalformedEmailErrorOmitsDomains (0.01s)
==================
WARNING: DATA RACE
Read at 0x00c060b54e68 by goroutine 296485:
golang.org/x/oauth2.(*Config).Exchange()
/home/runner/go/pkg/mod/golang.org/x/oauth2@v0.28.0/oauth2.go:228 +0x1d8
github.com/coder/coder/v2/coderd.(*OIDCConfig).Exchange()
<autogenerated>:1 +0xb7
github.com/coder/coder/v2/coderd.New.func11.12.1.2.ExtractOAuth2.1.1()
/home/runner/work/coder/coder/coderd/httpmw/oauth2.go:168 +0x7b5
net/http.HandlerFunc.ServeHTTP()
/opt/hostedtoolcache/go/1.24.1/x64/src/net/http/server.go:2294 +0x47
[...]
Previous write at 0x00c060b54e68 by goroutine 55730:
github.com/coder/coder/v2/coderd/coderdtest/oidctest.(*FakeIDP).SetRedirect()
/home/runner/work/coder/coder/coderd/coderdtest/oidctest/idp.go:1280 +0x1e6
github.com/coder/coder/v2/coderd/coderdtest/oidctest.(*FakeIDP).LoginWithClient()
/home/runner/work/coder/coder/coderd/coderdtest/oidctest/idp.go:494 +0x170
github.com/coder/coder/v2/coderd/coderdtest/oidctest.(*FakeIDP).AttemptLogin()
/home/runner/work/coder/coder/coderd/coderdtest/oidctest/idp.go:479 +0x624
github.com/coder/coder/v2/coderd_test.TestOIDCDomainErrorMessage.func3()
/home/runner/work/coder/coder/coderd/userauth_test.go:2041 +0x1f2
```
As seen, this race was caused by sharing a `*oidctest.FakeIDP` between test cases. The fix is to simply do the setup twice.
```
$ go test -race -run "TestOIDCDomainErrorMessage" github.com/coder/coder/v2/coderd -count=100
ok github.com/coder/coder/v2/coderd 7.551s
````
This does ~95% of the backend work required to integrate the AI work.
Most left to integrate from the tasks branch is just frontend, which
will be a lot smaller I believe.
The real difference between this branch and that one is the abstraction
-- this now attaches statuses to apps, and returns the latest status
reported as part of a workspace.
This change enables us to have a similar UX to in the tasks branch, but
for agents other than Claude Code as well. Any app can report status
now.
Closes https://github.com/coder/coder/issues/16775
## Changes made
- Added `OneWayWebSocket` function that establishes WebSocket
connections that don't allow client-to-server communication
- Added tests for the new function
- Updated API endpoints to make new WS-based endpoints, and mark
previous SSE-based endpoints as deprecated
- Updated existing SSE handlers to use the same core logic as the new WS
handlers
## Notes
- Frontend changes handled via #16855
* Improves tests for webpush notifications
* Sets subscriber correctly in web push payload (without this,
notifications do not work in Safari)
* NOTE: for now, I'm using the Coder Access URL. Some push messaging
service don't like it when you use a non-HTTPS URL, so dropping a warn
log about this.
* Adds a service worker and context for push notifications
* Adds a button beside "Inbox" to enable / disable push notifications
Notes:
* ✅ Tested in in Firefox and Safari, and Chrome.
## Summary
- Removes exposure of allowed domain list in OIDC authentication error
messages
- Replaces detailed error messages with a generic message that doesn't
expose internal domains
- Adds "Please contact your administrator" to guide users seeking
assistance
- Addresses security concern where third-party contractors could see
internal domain information
## Test plan
- Test accessing Coder with an email that doesn't match allowed domains
- Verify error message no longer displays the list of authorized domains
- Verify message now includes guidance to contact administrator
Fixes issue related to domain information exposure during
authentication. Linked issue:
https://github.com/coder/coder/issues/17130🤖 Generated with [Claude Code](https://claude.ai/code)
This change adds support for devcontainer autostart in workspaces. The
preconditions for utilizing this feature are:
1. The `coder_devcontainer` resource must be defined in Terraform
2. By the time the startup scripts have completed,
- The `@devcontainers/cli` tool must be installed
- The given workspace folder must contain a devcontainer configuration
Example Terraform:
```tf
resource "coder_devcontainer" "coder" {
agent_id = coder_agent.main.id
workspace_folder = "/home/coder/coder"
config_path = ".devcontainer/devcontainer.json" # (optional)
}
```
Closes#16423
* Adds `codersdk.ExperimentWebPush` (`web-push`)
* Adds a `coderd/webpush` package that allows sending native push
notifications via `github.com/SherClockHolmes/webpush-go`
* Adds database tables to store push notification subscriptions.
* Adds an API endpoint that allows users to subscribe/unsubscribe, and
send a test notification (404 without experiment, excluded from API docs)
* Adds server CLI command to regenerate VAPID keys (note: regenerating
the VAPID keypair requires deleting all existing subscriptions)
---------
Co-authored-by: Kyle Carberry <kyle@carberry.com>
We do not want password reset notifications to end up in Coder Inbox as
this doesn't make much sense. This implements the logic to ensure they
are not delivered if the method is Coder Inbox.
In the future we might want to investigate a better solution but for now
this works.
- Update go.mod to use Go 1.24.1
- Update GitHub Actions setup-go action to use Go 1.24.1
- Fix linting issues with golangci-lint by:
- Updating to golangci-lint v1.57.1 (more compatible with Go 1.24.1)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
Closes
[coder/internal#477](https://github.com/coder/internal/issues/477)

I'm solving this issue in two parts:
1. Updated the postgres function so that it doesn't omit 0 values in the
error
2. Created a new query to fetch the number of resources associated with
an organization and using that information to provider a cleaner error
message to the frontend
> **_NOTE:_** SQL is not my strong suit, and the code was created with
the help of AI. So I'd take extra time looking over what I wrote there
In the presence of multiple devcontainers, it would be nice to
differentiate them by name. This change inherits the resource name from
terraform.
Refs #17076
fixes https://github.com/coder/internal/issues/525
If the context is canceled, the goroutine that is supposed to read from the `errCh` could exit prematurely, leading to a goroutine leak. Refactors this code so it cannot block.
Pre-requisite for https://github.com/coder/coder/pull/16891
Closes https://github.com/coder/internal/issues/515
This PR introduces a new concept of a "system" user.
Our data model requires that all workspaces have an owner (a `users`
relation), and prebuilds is a feature that will spin up workspaces to be
claimed later by actual users - and thus needs to own the workspaces in
the interim.
Naturally, introducing a change like this touches a few aspects around
the codebase and we've taken the approach _default hidden_ here; in
other words, queries for users will by default _exclude_ all system
users, but there is a flag to ensure they can be displayed. This keeps
the changeset relatively small.
This user has minimal permissions (it's equivalent to a `member` since
it has no roles). It will be associated with the default org in the
initial migration, and thereafter we'll need to somehow ensure its
membership aligns with templates (which are org-scoped) for which it'll
need to provision prebuilds; that's a solution we'll have in a
subsequent PR.
---------
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
Co-authored-by: Sas Swart <sas.swart.cdk@gmail.com>
Records the Device ID, Device OS and Coder Desktop version to telemetry.
These values are provided by the Coder Desktop client in the StartRequest method of the VPN protocol. We render them as an HTTP header to transmit to Coderd, where they are decoded and added to telemetry.
Related to #17082
Some notifications ( workspace created and workspace manually updated )
are using wrong variables to build the Action URL. Fixing it.
Adds support for sending telemetry on calls to the User-scoped tailnet RPC endpoint. This is currently used only by Coder Desktop.
Later PRs will fill in the version, OS information, and device ID via HTTP headers.
This PR aims to allow clients to use different format for the title and
content of inbox notifications - on the watch endpoint.
This solution will help to have it working and formatted differently on
VSCode, WebUI ...
[Related to this issue](https://github.com/coder/internal/issues/523)
This PR aimes to [fix this
issue](https://github.com/coder/internal/issues/448) -
The main idea is to remove greetings from templates stored in the DB -
and instead push it into the template for require methods - for now
SMTP.
Updating golden files is an unnecessary extra step in addition to gen
that is easily overlooked, leading to the developer noticing the issue
in CI leading to lost developer time waiting for tests to complete.
Add the `--github-user-id` option to `coder users list`, which makes the
command only return users with a matching GitHub user id. This will
enable https://github.com/coder/start-workspace-action to find a Coder
user that corresponds to a GitHub user requesting to start a workspace.
This change allows specifying devcontainers in terraform and plumbs it
through to the agent via agent manifest.
This will be used for autostarting devcontainers in a workspace.
Depends on coder/terraform-provider-coder#368
Updates #16423
When DeviceFlow with GitHub OAuth2 is configured, the
`api.GithubOAuth2Config.AuthCode` is
[overridden](b08c8c9e1e/coderd/userauth.go (L779))
and returns a value that doesn't pass the `IsGithubDotComURL` check.
This PR ensures the original `AuthCodeURL` method is used instead.
## Summary
- Add UserTailnetConnection struct to track desktop client connections
- Add new field to Snapshot struct for telemetry
- Data collection to be implemented in a future PR
relates to coder/nexus#197
[Resolve this issue](https://github.com/coder/internal/issues/506)
Add a mark-all-as-read endpoint which is marking as read all
notifications that are not read for the authenticated user.
Also adds the DB logic.
Currently the `targets` column in `inbox_notifications` doesn't get
filled. This PR fixes that. Rather than give targets special treatment,
we should put it in the payload like everything else. This correctly
propagates notification targets to the inbox table without much code
change.
* Improves separation of concerns between `runDockerInspect` and
`convertDockerInspect`: `runDockerInspect` now just runs the command and
returns the output, while `convertDockerInspect` now does all of the
conversion and parsing logic.
* Improves testing of `convertDockerInspect` using real test fixtures.
* Fixes issue where the container port is returned instead of the host
port.
* Updates UI to link to correct host port. Container port is still
displayed in the button text, but the HostIP:HostPort is shown in a
popover.
* Adds stories for workspace agent UI
This change adds support for workspace app auditing.
To avoid audit log spam, we introduce the concept of app audit sessions.
An audit session is unique per workspace app, user, ip, user agent and
http status code. The sessions are stored in a separate table from audit
logs to allow use-case specific optimizations. Sessions are ephemeral
and the table does not function as a log.
The logic for auditing is placed in the DBTokenProvider for workspace
apps so that wsproxies are included.
This is the final change affecting the API fo #15139.
Updates #15139
This PR is part of the inbox notifications topic, and rely on previous
PRs merged - it adds :
- Endpoints to :
- WS : watch new inbox notifications
- REST : list inbox notifications
- REST : update the read status of a notification
Also, this PR acts as a follow-up PR from previous work and :
- fix DB query issues
- fix DBMem logic to match DB
This fixes a slight regex bug on Bash 5, where `[:/]` would only match
`:` but not both `:/`.
```bash
$ git remote -v | grep "github.com[:/]coder/coder.*(fetch)" | cut -f1
$ git remote -v | grep "github.com[:/]*coder/coder.*(fetch)" | cut -f1
origin
```
The former will actually cause the whole script to bork because of
`pipefail`, since `grep` exits 1.
Signed-off-by: Danny Kopping <dannykopping@gmail.com>