feat(webapp): share rate limit bucket across additional API keys per environment - #4508
Conversation
🦋 Changeset detectedLatest commit: e9ae728 The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A number passed to `expirationTime` is a Unix timestamp in seconds, not milliseconds as the JSDoc claimed. Following the old docs produced a token that effectively never expired. Also fail loudly when an additional API key reaches a local self-signing fallback. Those keys are not the environment's JWT signing material, so the token would never verify. Every endpoint that returns a public access token sets `x-trigger-jwt`, so this is unreachable today.
The API key policy methods are optional on the plugin-facing controller contract, so `Pick` over it yields optional members that these call sites would have to guard. Both already receive the LazyController singleton, which has substituted its fail-closed defaults, so point them at HostRbacController and keep the call sites guard-free.
Require both the global issuance switch and organization rollout flag before creating additional keys, while leaving existing credentials available for use and revocation. Show nullable creators and identify SDK v4.5.8 as the first compatible public-token version.
Record bounded outcomes for additional key creation, policy preparation, revocation, and public-token minting.
ba817b9 to
316db63
Compare
@trigger.dev/build
trigger.dev
@trigger.dev/core
@trigger.dev/python
@trigger.dev/react-hooks
@trigger.dev/redis-worker
@trigger.dev/rsc
@trigger.dev/schema-to-json
@trigger.dev/sdk
commit: |
Use environment identifiers when displaying remaining API capacity and ignore additional keys tied to deleted projects.
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
316db63 to
cd2a0c0
Compare
eb0e8f7 to
e9ae728
Compare
What
Rate-limit the API by environment rather than per API key.
Previously the limiter keyed its bucket on the hash of the full
Authorizationheader — one bucket per key. With additional environment API keys (tr_*_sk_*), an environment can mint many keys and each got its own full bucket, so more keys = higher effective rate limit. This collapses all of an environment's keys onto a single shared per-environment bucket, so the ceiling is exactly the configured limit regardless of key mix.How
authorizationRateLimitMiddlewarenow lets the override return{ config?, identifier? }.identifier, when present, is the rate limit bucket key; otherwise it falls back to the hashedAuthorizationheader (unchanged legacy behavior, still used byengineRateLimiterand any unauthenticated fallthrough).apiRateLimiter's override resolves the environment id and uses it as the identifier:isAdditionalApiKey) resolve via a newresolveAdditionalApiKeyRateLimitScope()— a scope-agnostic keyHash → (environmentId, org limiter config) lookup. It is deliberately permissive (restricted keys resolve too) because it's used only for bucketing, never as an auth decision — request auth still goes through the RBAC bearer controller, which enforces scopes. Revoked/expired keys are excluded so they can't hold a bucket warm.authenticateAuthorizationHeaderand key onenvironment.idtoo.Behavior notes
Tests
{ config }return shape.Base:
feat/multi-keys-surface. Closes TRI-12888.