Skip to content

Refuse a non-integer snapshotId as malformed, not stale - #486

Merged
davidmckayv merged 2 commits into
CopilotKit:mainfrom
Ayush7614:fix/computer-snapshotid-integer-validation
Sep 11, 2026
Merged

Refuse a non-integer snapshotId as malformed, not stale#486
davidmckayv merged 2 commits into
CopilotKit:mainfrom
Ayush7614:fix/computer-snapshotid-integer-validation

Conversation

@Ayush7614

Copy link
Copy Markdown
Contributor

What this changes

asRef and POST /:botId/control/secret accepted any typeof === number as a snapshot id. 1.5 and Infinity (valid JSON: 1e999 parses to it) then never equalled the stored integer, so the gateway reported a stale snapshot (409) plus an allowed-then-failed audit pair, and the caller retried a request that was malformed. Both sites now require Number.isInteger; malformed ids answer the existing 400 bad-ref before any decision or audit row.

Covers the acting routes through asRef (click/type and the rest) and the secret route which checks inline.

Where it runs

  • New state that outlives a request? None. Request-shape check at the route edge.
  • What happens on the second replica? Same 400 on every replica: no stored state consulted, no coordination needed. Stale-snapshot comparison afterwards still reads the snapshot store, unchanged.
  • Anything serialised? No. Refusal happens before gateway resolve/decide/audit.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? No.

Boundary and audit

  • Every acting call still goes through the gateway: resolve, decide, audit, then act. Malformed input is refused before the gateway, as before; well-formed input flows unchanged.
  • New refusals and new failures each write a row. N/A by design: a 400 for malformed input writes no audit row, matching the existing bad-ref path (only decided actions are audited).
  • Nothing new is trusted from the client that the server can resolve itself. The snapshot id is still compared against the server-held snapshot afterwards.

Changelog

  • A line in CHANGELOG.md under Unreleased: fractional/infinite snapshot id entry.

Proof

  • bun test server/tests/computer-snapshot-id.test.ts: 7 pass (integer reaches gateway; float, Infinity, -Infinity, string, null, boolean each 400 with the bad-ref message and zero gateway calls).
  • bun test server/tests/computer-scroll-delta.test.ts: still green (neighbouring edge-validation suite).
  • bun run format:check: clean. bun run lint: clean.
  • Server typecheck passes (bun run typecheck server/workspace OK; app has the pre-existing embla-carousel-react failure identical on clean main).

@davidmckayv davidmckayv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep-reviewed clean (validation, no secret leak, fail-closed, agrees with existing layers). CI green.

@davidmckayv
davidmckayv merged commit 339c367 into CopilotKit:main Sep 11, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants