## What
Adds `client_session_id` correlation to coderd's HTTP request handling,
per the
[Connection log collection and correlation
RFC](https://www.notion.so/coderhq/Connection-log-collection-and-correlation-36ed579be5928025a56cd11fe58661fb).
Clients attach a per-session correlation ID to every API request via W3C
baggage using the `client_session_id` key. This change makes coderd's
tracing
middleware read that baggage member and:
- add `client_session_id` to the **per-request log context** so all logs
for a
request (and the handlers it calls) can be correlated by a single ID,
and
- set `client_session_id` as a **span attribute** when tracing is
enabled.
Per RFC requirement 6.1, the value is added to the log context **even
when
tracing is disabled** (the middleware previously returned early when no
tracer
provider was configured, so baggage was never read). The
`client_session_id` is
validated as a 32-character hexadecimal string (a 16-byte value, per RFC
requirement 1) to guard against logging arbitrary client-controlled
baggage
values.
## Scope
This is `DEVEX-659` and is intentionally limited to the coderd tracing
middleware. It is the first piece of a stack: the web terminal client
change
(`DEVEX-663`) that generates and sends the `client_session_id` will be
stacked on top
of this PR. No client currently sends `client_session_id` baggage, so
this change is
a no-op until the client work lands.
## Testing
- `coderd/tracing`: new unit tests cover `validSessionID`, baggage
extraction
(`sessionIDFromHeaders`), and the middleware end to end, asserting
`client_session_id` lands on the log context with tracing enabled
**and** disabled,
is exposed as a span attribute when tracing is enabled, and that
absent/malformed baggage is ignored.
- Existing `Test_Middleware` route-matching behavior is unchanged.
<details>
<summary>Design notes / decision log</summary>
- **Where the value is read:** the existing `tracing.Middleware` runs
high in
the coderd middleware stack (`coderd/coderd.go`), before request-id and
request-logger middleware, and already matches the `/api`, `/api/**`,
app
proxy, and external-auth routes. Reading baggage here means the
`client_session_id`
is on the context before the request logger and handlers run, so it
flows
into all downstream `slog` calls that use the request context. This
mirrors
the existing `request_id` pattern in `httpmw.AttachRequestID`
(`slog.With(ctx, ...)` + span attribute).
- **Works when tracing is off:** the middleware now gates only on the
route
matcher, extracts baggage and adds `client_session_id` to the log
context for all
matched routes, and only then branches on whether a tracer is
configured.
When a tracer is present, `client_session_id` is additionally set as a
span
attribute.
- **Explicit baggage propagator:** extraction uses
`propagation.Baggage{}`
directly rather than the global text map propagator, so it does not
depend
on the global propagator being configured (also makes it deterministic
in
tests).
- **Validation:** only a 32-char hex string is accepted (lower or upper
case).
Malformed values are dropped rather than logged, preventing
log/attribute
pollution from arbitrary client-supplied baggage.
- **Out of scope for this PR (tracked elsewhere):** client
generation/sending
of `client_session_id` (`DEVEX-663`, web terminal), the equivalent
agent-side
middleware (RFC 6.2), `connection_logs.client_session_id` (RFC 12), and
additional
connection state-change logging (RFC 7-13).
</details>
---
_Opened by Coder Agents on behalf of @aqandrew._
Extends the Agent-chat MCP tools so an unattended UAT evidence loop can
fetch artifacts, monitor long runs, and find prior runs without burning
model context.
## Backend
- New `chat_files_token` crypto key feature (migration 000571) with
rotator support and a dedicated signing keycache on coderd.
- `POST /api/experimental/chats/files/{file}/download-url`
(authenticated) mints a short-lived (5 min) signed URL and returns it
with `sha256`, `size_bytes`, `name`, `mime_type`, and `expires_at`.
- `GET /api/experimental/chats/files/{file}/download?token=` (no session
token) redeems the signed URL: verifies the JWS, requires the token's
`file_id` to match the path, and re-checks the minting user's RBAC
access live at redemption. Clients can `curl -o` artifacts with zero
credentials in the URL consumer.
- `ChatFileMetadata` gains `size_bytes` (via `octet_length`, no bytes
fetched).
## MCP tools (`codersdk/toolsdk`)
- `coder_download_chat_file`: by `file_id` or `chat_id`+`file_name`;
returns the signed URL plus checksum and size instead of base64.
- `coder_await_chat`: blocks (bounded `wait_secs`, 1-120) until a chat
leaves `running`/`interrupting`, using the existing watch stream with
subscribe-before-read.
- `coder_list_chats`: label, query, and limit filtering; chat
projections now include labels.
- `coder_get_chat_messages`: `after_id` forward cursor with
`next_after_id` (exact incremental reads), plus per-message `files`
metadata so artifact-bearing messages are identifiable.
- `coder_get_chat`: file listings now include `size_bytes` and
`created_at`.
- `coder_list_templates`: exposes `agents_allowed` for pre-flight
checks.
## Testing
- coderd: mint/redeem happy path with an unauthenticated client,
expired/tampered/file-mismatched tokens, auth still required on the
plain file endpoint, non-owner mint rejection.
- toolsdk: harness + integration coverage for all new/changed tools,
including signed-URL redemption with checksum verification,
forward-cursor exactness, await transition/timeout paths, and label
filtering.
- Remote dogfood UAT (dev.coder.com Coder Agent) passed all six
acceptance scenarios end to end over both MCP transports.
Note: `go test ./codersdk/toolsdk/` has a pre-existing goleak flake on
main (leaked `agentssh` non-PTY session goroutines from SSH exec tests;
reproduced 3/3 on clean `b4971bc49f1`). It is unrelated to this diff.
> Mux acted on Mike's behalf to create this PR.
<!-- mux-attribution: model=claude-sonnet-4-6 thinking=high -->
Use typed atomics (atomic.Int64, atomic.Int32, etc.) in test files to prevent
mixing atomic and non-atomic access on the same value, guarantee 64-bit
alignment on 32-bit platforms, and provide a cleaner API.
Add Unwrap() to StatusWriter so http.ResponseController.SetWriteDeadline
can reach the underlying net.Conn through the middleware wrapper. Without
this, the agent's 20s WriteTimeout killed blocking process output
connections.
Also add 30s headroom to the write deadline in handleProcessOutput so
the response can be written after a full-duration blocking wait.
On the tool layer, waitForProcess and the process_output tool now try a
non-blocking snapshot on any error, not just context timeout. Transport
errors (like the WriteTimeout EOF) previously returned with no process
ID and no recovery path. Now if the process finished, the result is
returned transparently. If still running, the error includes the process
ID and tells the agent to use process_output.
Fixes all our Go file imports to match the preferred spec that we've _mostly_ been using. For example:
```
import (
"context"
"time"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"gopkg.in/natefinch/lumberjack.v2"
"cdr.dev/slog/v3"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/serpent"
)
```
3 groups: standard library, 3rd partly libs, Coder libs.
This PR makes the change across the codebase. The PR in the stack above modifies our formatting to maintain this state of affairs, and is a separate PR so it's possible to review that one in detail.
Upgrades to slog v3 which includes a small, but backward incompatible API change to the acceptible call arguments when logging. This change allows us to verify via compile time type checking that arguments are correct and won't cause a panic, as was possible in slog v1, which this replaces (v2 was tagged but never used in coder/coder).
It also updates dependencies that also use slog and were updated.
I've left the `aibridge` dependency as a commit SHA, under the assumption that the team there (cc @pawbana @dannykopping ) will tag and update the dependency soon and on their own schedule.
Other dependencies, I pushed new tags.
- 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>
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 adds a build flag to `exporter.go` in `coderd/tracing` that skips
compiling the file in slim builds. This file brings in some relatively
hefty dependencies that were growing the size of the slim binary a few
megabytes. All files that import `exporter.go` also aren't included in
slim builds, so this is safe.
We end up saving 5.4MB on the Linux slim binary.
* feat: allow external services to be authable
* Refactor external auth config structure for defaults
* Add support for new config properties
* Change the name of external auth
* Move externalauth -> external-auth
* Run gen
* Fix tests
* Fix MW tests
* Fix git auth redirect
* Fix lint
* Fix name
* Allow any ID
* Fix invalid type test
* Fix e2e tests
* Fix comments
* Fix colors
* Allow accepting any type as string
* Run gen
* Fix href
* chore: move `/gitauth` to `/externalauth` on the frontend
This actually took a lot more jank than anticipated,
so I wanted to split this up before adding the ability
to embed new providers.
* Rename FE
* Fix em' up
* Fix linting error
* Fix e2e tests
* chore: update helm golden files
* chore: add /v2 to import module path
go mod requires semantic versioning with versions greater than 1.x
This was a mechanical update by running:
```
go install github.com/marwan-at-work/mod/cmd/mod@latest
mod upgrade
```
Migrate generated files to import /v2
* Fix gen
* fix: Tidy up closes for nicer output
There was a context canceled message that would appear
because of traces, and this was using the wrong close.
I don't think it was causing any specific problems, but
it could make a replica warning appear on restart.
* Fix migration and experimental