## Summary
Phase 2 of the H1 → front-matter migration (`DOCS-483`; parent
`DOCS-477`). Makes the two reference-doc generators emit per-page
metadata as YAML front matter instead of a leading `# H1`, so generated
pages are self-describing and `make gen` stops reverting migrated pages
(Phase 3).
Phase 1 (`DOCS-482`) made the coder.com renderers prefer a front-matter
`title` (manifest fallback).
> [!NOTE]
> Rebased onto `main` and fully regenerated, and updated across two
rounds of Coder Agents Review — see **Review follow-ups** below.
## Changes
- **`scripts/clidocgen/command.tpl` + `gen.go` + `main.go`** — front
matter now carries `title` (from `fullName`) and `description` (from the
command's `Short`), and the leading `# H1` is dropped. The CLI index
page's front matter is taken from the manifest `Command Line` route
(title/description/icon_path).
- **`scripts/apidocgen/postprocess/main.go`** — reads the manifest and,
at write time, injects front matter carrying each section's `title` plus
any curated `description`, `state`, and `icon_path`. The API index
page's front matter is taken from the manifest `REST API` route.
- **`scripts/docgenenv`** (new shared code) — one `YAMLScalar`
front-matter escaper, one `Route`/`Manifest` schema +
`LoadManifest`/`FindRoute`, and one `FrontMatter(Route)` emitter, all
imported by both generators (no duplicated helpers, types, or emitters).
- Regenerated all **166 CLI + 31 API** reference pages.
### Metadata → front matter, and what stays in the manifest
Every *per-page* manifest field is mirrored into the page's front
matter: `title`, `description`, `state`, `icon_path`. The **structural**
fields stay in `manifest.json`:
- `children` — the nav tree (explicitly out of scope).
- `path` — the manifest's pointer to the file; a page carrying its own
path is redundant/error-prone, so it's treated like `children`.
The fields are **duplicated** into front matter and **`manifest.json` is
left unchanged**, so this is a **no-op for rendering today** (coder.com
strips front matter for `llms`, and Algolia + the renderer read only
`title`). Removing the fields from the manifest is the natural
follow-up, gated on the renderer reading them from front matter first.
### Why the API side changes the postprocessor, not the `.dot` templates
The issue text suggested editing
`scripts/apidocgen/markdown-template/*`. I deliberately did **not**,
because the postprocessor derives each page's **filename, section title,
and manifest route** from the leading `# {name}` line
(`extractSectionName`). Emitting front matter from the template would
break that extraction. Instead the widdershins templates still emit `#
{name}`, the postprocessor reads it (and now verifies it), and then
swaps the heading for a front-matter block as each section is written.
## Review follow-ups (Coder Agents Review)
### Round 1 — addressed in `e53d5e03` (all threads resolved)
- **CRF-1 / CRF-4** — de-duplicated the escaper and the
`route`/`manifest` schema + traversal into `scripts/docgenenv` (shared
by both generators).
- **CRF-2** — `YAMLScalar` now quotes YAML-reserved scalars
(`true/false/null/…`, numbers); no current value is affected.
- **CRF-3** — added unit tests: a `YAMLScalar` round-trip, `FindRoute`,
and `prependFrontMatter`.
- **CRF-5** — the CLI and API **index** pages now mirror their manifest
route's title/description/icon_path instead of a hardcoded
`coder`/`API`, fixing a rendered-heading regression (`REST API`/`Command
Line` were being overwritten).
- **CRF-6** — dropped the dead `#login` anchor in
`docs/support/support-bundle.md` (the migrated `login.md` no longer
mints that heading anchor).
- **CRF-7 / CRF-8 / CRF-11** — renamed to `prependFrontMatter`, switched
to `bytes.Cut`, and it now strips the first line only when it is the `#
{name}` heading (`extractSectionName` errors otherwise).
- **CRF-9** — removed the orphan `docs/reference/api/chat.md` (not in
the manifest, not linked; the real page is `chats.md`).
- **CRF-10** — the metadata read and the manifest rewrite now share one
`FindRoute` traversal.
- **CRF-13** — moot under squash-merge; this branch is a single
scopeless commit.
- **CRF-15** — the pre-existing `sort.Slice`/`slices.IsSorted`
comparator is left as-is per the review (out of scope; safe today
because section names are unique).
### Round 2 — addressed in `ee796e7107` (all threads resolved)
- **CRF-16** (P1) — removed three em-dashes from new doc comments (the
only `make lint` failure on the prior head); the emdash gate is green.
- **CRF-17 / CRF-18** — unified front-matter emission into one shared
`docgenenv.FrontMatter(Route)`, used by the API postprocessor directly
and by `command.tpl` via a `frontMatter` template func. This retires the
hand-written template YAML and the
`indexTitle`/`indexDescription`/`indexIconPath` closures, so a new
front-matter field is wired in one place, and it gives the CLI index the
`state` arm it previously lacked. Verified byte-identical: a full CLI +
API regen produces zero page changes.
- **CRF-19** — CLI child sort switched to `slices.SortFunc` +
`cmp.Compare` (typed comparator).
- **CRF-20** — reworded the `prependFrontMatter` comment:
`extractSectionName`'s fail-fast is the load-bearing guard; the prefix
check is a defensive backstop.
- **CRF-21** — added `icon_path`/`state` coverage in `docgenenv`'s
`TestFrontMatter/AllFields` (the branch the index page relies on,
previously at 0%).
- **CRF-22** — `YAMLScalar` no longer emits a trailing-space value as a
bare scalar (YAML strips it on read, so it would not round-trip); added
test coverage.
- **CRF-24** — the shared emitter removed the duplicated `cliIndexRoute`
doc comment; the rationale now lives in one place.
- **CRF-23** (Phase 3, out of scope here) — noted: the API generator
wipes and regenerates `reference/api/` from the manifest, so removing
curated metadata from the manifest in Phase 3 needs another source first
(a generator that preserves existing front matter, or metadata carried
alongside the swagger annotations).
- **Process (Mafu-san)** — the verification set below now leads with
`make lint`, the mandatory CI gate that the earlier list omitted.
## Cross-repo dependency
**Resolved — this PR no longer has a hard merge-ordering gate** (CRF-14
was right; the earlier "must merge after #968" note was stale).
The coder.com surfaces that would otherwise leak raw front matter from
`coder/coder` `main` are already front-matter-aware on merged PRs:
- **coder.com#964** (`DOCS-554`, llms-full.txt corpus + Algolia) —
**merged**.
- **coder.com#974** (`DOCS-574`, the `.md` proxy twin + `llms.txt` index
titles) — **merged**.
coder.com#968 (`DOCS-577`) was re-scoped to only the renderer
route-metadata generalization; it's a no-op on today's corpus and its
own description confirms the "deploy before the generators" constraint
no longer applies (that was driven by the llms corpus, now in #964).
Worth a final confirmation that #964/#974 are **deployed** before merge,
but there's no branch/PR ordering blocker left.
## Verification & evidence
AI was the primary author of this PR (see disclosure below); per the [AI
Contribution
Guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
here is manual verification.
- `make lint` (golangci-lint + the emdash gate) passes; `go build` / `go
vet` / `go test` are clean for the generators + `scripts/docgenenv`;
`pnpm check-docs` passes.
- `swagger.json`, `docs.go`, and `manifest.json` are **unchanged** —
metadata is duplicated into front matter; command/section names and
routes did not move.
- The diff is purely additive front matter
(`title`/`description`/`state`/`icon_path`) + the leading H1 removal; no
body reflow. A full CLI + API regen produces **zero** page changes
beyond the two index pages.
<details>
<summary>Terminal evidence</summary>
CLI `description` from the command's `Short` (`YAMLScalar` quotes when
needed, e.g. a `Short` with a colon):
```md
---
title: server
description: Start a Coder server
---
```
API pages inherit curated manifest metadata (only Agents/Chats have any
today):
```md
---
title: Chats
description: "REST endpoints for Coder Agents Chats API (programmatic agent sessions)."
state:
- early access
---
```
Diff scope + "no body changes" proof (uses an explicit `base..HEAD`
range, so it actually tests the claim):
```
$ git diff --shortstat origin/main
210 files changed, 1447 insertions(+), 344 deletions(-)
# = 166 CLI + 31 API reference pages + generators + scripts/docgenenv
# swagger.json / docs.go / manifest.json: NOT modified
# Every removed line under docs/reference is a leading "# H1"; nothing else:
$ git diff origin/main..HEAD -- docs/reference/ | grep '^-' | grep -v '^---' | grep -v '^-# '
(empty)
$ pnpm check-docs
Summary: 0 error(s)
```
</details>
Linear: DOCS-483
> This PR was created with AI assistance (Coder Agents).
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.
Relates to CODAGT-713
Depends on #27284
This makes the per-template `agents_allowed` field authoritative in the API and chatd. It adds optional create and metadata update fields with the intended default and omission semantics, supports `agents-allowed:` template search, includes the value in telemetry, and makes `list_templates`, `read_template`, and `create_workspace` read the template row directly. Existing-workspace retries remain idempotent, and blocked same-organisation templates return an actionable message.
The experimental `/template-allowlist` routes remain temporarily because the shipped AI Settings page still calls them, but they no longer control chatd enforcement. #27514 moves that page to per-template metadata, #27515 removes the legacy storage, routes, SDK types, and utility, #27517 adds the CLI flags, and #27518 updates the platform controls documentation for the per-template model, directly addressing CRF-5 and CRF-6. The stack is intended to merge as a unit.
Normalizes non-standard code-fence language tags across `docs/**` so a
strict highlighter (Shiki, used by Fumadocs) won't fail the build on an
unrecognized language, and unifies redundant synonym tags onto one
canonical form per language. The current renderer (Speed-Highlight)
detects the language from the code content, not the fence label, so this
drift wasn't visible until now.
## Changes
- `hcl` -> `tf` (199 fences, including indented ones nested in
numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two
distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**`
is actually Terraform resource/data/provider syntax, so the more
specific `terraform` grammar is correct for all of them. `tf` is Shiki's
own alias for that grammar, and it's also what GitHub's own markdown
renderer resolves to the same HCL/Terraform highlighting.
- `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered
PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a
registered file extension (`.ps` isn't), so `ps1` renders identically to
`powershell` there today while bare `ps` would silently lose
highlighting.
- `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files)
- `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text
fallback either way, just shorter.
- `Dockerfile` -> `dockerfile` (lowercase)
- `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all
three to a single shell grammar; this was already the style guide's
stated preference, just not enforced across the existing corpus until
now.
- `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki
and GitHub.
- `jsonc` -> `json` (1 fence). The block has no comments or trailing
commas, so it doesn't need the comments-capable grammar.
- `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`).
Verified the actual content tokenizes identically under both grammars,
and a sibling block in the same file already needs `tsx` for real JSX,
so unifying to one tag is safe for this file. Documented a caveat: `tsx`
mis-tokenizes the legacy angle-bracket type-assertion syntax
(`<Type>value`), which is invalid in real `.tsx` files anyway, so use
`value as Type` instead.
- `yml` -> `yaml` (1 fence)
- Updated `docs/.style/style-guide/formatting.md` to document all
canonical tags
`promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki
doesn't bundle a grammar for either, so they need a custom grammar
registration when the site adopts Shiki, rather than degrading to `txt`.
Tracked as follow-up work under DOCS-118 and
[DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting)
(promql).
Does not touch `offlinedocs/`.
Linear:
[DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs)
<details>
<summary>How the fence tags were verified</summary>
Each tag was tested against a real `shiki@latest` highlighter instance
(`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's
`@wooorm/starry-night` grammar sources (the renderer that actually
displays these `.md` files today, in repo browsing and PR diffs), since
that's what determines whether brevity is safe before Shiki adoption:
```text
FAIL env -- Language `env` is not included in this bundle.
FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle.
FAIL promql -- Language `promql` is not included in this bundle.
FAIL caddyfile -- Language `caddyfile` is not included in this bundle.
FAIL pwsh -- Language `pwsh` is not included in this bundle.
FAIL output -- Language `output` is not included in this bundle.
```
`hcl` doesn't error in Shiki, since it's a real grammar, but that's
exactly the trap: it was silently rendering every fence with the generic
HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged
fence in `docs/**` was manually checked against `origin/main` and is
genuinely Terraform content.
For `ts`/`tsx`, tokenizing the actual doc content confirmed identical
output under both grammars; a synthetic test with the legacy
angle-bracket cast syntax confirmed `tsx` degrades on that specific
construct, which the style guide now calls out.
The first normalization pass only matched fence tags at column 0
(`^```tag$`), missing tags indented inside numbered/bulleted lists. A
follow-up pass caught the remaining occurrences at any indentation
level.
</details>
---
*This PR description and the underlying changes were prepared with Coder
Agents assistance.*
Removes the coder_secret Terraform integration: the data.coder_secret
consumption path through provisionerdserver → provisioner.proto →
provisioner/terraform, the dynamic-parameter secret-requirement
validation, and the workspace-update / resolve-autostart surfaces that
depended on it. This is being done due to a product/feature direction
change (see PLAT-243). User-secret CRUD (DB, REST, CLI, UI, telemetry, audit)
and the agent-manifest secret-injection path are untouched.
The provisionerd API is bumped from v1.17 to v1.18 rather than rolled
back: v1.17 shipped in v2.33.x, so user_secrets field numbers are
reserved and the changelog documents both versions.
Generated with assistance from Coder Agents.
## Summary
When a workspace build fails because the user is over their group quota,
the chat tools currently surface the failure as a bare `"workspace build
failed: insufficient quota"` string with no machine-readable error code
and no visibility into the user's current usage. Agents and the UI
cannot distinguish quota failures from any other Terraform error, so
users see an opaque message and have no clear path to recovery.
This PR tags quota failures with a typed error code at the source and
propagates it through the chat tool layer so callers can react to it
explicitly.
Relates to CODAGT-20
## Changes
**Provisioner runner**
- Add `InsufficientQuotaErrorCode = "INSUFFICIENT_QUOTA"` and set it
explicitly at the `commitQuota` failure site via a new
`failedWorkspaceBuildfCode` helper, so `provisioner_jobs.error_code` is
populated only on the genuine quota path. The substring matcher used for
externally produced sentinels (e.g. `"missing parameter"`, `"required
template variables"`) is intentionally not extended; provider errors
that happen to mention "insufficient quota" stay classified as generic
build failures.
**SDK and API contract**
- Add `JobErrorCodeInsufficientQuota` and a
`JobIsInsufficientQuotaErrorCode` helper to `codersdk`.
- Extend the swagger `enums` tag on `ProvisionerJob.ErrorCode` to
include `INSUFFICIENT_QUOTA`.
- Regenerate `coderd/apidoc`, `docs/reference/api/*`, and
`site/src/api/typesGenerated.ts`.
**chattool create_workspace / start_workspace**
- `waitForBuild` now returns a typed `*workspaceBuildError` carrying
both the message and the `JobErrorCode`, instead of a bare error string.
- New `quotaerror.go` introduces a structured `quotaErrorResult` (with
`error_code`, `title`, `message`, `build_id`, and optional `quota`) and
a best-effort `workspaceQuotaDetails` lookup that wraps owner
authorization internally and fetches `credits_consumed` and `budget`
from the database. Quota lookup failures (including authorization
failures) never block the failure payload.
- On quota-coded build failures, both `create_workspace` and
`start_workspace` now return the structured response (with the recovery
guidance inlined into `message`) instead of the bare `"insufficient
quota"` string. This applies to all three failure paths: post-creation,
an in-progress existing build, and a freshly triggered start build.
Non-quota build failures continue to use the existing
`buildToolResponse` / `newBuildError` path.
- Owner authorization is wrapped only on the call sites that need it
(the `CreateFn` and `StartFn` invocations and the quota-detail lookup),
so idempotent fast paths (already running, already in progress,
existing-workspace early returns) do not pay for an extra RBAC
round-trip or fail when role lookup is transient.
## Out of scope
- No changes to quota math, allowances, or bypass behavior.
- No automatic retries.
- No new quota-inspection tools and no changes to MCP
`coder_create_workspace` (which returns immediately and never observed
the build outcome here).
- No frontend UI changes; those will land in a follow-up PR that
consumes the new `INSUFFICIENT_QUOTA` code.
Adds structured `secret_requirements` to dynamic parameter responses and
enforces missing required secrets during workspace start.
Stop, delete, and tag rendering paths skip secret requirement
enforcement so unmet secrets do not prevent cleanup. The SDK, generated
API docs/types, and backend render/resolver/wsbuilder tests are updated
for the new contract.
> [!WARNING]
> The change of the status code from `404` to `204` could break peoples
code downstream. Adding this as a breaking change incase.
Theres a whole ton of noise around failed requests, these are all
unrelated to the actual thing that is broken at hand (and are
confusing).
* Change `/api/v2/organizations/.../templates/.../versions/.../previous`
to return `204` instead of `404` (actually makes more sense because the
content doesn't exist, but the route is found.
* Remove unnecessary calls to `/api/v2/users/me/appearance` when the
user isn't logged in.
* Remove unnecessary calls to `/api/v2/deployment/stats` when the
deployment stats aren't allowed to be seen.
* Various changes to `workspace-sharing` so we don't make unnecessary
calls.
Whats left:
* `/api/v2/users/me` still `401`s on the login page. This persists as
when the user is logged in but tries to reach the sign-in page they
should be redirected to the app, not sign in again.
* `monaco-editor` is still upset... we theoretically could inject an
environment that can serve workers... but eh.
#### Old
```sh
% pnpm playwright:test -g "create workspace with default and required parameters"
> coder-v2@ playwright:test /home/coder/coder/site
> playwright test --config=e2e/playwright.config.ts -g 'create workspace with default and required parameters'
...
Running 2 tests using 1 worker
✓ 1 …e/setup/addUsersAndLicense.spec.ts:7:5 › setup deployment (8.2s)
2 ….ts:79:5 › create workspace with default and required parameters
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[console][error] Failed to load resource: the server responded with a status of 403 (Forbidden)
[response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."}
[console][error] Failed to load resource: the server responded with a status of 403 (Forbidden)
[response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."}
[console][error] Failed to load resource: the server responded with a status of 404 (Not Found)
[response] url=http://localhost:3111/api/v2/organizations//provisionerdaemons status=404 body={"message":"Resource not found or you do not have access to this resource"}
[console][error] Failed to load resource: the server responded with a status of 404 (Not Found)
[response] url=http://localhost:3111/api/v2/organizations/default/templates/a4e8096d/versions/agreeable_glenn33/previous status=404 body={"message":"No previous template version found for \"agreeable_glenn33\"."}
[console][warning] Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq
[console][warning] You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[console][error] Failed to load resource: the server responded with a status of 403 (Forbidden)
[response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."}
✓ 2 …5 › create workspace with default and required parameters (7.0s)atus of 403 (Forbidden)
[response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."}
[console][error] Failed to load resource: the server responded with a status of 403 (Forbidden)
[response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."}
2 passed (56.1s)
```
`23 LOL` (Lines of logs)
#### New
```sh
% pnpm playwright:test -g "create workspace with default and required parameters"
> coder-v2@ playwright:test /home/coder/coder/site
> playwright test --config=e2e/playwright.config.ts -g 'create workspace with default and required parameters'
...
Running 2 tests using 1 worker
✓ 1 …e/setup/addUsersAndLicense.spec.ts:7:5 › setup deployment (8.7s)
2 ….ts:79:5 › create workspace with default and required parameters
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[console][warning] Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq
[console][warning] You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker
✓ 2 …5 › create workspace with default and required parameters (7.1s)atus of 401 (Unauthorized)
[console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized)
[response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
[response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."}
2 passed (32.0s)
```
`9 LOL` (Lines of logs)
Closes#16332
Previously `coder provisioner jobs list` showed no indication of what a workspace
build job was doing (i.e., start, stop, or delete). This adds
`workspace_build_transition` to the provisioner job metadata, exposed in
both the REST API and CLI. Template and workspace name columns were also
added, both available via `-c`.
```
$ coder provisioner jobs list -c id,type,status,"workspace build transition"
ID TYPE STATUS WORKSPACE BUILD TRANSITION
95f35545-a59f-4900-813d-80b8c8fd7a33 template_version_import succeeded
0a903bbe-cef5-4e72-9e62-f7e7b4dfbb7a workspace_build succeeded start
```
**Background**
Reported in #17417, there is a `deleted` query parameter supported by
/api/v2/templates, but we do not respect this field on the client,
showing the "Create Workspace" button for deleted templates.
**Expected Behavior**
Don't show the "Create Workspace" button for deleted templates.
**Notes**
This PR adds a new `deleted` field to the templates API response.
Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
* Adds support for parameter `format=text` in the following API routes:
* `/api/v2/workspaceagents/:id/logs`
* `/api/v2/workspacebuilds/:id/logs`
* `/api/v2/templateversions/:id/logs`
* `/api/v2/templateversions/:id/dry-run/:id/logs`
* Adds links to view raw logs on the following pages:
* Workspace build page
* Template editor page
* Template version page
* Refactors existing log formatting in `cli/logs.go` to live in `codersdk`.
🤖 Generated with Claude Opus 4.5, reviewed by me.
---------
Co-authored-by: Claude <noreply@anthropic.com>
For experimental and dogfood purposes, this adds the ability to opt in a single template.
Leaving the rest of the templates as is.
For GA, this setting might be removed or changed.
- Adds FK from `aibridge_interceptions.initiator_id` to `users.id`
- This is enforced by deleting any rows that don't have any users. Since
this is an experimental feature AND coder never deletes user rows I
think this is acceptable.
- Adds `name` as a property on `codersdk.MinimalUser`
- This matches the `visible_users` view in the database. I'm unsure why
`name` wasn't already included given that `username` is.
- Adds a new `initiator` field to `codersdk.AIBridgeInterception` which
contains `codersdk.MinimalUser` (ID, username, name, avatar URL)
- Removes `initiator_id` from `codersdk.AIBridgeInterception`
- Should be fine since we're still in early access
Relates to https://github.com/coder/internal/issues/934
This PR provides a mechanism to filter provisioner jobs according to who
initiated the job.
This will be used to find pending prebuild jobs when prebuilds have
overwhelmed the provisioner job queue. They can then be canceled.
If prebuilds are overwhelming provisioners, the following steps will be
taken:
```bash
# pause prebuild reconciliation to limit provisioner queue pollution:
coder prebuilds pause
# cancel pending provisioner jobs to clear the queue
coder provisioner jobs list --initiator="prebuilds" --status="pending" | jq ... | xargs -n1 -I{} coder provisioner jobs cancel {}
# push a fixed template and wait for the import to complete
coder templates push ... # push a fixed template
# resume prebuild reconciliation
coder prebuilds resume
```
This interface differs somewhat from what was specified in the issue,
but still provides a mechanism that addresses the issue. The original
proposal was made by myself and this simpler implementation makes sense.
I might add a `--search` parameter in a follow-up if there is appetite
for it.
Potential follow ups:
* Support for this usage: `coder provisioner jobs list --search
"initiator:prebuilds status:pending"`
* Adding the same parameters to `coder provisioner jobs cancel` as a
convenience feature so that operators don't have to pipe through `jq`
and `xargs`
This pull request introduces support for external workspace management, allowing users to register and manage workspaces that are provisioned and managed outside of the Coder.
Depends on: https://github.com/coder/terraform-provider-coder/pull/424
* GET /api/v2/init-script - Gets the agent initialization script
* By default, it returns a script for Linux (amd64), but with query parameters (os and arch) you can get the init script for different platforms
* GET /api/v2/workspaces/{workspace}/external-agent/{agent}/credentials - Gets credentials for an external agent **(enterprise)**
* Updated queries to filter workspaces/templates by the has_external_agent field
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
## 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 -->
"Idle" is more accurate than "complete" since:
1. AgentAPI only knows if the screen is active; it has no way of knowing
if the task is complete.
2. The LLM might be done with its current prompt, but that does not mean
the task is complete either (it likely needs refinement).
The "complete" state will be reserved for future definition.
Additionally, in the case where the screen goes idle but the LLM never
reported a status update, we can get an idle icon without a message, and
it looks kinda janky in the UI so if there is no message I display the
state text.
Closes https://github.com/coder/internal/issues/699
# Description
This PR adds the `worker_name` field to the provisioner jobs endpoint.
To achieve this, the following SQL query was updated:
-
`GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner`
As a result, the `codersdk.ProvisionerJob` type, which represents the
provisioner job API response, was modified to include the new field.
**Notes:**
* As mentioned in
[comment](https://github.com/coder/coder/pull/17877#discussion_r2093218206),
the `GetProvisionerJobsByIDsWithQueuePosition` query was not changed due
to load concerns. This means that for template and template version
endpoints, `worker_id` will still be returned, but `worker_name` will
not.
* Similar to `worker_id`, the `worker_name` is only present once a job
is assigned to a provisioner daemon. For jobs in a pending state (not
yet assigned), neither `worker_id` nor `worker_name` will be returned.
---
# Affected Endpoints
- `/organizations/{organization}/provisionerjobs`
- `/organizations/{organization}/provisionerjobs/{job}`
---
# Testing
- Added new tests verifying that both `worker_id` and `worker_name` are
returned once a provisioner job reaches the **succeeded** state.
- Existing tests covering state transitions and other logic remain
unchanged, as they test different scenarios.
---
# Front-end Changes
Admin provisioner jobs dashboard:
<img width="1088" alt="Screenshot 2025-05-16 at 11 51 33"
src="https://github.com/user-attachments/assets/0e20e360-c615-4497-84b7-693777c5443e"
/>
Fixes: https://github.com/coder/coder/issues/16982
## Description
Modifies the behaviour of the "list templates" API endpoints to return
non-deprecated templates by default. Users can still query for
deprecated templates by specifying the `deprecated=true` query
parameter.
**Note:** The deprecation feature is an enterprise-level feature
## Affected Endpoints
* /api/v2/organizations/{organization}/templates
* /api/v2/templates
Fixes#17565
https://github.com/coder/coder/pull/17163 introduced the
`workspace_app_statuses` table. Two of these fields
(`needs_user_attention`, `icon`) turned out to be surplus to
requirements.
- Removes columns `needs_user_attention` and `icon` from
`workspace_app_statuses`
- Marks the corresponding fields of `codersdk.WorkspaceAppStatus` as
deprecated.
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.
As we worked on adding a `open_in` parameter for workspace_apps - we
initially created three options :
- window
- slim_window
- tab
After further investigation, `window` should not be used and has to be
removed.
ℹ️ I decided to remove the option instead of deprecating it as we've not
created any release nor documented the feature. Can be discussed.