regression: add chat.sendMessage rate limiter
Proposed changes (including videos or screenshots)
POST /v1/chat.sendMessage declared no rateLimiterOptions, so it fell back to the REST API default of 10 requests per 60 seconds — a default added in #11251 (2019) for machine-to-machine traffic.
When the web client's send flow moved from the sendMessage Meteor method to REST in #40675, it inherited that budget. The method had its own rule (5 messages per second, since 2015), so the allowance dropped from 300 to 10 messages per minute and the 11th message returned 429.
This declares the previous allowance on the endpoint, the same way users.setStatus does:
rateLimiterOptions: { numRequestsAllowed: 5, intervalTimeInMS: 1000 },
Issue(s)
Steps to test or reproduce
Requires a server started without TEST_MODE and with API_Enable_Rate_Limiter_Dev enabled — otherwise no rule is registered and no X-RateLimit-* headers are returned.
As a regular user without api-bypass-rate-limit:
- Send 12 messages ~300 ms apart → all
200. The 11th used to return429. - Send 10 messages as fast as possible → first 5
200, rest429. - Wait ~1 s and send again →
200. The window is 1 second, not 60. - Repeat step 2 with the
botrole → no rejections.
Further comments
The REST limiter buckets by IP address, not by user — the counter key is IPAddr + route, with no per-route way to change it. This allowance is therefore shared by everyone behind one address, unlike the Meteor rule, which was keyed by userId. Keying on userId would remove that ceiling, but it affects every route and is deliberately left out of this fix.
There's a follow up task to handle per user: CORE-2637
Summary by CodeRabbit
-
New Features
- Added rate limiting to chat message requests, allowing up to 5 requests per second.
- Authorized integrations can bypass limits when granted the appropriate permissions.
- API rate-limit bypasses now support route-specific permissions for more flexible access control.
-
Bug Fixes
- Improved rate-limit exemption handling to apply permissions consistently across API routes.
- Ensured users without the required permissions remain subject to configured request limits.