Closes https://github.com/coder/internal/issues/780
## Summary of changes:
- added `user_secrets` table
- `user_secrets` table contains `env_name` and `file_path` fields which
are not used at the moment, but will be used in later PRs
- `user_secrets` table doesn't contain `value_key_id`, I will add it in
a separate migration in a dbcrypt PR
- on one hand I don't want to add fields which are not used (because
it's a risk smth may change in implementation later), on the other hand
I don't want to add too many migrations for user secrets table
- added unique sql indexes
- added sql queries for CRUD operations on user-secrets
- introduced new `ResourceUserSecret` resource
- basic unit-tests for CRUD ops and authorization behavior
- Role updates:
- owner:
- remove `ResourceUserSecret` from site-wide perms
- add `ResourceUserSecret` to user-wide perms
- orgAdmin
- remove `ResourceUserSecret` from org-wide perms; seems it's not
strictly required, because `ResourceUserSecret` is not tied to
organization in dbauthz wrappers?
- memberRole
- no need to change memberRole because it implicitly has access to
user-secrets thanks to the `allPermsExcept`
- is it enough changes to roles?
Main questions:
- [ ] We will have 2 migrations for user-secrets:
- initial migration (in current PR)
- adding `value_key_id` in dbcrypt PR
- is this approach reasonable?
- [ ] Are changes to roles's permissions are correct?
- [ ] Are changes in roles_test.go are correct?
---------
Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>
Can do `author:username` to filter templates created by a certain
author. Adding to help clean out some templates that I created on our
dev instance. This makes sorting a bit easier.
Closes#18599.
The linked issue was created due to me assuming the dialer didn't fail fast at all. In reality, it does fail fast, but only for a select few status codes. Auth[n|z] errors aren't any of those status codes, despite being 'permanent' in the same way a `400` is.
This PR makes 401* and 403 'permanent' errors, meaning the dialer will give up immediately after receiving them from coderd.
*One reason to receive a 401 is when the supplied resume_token is invalid. These are not permanent errors, and when we encounter those the dialer will retain the existing behaviour of unsetting the resume token and retrying.
This PR sets a constraint of 1MB on the provisioner job logs written to
the database. This is consistent with the constraint we place on
workspace agent logs:
https://github.com/coder/coder/blob/4ac6be6d835dc36c242e35a26b584b784040bf28/coderd/database/dump.sql#L2030
It also adds a message printed to the front end about the provisioner
log overflow, and updates the message printed to the front end when
workspace startup logs exceed the max, as it was causing some customers
to think their startup script had failed to run.
Solves https://github.com/coder/coder/issues/15096
This is a slight rework/refactor of the earlier PRs from @dannykopping
and @Emyrk:
- https://github.com/coder/coder/pull/15669
- https://github.com/coder/coder/pull/15684
- https://github.com/coder/coder/pull/17596
Rather than having a per-app CORS behaviour setting and additionally a
template level setting for ports, this PR adds a single template level
CORS behaviour setting that is then used by all apps/ports for
workspaces created from that template.
The main changes are in `proxy.go` and `request.go` to:
a) get the CORS behaviour setting from the template
b) have `HandleSubdomain` bypass the CORS middleware handler if the
selected behaviour is `passthru`
c) in `proxyWorkspaceApp`, do not modify the response if the selected
behaviour is `passthru`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added support for configuring CORS behavior ("simple" or "passthru")
at the template level for all shared ports.
* Introduced a new "CORS Behavior" setting in the template creation and
settings forms.
* API endpoints and responses now include the optional `cors_behavior`
property for templates.
* Workspace apps and proxy now honor the specified CORS behavior,
enabling conditional CORS middleware application.
* Enhanced workspace app tests with comprehensive scenarios covering
CORS behaviors and authentication states.
* **Bug Fixes**
* None.
* **Documentation**
* Updated API and admin documentation to describe the new
`cors_behavior` property and its usage.
* Added examples and schema references for CORS behavior in relevant API
docs.
* **Tests**
* Extended automated tests to cover different CORS behavior scenarios
for templates and workspace apps.
* **Chores**
* Updated audit logging to track changes to the `cors_behavior` field on
templates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Callum Styan <callumstyan@gmail.com>
## Description
This PR adds support for `description` and `icon` fields to
`template_version_presets`. These fields will allow displaying richer
information for presets in the UI, improving the user experience when
creating a workspace.
Both fields are optional, non-nullable, and default to empty strings.
## Changes
* Database migration with the addition of `description VARCHAR(128)` and
`icon VARCHAR(256)` columns to the `template_version_presets` table.
* Updated the `CreateWorkspacePageView` in the UI
Note: UI changes will be addressed in a separate PR
# Add timeout support to workspace bash tool
This PR adds a timeout feature to the workspace bash tool, allowing
users to specify a maximum execution time for commands. Key changes
include:
- Added a `timeout_ms` parameter to control command execution time
(defaults to 60 seconds, with a maximum of 5 minutes)
- Implemented a new `executeCommandWithTimeout` function that properly
handles command timeouts
- Added proper output capturing during timeout scenarios, returning all
output collected before the timeout
- Updated documentation to explain the timeout feature and provide usage
examples
- Added comprehensive tests for the timeout functionality, including
integration tests
When a command times out, the tool now returns all captured output up to
that point along with a cancellation message, making it clear to users
what happened.
Signed-off-by: Thomas Kosiewski <tk@coder.com>
This pull request addresses a bug related to a nil pointer dereference
in the task reporting functionality.
### Bug Fixes and Error Handling:
* Updated `RegisterTools` in `mcp.go` to skip registering the
`ReportTask` tool in the remote MCP context when a task reporter is not
configured, preventing potential nil pointer dereference panics.
* Added a check in `toolsdk.go` to ensure task reporting dependencies
are available before invoking the reporter, returning an appropriate
error if not.
### Test Coverage:
* Added `TestReportTaskNilPointerDeref` in `toolsdk_test.go` to verify
that the system does not panic when task reporting dependencies are
missing and instead returns a clear error message.
* Added `TestReportTaskWithReporter` in `toolsdk_test.go` to validate
correct behavior when a task reporter is configured, ensuring the
handler processes the request as expected.
Signed-off-by: Thomas Kosiewski <tk@coder.com>
## Description
This PR introduces a new `list presets` command to display the presets
associated with a given template.
By default, it displays the presets for the template's active version,
unless a `--template-version` flag is provided.
## Changes
* Added a new `list presets` command under `coder templates presets` to
display presets associated with a template.
* By default, the command lists presets from the template’s active
version.
* Users can override the default behavior by providing the
`--template-version` flag to target a specific version.
```
> coder templates versions presets list --help
USAGE:
coder templates presets list [flags] <template>
List all presets of the specified template. Defaults to the active template version.
OPTIONS:
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
-c, --column [name|parameters|default|desired prebuild instances] (default: name,parameters,default,desired prebuild instances)
Columns to display in table output.
-o, --output table|json (default: table)
Output format.
--template-version string
Specify a template version to list presets for. Defaults to the active version.
```
Related PR: https://github.com/coder/coder/pull/18912 - please consider
both PRs together as they’re part of the same workflow
Relates to issue: https://github.com/coder/coder/issues/16594
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added CLI commands to manage and list presets for specific template
versions, supporting tabular and JSON output.
* Introduced a new CLI subcommand group for template version presets,
including detailed help and documentation.
* Added support for displaying and managing the desired number of
prebuild instances for presets in CLI, API, and UI.
* **Documentation**
* Updated and expanded CLI and API documentation to describe new
commands, options, and the desired prebuild instances field in presets.
* Added new help output and reference files for template version presets
commands.
* **Bug Fixes**
* Ensured correct handling and display of the desired prebuild instances
property for presets across CLI, API, and UI.
* **Tests**
* Introduced end-to-end tests for listing template version presets,
covering scenarios with and without presets.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Updates `develop.sh`, `coder-dev.sh` and `build_go.sh` to conditionally override `codersdk.SessionTokenCookie` for usage in nested development scenario.
- Refactors the bash tool to use `io.Discard` instead of nil to avoid panics.
- Enhances panic recovery in `codersdk/toolsdk/toolsdk.go` by adding stack trace information in development builds. When a panic occurs in a tool handler:
- In development builds: The error includes the full stack trace for easier debugging
- In production builds: A simpler error message is shown without the stack trace
This PR introduces new build reason values to identify what type of
connection triggered a workspace build, helping to troubleshoot
workspace-related issues.
## Database Migration
Added migration 000349_extend_workspace_build_reason.up.sql that extends
the build_reason enum with new values:
```
dashboard, cli, ssh_connection, vscode_connection, jetbrains_connection
```
## Implementation
The build reason is specified through the API when creating new
workspace builds:
- Dashboard: Automatically sets reason to `dashboard` when users start
workspaces via the web interface
- CLI `start` command: Sets reason to `cli` when workspaces are started
via the command line
- CLI `ssh` command: Sets reason to ssh_connection when workspaces are
started due to SSH connections
- VS Code connections: Will be set to `vscode_connection` by the VS Code
extension through CLI hidden flag
(https://github.com/coder/vscode-coder/pull/550)
- JetBrains connections: Will be set to `jetbrains_connection` by the
Jetbrains Toolbox
(https://github.com/coder/coder-jetbrains-toolbox/pull/150) and
Jetbrains Gateway extension
(https://github.com/coder/jetbrains-coder/pull/561)
## UI Changes:
* Tooltip with reason in Build history
<img width="309" height="457" alt="image"
src="https://github.com/user-attachments/assets/bde8440b-bf3b-49a1-a244-ed7e8eb9763c"
/>
* Reason in Audit Logs Row tooltip
<img width="906" height="237" alt="image"
src="https://github.com/user-attachments/assets/ebbb62c7-cf07-4398-afbf-323c83fb6426"
/>
<img width="909" height="188" alt="image"
src="https://github.com/user-attachments/assets/1ddbab07-44bf-4dee-8867-b4e2cd56ae96"
/>
# Add SSH Command Execution Tool for Coder Workspaces
This PR adds a new AI tool `coder_workspace_ssh_exec` that allows executing commands in Coder workspaces via SSH. The tool provides functionality similar to the `coder ssh <workspace> <command>` CLI command.
Key features:
- Executes commands in workspaces via SSH and returns the output and exit code
- Automatically starts workspaces if they're stopped
- Waits for the agent to be ready before executing commands
- Trims leading and trailing whitespace from command output
- Supports various workspace identifier formats:
- `workspace` (uses current user)
- `owner/workspace`
- `owner--workspace`
- `workspace.agent` (specific agent)
- `owner/workspace.agent`
The implementation includes:
- A new tool definition with schema and handler
- Helper functions for workspace and agent discovery
- Workspace name normalization to handle different input formats
- Comprehensive test coverage including integration tests
This tool enables AI assistants to execute commands in user workspaces, making it possible to automate tasks and provide more interactive assistance.
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Introduced the ability to execute bash commands inside a Coder workspace via SSH, supporting multiple workspace identification formats.
* **Tests**
* Added comprehensive unit and integration tests for executing bash commands in workspaces, including input validation, output handling, and error scenarios.
* **Chores**
* Registered the new bash execution tool in the global tools list.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Note that enforcement and checking usage will come in a future PR.
This feature is implemented differently than existing features in a few
ways.
It's highly recommended that reviewers read:
- This document which outlines the methods we could've used for license
enforcement:
https://www.notion.so/coderhq/AI-Agent-License-Enforcement-21ed579be59280c088b9c1dc5e364ee8
- Phase 0 of the actual RFC document:
https://www.notion.so/coderhq/Usage-based-Billing-AI-b-210d579be592800eb257de7eecd2d26d
### Multiple features in the license, a single feature in codersdk
Firstly, the feature is represented as a single feature in the codersdk
world, but is represented with multiple features in the license.
E.g. in the license you may have:
{
"features": {
"managed_agent_limit_soft": 100,
"managed_agent_limit_hard": 200
}
}
But the entitlements endpoint will return a single feature:
{
"features": {
"managed_agent_limit": {
"limit": 200,
"soft_limit": 100
}
}
}
This is required because of our rigid parsing that uses a
`map[string]int64` for features in the license. To avoid requiring all
customers to upgrade to use new licenses, the decision was made to just
use two features and merge them into one. Older Coder deployments will
parse this feature (from new licenses) as two separate features, but
it's not a problem because they don't get used anywhere obviously.
The reason we want to differentiate between a "soft" and "hard" limit is
so we can show admins how much of the usage is "included" vs. how much
they can use before they get hard cut-off.
### Usage period features will be compared and trump based on license
issuance time
The second major difference to other features is that "usage period"
features such as `managed_agent_limit` will now be primarily compared by
the `iat` (issued at) claim of the license they come from. This differs
from previous features. The reason this was done was so we could reduce
limits with newer licenses, which the current comparison code does not
allow for.
This effectively means if you have two active licenses:
- `iat`: 2025-07-14, `managed_agent_limit_soft`: 100,
`managed_agent_limit_hard`: 200
- `iat`: 2025-07-15, `managed_agent_limit_soft`: 50,
`managed_agent_limit_hard`: 100
Then the resulting `managed_agent_limit` entitlement will come from the
second license, even though the values are smaller than another valid
license. The existing comparison code would prefer the first license
even though it was issued earlier.
### Usage period features will count usage between the start and end
dates of the license
Existing limit features, like the user limit, just measure the current
usage value of the feature. The active user count is a gauge that goes
up and down, whereas agent usage can only be incremented, so it doesn't
make sense to use a continually incrementing counter forever and ever
for managed agents.
For managed agent limit, we count the usage between `nbf` (not before)
and `exp` (expires at) of the license that the entitlement comes from.
In the example above, we'd use the issued at date and expiry of the
second license as this date range.
This essentially means, when you get a new license, the usage resets to
zero.
The actual usage counting code will be implemented in a follow-up PR.
### Managed agent limit has a default entitlement value
Temporarily (until further notice), we will be providing licenses with
`feature_set` set to `premium` a default limit.
- Soft limit: `800 * user_limit`
- Hard limit: `1000 * user_limit`
"Enterprise" licenses do not get any default limit and are not entitled
to use the feature.
Unlicensed customers (e.g. OSS) will be permitted to use the feature as
much as they want without limits. This will be implemented when the
counting code is implemented in a follow-up PR.
Closes https://github.com/coder/internal/issues/760
The agentsdk currently does a remap of the DERP map to change the
EmbeddedRelay node's URL to match the agent's access URL.
This PR makes changes to the `workspacesdk` (used by clients like the
CLI) and `vpn` (used by Coder Desktop) to match this behavior.
This enables us the ability to try Coder clients in dogfood over a VPN
without changing the global access URL.
## Description
This PR updates the UI to avoid rendering workspace schedule settings
(autostop, autostart, etc.) for prebuilt workspaces. Instead, it
displays an informational message with a link to the relevant
documentation.
## Changes
* Introduce `IsPrebuild` parameter to `convertWorkspace` to indicate
whether the workspace is a prebuild.
* Prevent the Workspace Schedule settings form from rendering in the UI
for prebuilt workspaces.
* Display an info alert with a link to documentation when viewing a
prebuilt workspace.
<img width="2980" height="864" alt="Screenshot 2025-07-10 at 13 16 13"
src="https://github.com/user-attachments/assets/5f831c21-50bb-4e05-beea-dbeb930ddff8"
/>
Relates with: https://github.com/coder/coder/pull/18762
---------
Co-authored-by: BrunoQuaresma <bruno_nonato_quaresma@hotmail.com>
This is the second PR for moving connection events out of the audit log.
This PR:
- Adds the `/api/v2/connectionlog` endpoint
- Adds filtering for `GetAuthorizedConnectionLogsOffset` and thus the endpoint.
There's quite a few, but I was aiming for feature parity with the audit log.
1. `organization:<id|name>`
2. `workspace_owner:<username>`
3. `workspace_owner_email:<email>`
4. `type:<ssh|vscode|jetbrains|reconnecting_pty|workspace_app|port_forwarding>`
5. `username:<username>`
- Only includes web-based connection events (workspace apps, web port forwarding) as only those include user metadata.
6. `user_email:<email>`
7. `connected_after:<time>`
8. `connected_before:<time>`
9. `workspace_id:<id>`
10. `connection_id:<id>`
- If you have one snapshot of the connection log, and some sessions are ongoing in that snapshot, you could use this filter to check if they've been closed since.
11. `status:<connected|disconnected>`
- If `connected` only sessions with a null `close_time` are returned, if `disconnected`, only those with a non-null `close_time`. If filter is omitted, both are returned.
Future PRs:
- Populate `count` on `ConnectionLogResponse` using a seperate query (to preemptively mitigate the issue described in #17689)
- Implement a table in the Web UI for viewing connection logs.
- Write a query to delete old events from the audit log, call it from dbpurge.
- Write documentation for the endpoint / feature (including these filters)
### Breaking Change (changelog note):
> User connections to workspaces, and the opening of workspace apps or ports will no longer create entries in the audit log. Those events will now be included in the 'Connection Log'.
Please see the 'Connection Log' page in the dashboard, and the Connection Log [documentation](https://coder.com/docs/admin/monitoring/connection-logs) for details. Those with permission to view the Audit Log will also be able to view the Connection Log. The new Connection Log has the same licensing restrictions as the Audit Log, and requires a Premium Coder deployment.
### Context
This is the first PR of a few for moving connection events out of the audit log, and into a new database table and web UI page called the 'Connection Log'.
This PR:
- Creates the new table
- Adds and tests queries for inserting and reading, including reading with an RBAC filter.
- Implements the corresponding RBAC changes, such that anyone who can view the audit log can read from the table
- Implements, under the enterprise package, a `ConnectionLogger` abstraction to replace the `Auditor` abstraction for these logs. (No-op'd in AGPL, like the `Auditor`)
- Routes SSH connection and Workspace App events into the new `ConnectionLogger`
- Updates all existing tests to check the values of the `ConnectionLogger` instead of the `Auditor`.
Future PRs:
- Add filtering to the query
- Add an enterprise endpoint to query the new table
- Write a query to delete old events from the audit log, call it from dbpurge.
- Implement a table in the Web UI for viewing connection logs.
> [!NOTE]
> The PRs in this stack obviously won't be (completely) atomic. Whilst they'll each pass CI, the stack is designed to be merged all at once. I'm splitting them up for the sake of those reviewing, and so changes can be reviewed as early as possible. Despite this, it's really hard to make this PR any smaller than it already is. I'll be keeping it in draft until it's actually ready to merge.
## Description
This PR updates the lifecycle executor to explicitly exclude prebuilt
workspaces from being considered for lifecycle operations such as
`autostart`, `autostop`, `dormancy`, `default TTL` and `failure TTL`.
Prebuilt workspaces (i.e., those owned by the prebuild system user) are
handled separately by the prebuild reconciliation loop. Including them
in the lifecycle executor could lead to unintended behavior such as
incorrect scheduling or state transitions.
## Changes
* Updated the lifecycle executor query
`GetWorkspacesEligibleForTransition` to exclude workspaces with
`owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'` (prebuilds).
* Added tests to verify prebuilt workspaces are not considered in:
* Autostop
* Autostart
* Default TTL
* Dormancy
* Failure TTL
Fixes: https://github.com/coder/coder/issues/18740
Related to: https://github.com/coder/coder/issues/18658
Closes#17791
This PR adds ability to cancel workspace builds that are in "pending"
status.
Breaking changes:
- CancelWorkspaceBuild method in codersdk now accepts an optional
request parameter
API:
- Added `expect_status` query parameter to the cancel workspace build
endpoint
- This parameter ensures the job hasn't changed state before canceling
- API returns `412 Precondition Failed` if the job is not in the
expected status
- Valid values: `running` or `pending`
- Wrapped the entire cancel method in a database transaction
UI:
- Added confirmation dialog to the `Cancel` button, since it's a
destructive operation


- Enabled cancel action for pending workspaces (`expect_status=pending`
is sent if workspace is in pending status)

---------
Co-authored-by: Dean Sheather <dean@deansheather.com>
- Add `format:"uri"` to `Group.AvatarURL` (matches `User.AvatarURL`
field)
- `<user_id>` and `<group_id>` were backwards in the `example:` tags
- The `@Success` annotation for `/acl [get]` had an incorrect type
# Add MCP HTTP Server Experiment
This PR adds a new experiment flag `mcp-server-http` to enable the MCP HTTP server functionality. The changes include:
1. Added a new experiment constant `ExperimentMCPServerHTTP` with the value "mcp-server-http"
2. Added display name and documentation for the new experiment
3. Improved the experiment middleware to:
- Support requiring multiple experiments
- Provide better error messages with experiment display names
- Add a development mode bypass option
4. Applied the new experiment requirement to the MCP HTTP endpoint
5. Replaced the custom OAuth2 middleware with the standard experiment middleware
The PR also improves the `Enabled()` method on the `Experiments` type by using `slices.Contains()` for better readability.
# Add OAuth2 Provider Functionality as an Experiment
This PR adds a new experiment flag `oauth2` that enables OAuth2 provider functionality in Coder. When enabled, this experiment allows Coder to act as an OAuth2 provider.
The changes include:
- Added the new `ExperimentOAuth2` constant with appropriate documentation
- Updated the OAuth2 provider middleware to check for the experiment flag
- Modified the error message to indicate that the OAuth2 provider requires enabling the experiment
- Added the new experiment to the known experiments list in the SDK
Previously, OAuth2 provider functionality was only available in development mode. With this change, it can be enabled in production environments by activating the experiment.
# Add MCP HTTP server with streamable transport support
- Add MCP HTTP server with streamable transport support
- Integrate with existing toolsdk for Coder workspace operations
- Add comprehensive E2E tests with OAuth2 bearer token support
- Register MCP endpoint at /api/experimental/mcp/http with authentication
- Support RFC 6750 Bearer token authentication for MCP clients
Change-Id: Ib9024569ae452729908797c42155006aa04330af
Signed-off-by: Thomas Kosiewski <tk@coder.com>
# Implement OAuth2 Dynamic Client Registration (RFC 7591/7592)
This PR implements OAuth2 Dynamic Client Registration according to RFC 7591 and Client Configuration Management according to RFC 7592. These standards allow OAuth2 clients to register themselves programmatically with Coder as an authorization server.
Key changes include:
1. Added database schema extensions to support RFC 7591/7592 fields in the `oauth2_provider_apps` table
2. Implemented `/oauth2/register` endpoint for dynamic client registration (RFC 7591)
3. Added client configuration management endpoints (RFC 7592):
- GET/PUT/DELETE `/oauth2/clients/{client_id}`
- Registration access token validation middleware
4. Added comprehensive validation for OAuth2 client metadata:
- URI validation with support for custom schemes for native apps
- Grant type and response type validation
- Token endpoint authentication method validation
5. Enhanced developer documentation with:
- RFC compliance guidelines
- Testing best practices to avoid race conditions
- Systematic debugging approaches for OAuth2 implementations
The implementation follows security best practices from the RFCs, including proper token handling, secure defaults, and appropriate error responses. This enables third-party applications to integrate with Coder's OAuth2 provider capabilities programmatically.
# Add OAuth2 Protected Resource Metadata Endpoint
This PR implements the OAuth2 Protected Resource Metadata endpoint according to RFC 9728. The endpoint is available at `/.well-known/oauth-protected-resource` and provides information about Coder as an OAuth2 protected resource.
Key changes:
- Added a new endpoint at `/.well-known/oauth-protected-resource` that returns metadata about Coder as an OAuth2 protected resource
- Created a new `OAuth2ProtectedResourceMetadata` struct in the SDK
- Added tests to verify the endpoint functionality
- Updated API documentation to include the new endpoint
The implementation currently returns basic metadata including the resource identifier and authorization server URL. The `scopes_supported` field is empty until a scope system based on RBAC permissions is implemented. The `bearer_methods_supported` field is omitted as Coder uses custom authentication methods rather than standard RFC 6750 bearer tokens.
A TODO has been added to implement RFC 6750 bearer token support in the future.
This PR provides two commands:
* `coder prebuilds pause`
* `coder prebuilds resume`
These allow the suspension of all prebuilds activity, intended for use
if prebuilds are misbehaving.
## Summary
This PR implements critical MCP OAuth2 compliance features for Coder's authorization server, adding PKCE support, resource parameter handling, and OAuth2 server metadata discovery. This brings Coder's OAuth2 implementation significantly closer to production readiness for MCP (Model Context Protocol)
integrations.
## What's Added
### OAuth2 Authorization Server Metadata (RFC 8414)
- Add `/.well-known/oauth-authorization-server` endpoint for automatic client discovery
- Returns standardized metadata including supported grant types, response types, and PKCE methods
- Essential for MCP client compatibility and OAuth2 standards compliance
### PKCE Support (RFC 7636)
- Implement Proof Key for Code Exchange with S256 challenge method
- Add `code_challenge` and `code_challenge_method` parameters to authorization flow
- Add `code_verifier` validation in token exchange
- Provides enhanced security for public clients (mobile apps, CLIs)
### Resource Parameter Support (RFC 8707)
- Add `resource` parameter to authorization and token endpoints
- Store resource URI and bind tokens to specific audiences
- Critical for MCP's resource-bound token model
### Enhanced OAuth2 Error Handling
- Add OAuth2-compliant error responses with proper error codes
- Use standard error format: `{"error": "code", "error_description": "details"}`
- Improve error consistency across OAuth2 endpoints
### Authorization UI Improvements
- Fix authorization flow to use POST-based consent instead of GET redirects
- Remove dependency on referer headers for security decisions
- Improve CSRF protection with proper state parameter validation
## Why This Matters
**For MCP Integration:** MCP requires OAuth2 authorization servers to support PKCE, resource parameters, and metadata discovery. Without these features, MCP clients cannot securely authenticate with Coder.
**For Security:** PKCE prevents authorization code interception attacks, especially critical for public clients. Resource binding ensures tokens are only valid for intended services.
**For Standards Compliance:** These are widely adopted OAuth2 extensions that improve interoperability with modern OAuth2 clients.
## Database Changes
- **Migration 000343:** Adds `code_challenge`, `code_challenge_method`, `resource_uri` to `oauth2_provider_app_codes`
- **Migration 000343:** Adds `audience` field to `oauth2_provider_app_tokens` for resource binding
- **Audit Updates:** New OAuth2 fields properly tracked in audit system
- **Backward Compatibility:** All changes maintain compatibility with existing OAuth2 flows
## Test Coverage
- Comprehensive PKCE test suite in `coderd/identityprovider/pkce_test.go`
- OAuth2 metadata endpoint tests in `coderd/oauth2_metadata_test.go`
- Integration tests covering PKCE + resource parameter combinations
- Negative tests for invalid PKCE verifiers and malformed requests
## Testing Instructions
```bash
# Run the comprehensive OAuth2 test suite
./scripts/oauth2/test-mcp-oauth2.sh
Manual Testing with Interactive Server
# Start Coder in development mode
./scripts/develop.sh
# In another terminal, set up test app and run interactive flow
eval $(./scripts/oauth2/setup-test-app.sh)
./scripts/oauth2/test-manual-flow.sh
# Opens browser with OAuth2 flow, handles callback automatically
# Clean up when done
./scripts/oauth2/cleanup-test-app.sh
Individual Component Testing
# Test metadata endpoint
curl -s http://localhost:3000/.well-known/oauth-authorization-server | jq .
# Test PKCE generation
./scripts/oauth2/generate-pkce.sh
# Run specific test suites
go test -v ./coderd/identityprovider -run TestVerifyPKCE
go test -v ./coderd -run TestOAuth2AuthorizationServerMetadata
```
### Breaking Changes
None. All changes maintain backward compatibility with existing OAuth2 flows.
---
Change-Id: Ifbd0d9a543d545f9f56ecaa77ff2238542ff954a
Signed-off-by: Thomas Kosiewski <tk@coder.com>
This PR replaces the use of the **container** ID with the
**devcontainer** ID. This is a breaking change. This allows rebuilding a
devcontainer when there is no valid container ID.
Add an endpoint to fetch AI task prompts for multiple workspace builds
at the same time. A prompt is the value of the "AI Prompt" workspace
build parameter. On main, the only way our API allows fetching workspace
build parameters is by using the `/workspacebuilds/$build_id/parameters`
endpoint, requiring a separate API call for every build.
The Tasks dashboard fetches Task workspaces in order to show them in a
list, and then needs to fetch the value of the `AI Prompt` parameter for
every task workspace (using its latest build id), requiring an
additional API call for each list item. This endpoint will allow the
dashboard to make just 2 calls to render the list: one to fetch task
workspaces, the other to fetch prompts.
<img width="1512" alt="Screenshot 2025-06-20 at 11 33 11"
src="https://github.com/user-attachments/assets/92899999-e922-44c5-8325-b4b23a0d2bff"
/>
Related to https://github.com/coder/internal/issues/660.
Fixes https://github.com/coder/coder/issues/18024
* drive-by: renames `handleExperimentsSafe` to
`handleExperimentsAvailable` to better match semantics
* defines list of `codersdk.ExperimentsKnown` and updates
`ReadExperiments` to log on invalid experiments
* typescript-ignores `codersdk.Experiments` so apitypings generates a
valid enum list of possible values of experiment
* updates OverviewPageView to distinguish between known 'hidden'
experiments and unknown 'invalid' experiments
When in experimental this was used as an escape hatch. Removed to be
consistent with the template author's intentions
Backwards compatible, removing an experimental api field that is no longer used.