activateCode checked the device lock only when the request carried a MAC, so
any client could read a locked code's line credentials by leaving `mac` out —
through /api/active_code, through player_api (which accepts a code as the
username with any password) and through the portal. A code bound to a device
now answers that device only; a request naming no device is refused like any
other mismatch. Admins and resellers clear a binding with "reset device".
The first activation is also claimed atomically: the UPDATE repeats the
"still unactivated" check in its WHERE, so of two requests that read a fresh
code at once only one binds its device and starts the countdown. The other
re-reads the code and meets the lock, instead of re-binding the code to itself
and restarting the subscription's expiry. is_new_activation now reports that
this call did the activation, not that one happened in the last 5 s.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuZvjFSdodqgpyXtaoH1Xt