|
|
@@ -11,7 +11,7 @@
|
|
|
>
|
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
|
>
|
|
|
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (18 fixed, 9 open), 42 sev-1.
|
|
|
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (19 fixed, 8 open), 42 sev-1.
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -1010,6 +1010,28 @@
|
|
|
rate is `(perSecond) * N_replicas` per token behind a non-sticky
|
|
|
LB. Idle/revoked tokens linger forever until container restart.
|
|
|
- **Severity: 2**
|
|
|
+- **Status:** Fixed in `e09964b`. `RateLimiter` now caps the bucket map at a
|
|
|
+ configurable `maxBuckets` (default 10 000). Every `tryConsume()`
|
|
|
+ re-inserts the touched key at the end of the PHP array so insertion
|
|
|
+ order tracks LRU; on overflow the oldest entries get dropped in
|
|
|
+ batches of 256 so eviction amortises across requests instead of
|
|
|
+ running on every call once we're at steady state. A dropped bucket
|
|
|
+ comes back as a fresh full-capacity bucket on next access —
|
|
|
+ equivalent to the bucket having idled long enough to refill, so
|
|
|
+ eviction never grants more tokens than the configured rate would
|
|
|
+ already permit. The cap kills the unbounded-growth path and
|
|
|
+ short-circuits the "idle/revoked tokens linger forever" leak: once a
|
|
|
+ rotated/revoked token's bucket is the LRU front, the next eviction
|
|
|
+ drops it. The multi-replica half is a SPEC §10 topology constraint
|
|
|
+ (single-replica is the documented supported topology for the
|
|
|
+ limiter; horizontal `api` scaling requires sticky LB) and is tracked
|
|
|
+ separately as future scaling work to swap the in-process map for a
|
|
|
+ shared backend (Redis / DB). Regression tests in
|
|
|
+ `api/tests/Unit/Http/RateLimiterTest.php`
|
|
|
+ (`testBucketMapIsBoundedByMaxBucketsCap`,
|
|
|
+ `testEvictedBucketReturnsAtFullCapacityOnReuse`,
|
|
|
+ `testRecentlyTouchedKeyIsNotEvicted`,
|
|
|
+ `testMaxBucketsBelowEvictionBatchIsRejected`).
|
|
|
|
|
|
### F29 — `/api/v1/admin/*` group has no rate limit
|
|
|
- **File:** `api/src/App/AppFactory.php:188-337`
|