Files
coder/site/src/utils
Phorcys 🐾 1bb0978361 fix(site): centralize UUID generation and fix non-secure crash (#28285)
Fixes OSS-38: `crypto.randomUUID is not a function` when accessing Coder
over plain HTTP.

### Root cause
`crypto.randomUUID` is only defined in secure contexts (HTTPS or
localhost). It is `undefined` when Coder is served over plain HTTP. The
`uuid` package's `v4()` short-circuits to `crypto.randomUUID()` when it
is truthy, and in the production bundle that path compiles down to a
direct `crypto.randomUUID()` call, so `uuidv4()` throws over HTTP.
Observed crash (Template Builder, in the `useMemo` that mints the
telemetry session ID):

```
TypeError: crypto.randomUUID is not a function
  Rt/h<@.../assets/TemplateBuilderPage-*.js
  useMemo@...
```

The same `uuidv4()` path backed the Terminal reconnection token and the
Agent chat tab IDs / reconnection tokens, so those flows were affected
too.

### Fix
Add a single `generateUUID` helper in `site/src/utils/random.ts` that
derives the UUID from `crypto.getRandomValues` (the one `Crypto` member
available in insecure contexts) and only calls `crypto.randomUUID` when
it actually exists. Route all client-side UUID generation through it, so
every call site is fixed at once and future ones stay safe.

### Changes

| Change | Route | Human tested/verified |
|---|---|---|
| `utils/random.ts` — new `generateUUID()` helper | N/A | N/A |
| `TemplateBuilderPage.tsx` — telemetry session ID |
`/templates/new/builder` | [x] |
| `TerminalPage.tsx` — reconnection token |
`/:username/:workspace/terminal` | [x] |
| `AgentChatPageView.tsx` — tab IDs + reconnection tokens |
`/agents/:agentId` | [ ] |
| `useChatDraftAttachments.ts` — draft client IDs | `/agents/:agentId` |
[x] |
| `TaskApps.stories.tsx` — mock app IDs (Storybook) |
`/tasks/:username/:taskId` | [ ] |
| `WorkspaceSharingIndicator.stories.tsx` — mock actor IDs (Storybook) |
`/workspaces` | [ ] |
| Removed unused `uuid` / `@types/uuid` direct deps | N/A | N/A |

`uuid` is still pinned via a `pnpm.overrides` entry because
`mermaid`/`streamdown` depend on it transitively.

### Tests
- `random.test.ts` covers a valid UUID, uniqueness, and the
insecure-context path (with `crypto.randomUUID` stubbed to `undefined`).
- `TerminalPage.test.tsx` now mocks `#/utils/random` instead of the
`uuid` module.

### Validation
- `make fmt`, `biome check`, `tsc --noEmit` clean
- `vitest run` green: `random.test.ts` (6), `TerminalPage.test.tsx`
(16), `useChatDraftAttachments.test.ts` (17), both changed stories (12)
- Reproduced the original crash over HTTP on a production build, top
frame `uuidv4()` in Template Builder.

---

_This PR was generated by Coder Agents on behalf of @phorcys420._
2026-08-19 15:51:42 +00:00
..
…
…