Skip to content

Gate tokens on per-device rate; require human key holds for the keyboard exemption - #52

Merged
cport1 merged 1 commit into
mainfrom
feat/device-rate-gate-and-keyboard-exemption
Sep 11, 2026
Merged

Gate tokens on per-device rate; require human key holds for the keyboard exemption#52
cport1 merged 1 commit into
mainfrom
feat/device-rate-gate-and-keyboard-exemption

Conversation

@cport1

@cport1 cport1 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

What and why

An automated client was observed on the public demo verifying invisible mode every few seconds and receiving a token each time. Two things let it through: the keyboard-only accessibility exemption accepted key events with no pointer as proof of a keyboard user, and the per-minute rate limit only produced a detection in a category that carries almost no weight.

  • Per-device verification rate gate. After 10 verifications in a minute from one page instance on one device at one address, the token is withheld with reason: rate_limited. Keyed on the widget instance as well as address and fingerprint, so identical machines behind one address do not share a budget. A client that reports no instance id is not gated. Applied to Go, Node, and Python.
  • Keyboard exemption checks key holds. When hold data is present, at least three holds averaging under 20ms deny the exemption, and the session is scored as pointerless. No hold data keeps the exemption, so older widgets and visitors who only tab to the checkbox are unaffected. The widget now reports an average key hold alongside its key count; durations only, never which key.
  • Bench capture now holds keys with a human-like delay for the keyboard-only and screen-reader personas, so a future re-capture does not score the harness's own humans as agents.

Validation

  • run-bench.js --gate: human FPR 0.00% (0/126), agent TPR 97.33%, PASS.
  • Go vet and test, Node and Python suites pass, with ten new tests per server covering the exemption boundaries and the rate gate.
  • Playwright accessibility, lifecycle, and PoW specs pass with the new widget.
  • E2E detection suite passes against the Node server.

Compatibility

  • Integrators see a new withheld reason, rate_limited, documented in the README.
  • Sessions with mechanical key holds and no pointer now score as pointerless and can block.
  • The device fingerprint the gate uses differs between Go and Node (canvas hash field shape), which predates this change; under mixed-runtime Redis the per-device budget is counted per runtime.

Follow-up

  • Bench runs on macOS must be caffeinated; documented in bench/README.md.
  • The 20ms hold threshold is set well below the panel's 41ms floor and well above automation's 1 to 8ms; a real-human capture should confirm it before it is tightened.

https://claude.ai/code/session_0198hVg9KALKecyEFDhsDxdg

…lds for the keyboard exemption

An automated client on the public demo verified invisible mode every few
seconds and received a token each time. The keyboard-only accessibility
exemption accepted key events with no pointer as a keyboard user, and the
per-minute rate limit only produced a detection in a category weighing 0.01.

Per-device rate gate: after 10 verifications in a minute from one page
instance on one device at one address the token is withheld with
reason rate_limited. Keyed on the widget instance as well as address and
fingerprint so identical machines behind one address do not share a budget;
no instance id means no gate.

Keyboard exemption: when hold data is present, three or more holds averaging
under 20ms deny the exemption and the session scores as pointerless. No hold
data keeps it. The widget reports keyHoldSamples and keyHoldAvg (durations
only, never the key). Bench keyboard personas now hold keys like people.

Applied to Go, Node and Python with ten new tests each. Bench gate: human FPR
0.00% (0/126), agent TPR 97.33%. Playwright and E2E suites pass.

Claude-Session: https://claude.ai/code/session_0198hVg9KALKecyEFDhsDxdg
@cport1
cport1 merged commit bee9324 into main Sep 11, 2026
17 checks passed
@cport1
cport1 deleted the feat/device-rate-gate-and-keyboard-exemption branch September 11, 2026 00:34
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