Currently in testing: the GitHub code will be opened once complete.

Field Constraints and Value Ranges

Request Fields (C→S)

FieldTypeValid rangeMeaningOn violation
opASCII 1BA(0x41) · R(0x52)Request kindE bad_op
waitu80255 (seconds)0 is an immediate attempt with no queue; 1..255 is the acquire-wait cap— (always valid by type)
leaseu81250 (seconds)Lease. 0 and 251..255 are rejected/reservedE bad_lease
owneru64 BEthe full 02^64-1Acquire-attempt identifier (client-generated)— (server does not validate)
tokenu64 BEa server-issued valueNames what to release (R only)N on mismatch
keyUTF-81 – 128 bytesLock name. No whitespace (0x20) or newline (0x0A)E bad_key
  • There is no infinite wait or lease. Official clients round sub-second values up, validate the range, and return an explicit input error before sending instead of clamping an out-of-range value. The default lease is 30 seconds.
  • In the official client API, wait is the whole acquire limit from call entry through the local queue, definitely-unsent connection retries, the write, and the response. The client creates one monotonic operation deadline, and immediately before sending the writer puts the u8 ceiling of the remaining seconds into the frame's wait. A late connection or definitely-unsent failover therefore cannot restart the server wait from the beginning. At the deadline, a request still queued times out definitely unsent; if even one byte may have been sent, the exact session is closed and the result is Indeterminate. Only an original wait=0 uses wire 0, and that immediate attempt has a separate finite I/O deadline so a stalled transport cannot block forever. If a correlated A from just before the deadline is discovered late at the Ticket delivery gate, the server waiter is already resolved: keep the session open, compensate the known exact token, and return Indeterminate. Correlated T/B remain definitive non-acquisitions.
  • For an original wait=0, wire and server behavior remain one immediate, non-queued attempt. Within its separate five-second transport deadline, a definitely-unsent failure may select another connection and retry with the same owner. Once any byte may have been sent, the acquire is never retransmitted.
  • The official client API requires min_work_budget, which is not carried on the wire. It must cover critical work + expected pause + DB commit/rollback completion, be in 0..250 seconds, and not exceed the normalized lease. Violations fail before any frame is sent with an UnsupportedDuration/InsufficientLease-class error.
  • Key length is measured in bytes, not characters — Korean is 3 bytes per character in UTF-8, so at most 42 characters.
  • owner is only a response correlation ID, not authority. Reusing it does not return an active token or renew a lease. Concurrent in-flight requests from one client must still use distinct non-zero values so responses remain unambiguous. Official clients fail closed if their local counter reaches zero or wraps.
  • bad_key covers an empty key, one over 128 bytes, one containing whitespace or a newline, and invalid UTF-8, all alike. Official clients additionally never send \r — a key ending in \r would silently become a different key.
  • Explicit release and compensating release for an already-known token have one absolute 5-second deadline from call/enqueue time, including reconnects and retries. R confirms success; N means already gone or not the current token. No observed response is never assumed to mean success. A full bounded compensation queue falls back to the lease-expiry safety net.

Response Fields (S→C)

FieldTypeRangeAppears in
tokenu64 BE1 or greater, increasing with every grantA (newly issued) · R/N (request echo)
owneru64 BEthe request value verbatimA · T · B (request echo)
keyUTF-8the request value verbatim (1–128B)A · T · B · R · N
addrUTF-8host:portM · L
reasonASCIIone of eightE

The server never issues token 0. Single mode uses a counter for the current process lifetime; cluster mode uses a consensus-replicated counter and fails closed before overflow. Wall clock or randomness is not claimed to provide monotonicity across restart.

Fixed-Header Lengths

The fixed-length binary run that follows the op. These bytes may contain 0x0A, so a parser must consume exactly this many before it starts scanning for the newline.

DirectionopFixed headerComposition
C→SA10 Bwait(1) + lease(1) + owner(8)
C→SR8 Btoken(8)
S→CA16 Btoken(8) + owner(8)
S→CT · B8 Bowner(8)
S→CR · N8 Btoken(8)
S→CM · L · E0 Bnone (text starts right after the op)

Too few bytes yields E bad_request.

Frame Size

ItemValue
Frame limit (excluding \n)192 bytes — beyond that, E line_too_long
Largest A request1 + 10 + 128 + 1 = 140 B
Largest R request1 + 8 + 128 + 1 = 138 B
Largest A response1 + 16 + 128 + 1 = 146 B
Empty frame (a lone \n)keep-alive — ignored by the server

The 192B limit sits comfortably above the largest possible frame (146B), so a client that follows the spec can never hit it. After a structurally malformed or oversized frame, framing is no longer trusted and the connection is closed.

Auth Handshake

ItemValue
HashSHA-256 (named in the challenge line)
nonce8 base64url characters
Response digest43 base64url characters (unpadded)
Line limit256 bytes
Time limit10 seconds (including TLS negotiation) — the connection is closed if exceeded

See Auth Handshake for the full procedure.

Server-Side Limits

Values a client never sets directly, but which still shape its behaviour.

ItemDefaultSettingWhen exceeded
Waiters per key2048 (hard cap 16384)MAX_WAITERSB (busy)
Total waiters16384 (hard cap 65536)MAX_TOTAL_WAITERSThat acquire gets B
Concurrent client connections1024 (hard cap 8192)MAX_CONNECTIONSConnection closed immediately
Backlogged replies per connection256(compile-time constant)Slow client connection closed
Global in-flight acquire4096(compile-time constant)That acquire gets B
Global in-flight release512, separate lane(compile-time constant)Bounded wait until connection close
Cluster active keys65536(compile-time constant)A new-key acquire gets B

The read buffer (4096B), response batch (64), 5-second progress timeout for a started client frame, and the single-mode expiry sweep (5 seconds) are compile-time constants, not environment variables. Cluster expiry uses a token-validating deadline min-heap rather than a full scan. For the full list of configurable values and their valid ranges, see Configuration (Env Vars).

Acquire, new-key, and total-waiter admission closes at 90% of each hard limit and reopens only after usage falls below 75%. A new acquire can therefore get B before the hard limit; capacity reserved for release and Raft recovery is separate from this hysteresis.

Violation → Response Summary

SituationResponseConnection
Unknown opE bad_opclosed
Fixed header too shortE bad_requestclosed
lease = 0 or 251..255E bad_leaseclosed
Key empty / over 128B / contains whitespace or newline / not UTF-8E bad_keyclosed
Frame over 192BE line_too_longclosed
Auth digest mismatchE auth_failedclosed
Wait queue fullB + owner + keykept
Release token mismatchN + token + keykept

For every error reason and its connection handling, see Response · Error E.