throttlekit
·

A hardening sweep — throttlekit 1.6.0 and server 0.4.x

A multi-agent audit pass landed across the core and the server: correctness, concurrency, and security fixes — each reproduced on real code, traced to root cause, and pinned by a regression that failed on the prior commit.

The last few weeks were not about new features. They were about making sure the features already shipped are correct: a full audit sweep across the core and the server, run by multiple independent passes over security, math, logic, performance, and concurrency. Every finding was reproduced on the real code, traced to a root cause, and pinned by a regression test proven to fail on the commit before the fix. Here’s what shipped.

throttlekit 1.6.0

A minor (not a patch) only because a few fixes add opt-in, backward-compatible options. No default that was already correct changed shape. Among the fixes:

  • Concurrency-coordinator over-eviction. RedisConcurrencyCoordinator compared each peer’s stored deadline against the calling node’s wall clock, so a node with a fast clock evicted healthy peers and over-granted. Eviction now resolves now from the Redis server clock (new useServerTime, default on).
  • Two window-roll over-admits. A federation lease that resolved after a concurrent check rolled to the next window was credited into the new window; likewise a late twoTier low-water refill could smuggle a pre-boundary lease past the roll. Both now capture the granting window and forfeit a rolled grant.
  • multiRateLimit Redis prefix. check() wrote multi keys without the store prefix while reset() deleted with it, so reset() was a silent no-op and two prefixed stores could collide. Both paths now flow through the prefix.
  • New opt-in safety valves: RedisStore.ttlFloorMs (keep a logically-live key from being GC’d under a node clock), and a per-instance random seed for the DDoS sketches.

throttlekit-server 0.4.1 → 0.4.3

The server picked up its own findings, including two that matter for anyone running it exposed:

  • Lease-id hijacking (0.4.2, security). Admit minted lease ids as a process-global sequential counter, and Release / Heartbeat keyed only on the id with no ownership check, so a client could enumerate ids to free another client’s concurrency slot or renew its deadline. Lease ids are now 128-bit random capability tokens.
  • Monitor door resilience (0.4.2 / 0.4.3). GetSnapshot could be taken down by a single non-serializable custom stat (a BigInt counter, a circular object); it now uses a safeStringify that tames those. A later fix corrected that guard’s DAG false-positive, so a shared-but-not-circular object is no longer mangled to "[Circular]".
  • Honest mTLS labelling (0.4.3). The startup banner reported mTLS whenever a CA was given, even if the cert/key were missing and the channel had silently downgraded to insecure. The label now tracks the channel actually built, and startup fails closed.
  • Replay what-if accuracy (0.4.1). The what-if shadow misclassified distributed policies (federated / fleetBudget / distributedConcurrency / federatedFairEscrow) as plain leaf-rate (a silently-wrong baseline for exactly the policies you’d most want to plan). The classifier is now sourced from the canonical block list.
  • Plus a capture audit-hole fix and an O(N)→O(1) fix to the capture segment store’s read.

The full per-release detail is on each package’s CHANGELOG.md, linked from the changelog; the current shipped versions are on the status board. Nothing here changes the frozen 1.x API or the wire. It just makes the guarantees harder to break.