feat(rate-limit): read the per-flow limits from system config - #310
Merged
Merged
Conversation
13 tasks
The OTP, magic link and OAuth limiters carried their values as constants: 10 OTP sends and 20 magic links per IP per 15 minutes, 5 per address, 30 OAuth starts per IP and 10 per provider. Those suit a web audience and refuse a mobile one, because carriers put thousands of subscribers behind one IPv4 address. The six limiters read flow_rate_limits from system config, an object whose defaults are exactly those constants, so an instance that sets nothing behaves as it did. express-rate-limit takes the limit as a function but the window only as a number, so one limiter is built per configured window on first use; a changed limit applies on the next request. @seamless-auth/types moves to 0.22.0 for the key. Docs gain a native and mobile clients section in api-contract.md, a flow rate limits section in configuration.md, and the client SDK packages in ecosystem.md.
Bccorb
force-pushed
the
feat/flow-rate-limits
branch
from
September 13, 2026 16:22
84be3dc to
bf85910
Compare
Bccorb
marked this pull request as ready for review
September 13, 2026 16:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part of the mobile track (fells-code/seamless-templates#40). On the published
@seamless-auth/types0.22.0; the lockfile carries it as of the last commit.What changes
src/middleware/rateLimit.ts: the six flow limiters (otpIpLimiter,otpIdentityLimiter,magicLinkIpLimiter,magicLinkEmailLimiter,oauthIpLimiter,oauthProviderLimiter) readflow_rate_limitsfrom system config instead of carrying constants.express-rate-limittakes the limit as a function but the window only as a number, socreateFlowLimiterbuilds one limiter per configuredwindowSecondson first use and keeps it; a changed limit takes effect on the next request, a changed window starts fresh counters. Key generators and the JSON 429 body are unchanged.SYSTEM_CONFIG_DEFAULTS.flow_rate_limits = DefaultFlowRateLimits,SYSTEM_CONFIG_ENV_MAP.flow_rate_limits = 'FLOW_RATE_LIMITS', JSON parse case,.env.exampleentry.bootstrapSystemConfigseeds the row on next boot for an existing instance, so no migration.openapi.json/src/generated/api.tsregenerated: the system config routes gain the key.otp.perIp: 10refuses a phone audience at modest scale while never troubling a web one. Operators raiseperIpand leaveperIdentityalone. Defaults are exactly the previous constants, so nothing changes for a deployment that sets nothing.Docs
docs/api-contract.md: new Native and mobile clients section: RP ID andoriginsfor iOS (https://<rpid>) and Android (android:apk-key-hash:<base64url>), keep the web origin first, magic link and OAuth destinations for apps, the tenant-wide session lifetime caveat, refresh reuse detection, authenticator policy defaults.docs/configuration.md: table row plus a Flow rate limits section.docs/ecosystem.md:@seamless-auth/clientand@seamless-auth/react-nativejoin@seamless-auth/reactas Tier 1 dependents (one repo, three packages).Contract-affecting per CLAUDE.md: a new system config key. Dependents:
@seamless-auth/types(done in #68), admin dashboard (renders system config; unknown keys are additive), server adapter passes the system config PATCH through untouched.Test plan
npm run typecheck,npm run lint,npm run check:changeset-bumpnpm run test:run: 1472 passing (rate limiter suite rewritten for lazy, config-driven limiters: historical defaults per limiter, per-flow override, live limit change without rebuild, one limiter per window, key generators, JSON refusal body across all eight limiters)npm run generate:apicommittednpm installafter the types release to update the lockfile, then ready for review