mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
fix(rate-limit): fail the shared write ceiling open and skip reads over POST
The shared write bucket threw on any SQL error, so a lock on rate_limits answered every authenticated write with 500. It is a loop cutter, not an access check: when the bucket cannot be read the write now goes ahead with a warn signal. The login and other auth-surface limits call the limiter directly and still fail closed. requireAuth now passes readOverPost to the meter, the draft-only document assist declares it, and the three chat routes, which meter their turns with buckets of their own, declare that instead of being counted twice.
This commit is contained in:
1 parent
408ae35b7c
commit
5185edca74
12 files changed
+148
-19
No files matched your search
@@ -398,14 +398,15 @@ paths:
|
||||
"429": &a12
|
||||
description: "Rate limit exceeded. This route shares one per-account bucket with every other authenticated write —
|
||||
`record-write:<accountId>`, 300 requests per 60 seconds — keyed on the ACTING account, so a delegate burns
|
||||
their own allowance rather than the record owner's. Only the bulk ingest endpoints, which meter themselves
|
||||
with a dedicated bucket, stay outside it. Nothing was written. `meta.errorCode` is
|
||||
`record_write.rate_limited`, which is what tells this refusal apart from a route's own narrower bucket when
|
||||
both can answer 429. The `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`
|
||||
headers describe that bucket; back off on `Retry-After` rather than guessing. Every request counts against
|
||||
the bucket, refused ones included: the check runs before the body is read, so a client looping on a 422
|
||||
spends the same allowance as one that writes rows. A client with more than a handful of rows to send should
|
||||
use the batch endpoint for its domain instead of looping this one."
|
||||
their own allowance rather than the record owner's. Only the routes that meter themselves with a dedicated
|
||||
bucket (the bulk ingest endpoints and the model-turn chats) and a POST that writes nothing stay outside it.
|
||||
If the bucket cannot be read, the write goes ahead unmetered rather than failing. Nothing was written.
|
||||
`meta.errorCode` is `record_write.rate_limited`, which is what tells this refusal apart from a route's own
|
||||
narrower bucket when both can answer 429. The `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`
|
||||
and `X-RateLimit-Reset` headers describe that bucket; back off on `Retry-After` rather than guessing. Every
|
||||
request counts against the bucket, refused ones included: the check runs before the body is read, so a
|
||||
client looping on a 422 spends the same allowance as one that writes rows. A client with more than a handful
|
||||
of rows to send should use the batch endpoint for its domain instead of looping this one."
|
||||
headers: *a8
|
||||
content:
|
||||
application/json:
|
||||
|
||||
Reference in new issue
Block a user