Skip to content

feat: WithStrictDecode to reject lossy client signal decodes#116

Merged
joaomdsg merged 1 commit into
mainfrom
feat/strict-decode
Jun 10, 2026
Merged

feat: WithStrictDecode to reject lossy client signal decodes#116
joaomdsg merged 1 commit into
mainfrom
feat/strict-decode

Conversation

@joaomdsg

Copy link
Copy Markdown
Member

Critic panel finding #4 (major; raised 3×). A client value overflowing a Signal[T]'s narrower numeric type (e.g. 9999 into Signal[int8]) was silently truncated; a shape mismatch silently dropped. The typed Signal was only as safe as a best-effort decode.

Change

WithStrictDecode(): a client value that overflows the target int/uint/float width, or whose JSON shape doesn't match the field, surfaces an action error and the handler does not run — corrupt input can't reach server state.

Decode is factored into decodeScalarChecked (reports the error); decodeScalarInto wraps + discards it so server-side store decodes (StateSess/StateTab from the backplane) keep the lenient contract. The struct-tag init= path stays best-effort (author input, not untrusted client). Off by default.

Tests

  • off: overflowing value (9999→int8) still runs the action (best-effort)
  • on: overflow surfaces an error naming the signal (over SSE)
  • on: in-range value (42) decodes cleanly

Full ci-check.sh green.

A client value that overflowed a Signal[T]'s narrower numeric type (e.g. 9999
into Signal[int8]) was silently truncated, and a shape mismatch was silently
dropped — the typed Signal was only as safe as a best-effort decode.

Add WithStrictDecode(): a client value that overflows the target int/uint/float
width or whose JSON shape doesn't match the field surfaces an action error and
the handler does not run, so corrupt input can't reach server state. Off by
default (best-effort decode preserved). The decode is factored into
decodeScalarChecked, which reports the error; decodeScalarInto wraps it and
discards it so server-side store decodes keep the lenient contract. The
struct-tag init path stays best-effort (author input, not untrusted client).
@joaomdsg
joaomdsg merged commit 324bd46 into main Jun 10, 2026
4 checks passed
@joaomdsg
joaomdsg deleted the feat/strict-decode branch June 10, 2026 19:17
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.

1 participant