cloudflare / cloudflare/agents
WebSockets state sync: clients can write state by default; consider a read-only mode
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 711
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 53
Description
## Problem
With `WebSockets({ state })`, any connected client can send a `cf_agent_state` frame and replace host state unless the host's `validateStateChange` rejects it, or the connection was marked readonly via the `readonly` policy or `setReadonly()`. Enabling sync therefore enables writes by default.
This matches Agent, where `validateStateChange` has always been the gate and `shouldConnectionBeReadonly` the per-connection switch, so #2257 kept parity deliberately. Devin flagged it on #2257 (`applyStateFrame`) as an easy way to expose writes unintentionally when a host only wanted to push state down.
## Possible shapes
- A `state: { sync: State, writable: false }` option (or `readonly: () => true` shorthand) that makes every connection readonly for state without touching the validator.
- Or accept the status quo and document the read-only recipe: `validateStateChange: (_, source) => { if (source !== "server") throw new Error("read-only"); }`, which works today and is already covered by tests.
Whichever is chosen should apply to Agent the same way, so the two hosts do not diverge.
## Where
- `packages/agents/src/websockets/options.ts`: `state`, `readonly`
- `packages/agents/src/websockets/websockets.ts`: `applyStateFrame`
- `docs/agents/lifecycle.md`: the `state` bullet
Contributor guide
Assessment
This issue has not been assessed yet.