Implements tasks T026-T032 from specs/002-saas-integration/tasks.md
(User Story 3, P3 - the final piece of this feature) plus Polish.
- New bespoke Redis fixed-window counter (checkRateLimit,
src/infrastructure/cache/rate-limiter.ts) rather than
@fastify/rate-limit's default onRequest-stage hook -- that hook
runs before this feature's preHandler-based auth resolves the
integration/user identity the limit needs to key on. A second
preHandler (checkIntegrationRateLimit) runs after
authenticateProductIntegration on the inbound route, checking the
integration-level limit then the per-user limit independently,
each throwing the existing RateLimitError (429
RATE_LIMIT_EXCEEDED) on breach.
- New integration test (inbound-rate-limit.test.ts) verifies both
limits are enforced independently against a real Postgres/Redis:
a throttled user doesn't affect others, and the integration cap
throttles even when no individual user has hit their own limit.
- Docs: contracts/quickstart updated from the placeholder
"RATE_LIMITED" code to the actual reused RATE_LIMIT_EXCEEDED code;
cleaned up a duplicated paragraph in the admin endpoints section;
added a "SaaS Integration" section to README.md documenting the
inbound contract, admin routes (and their known auth-stub
limitation), and how rate limits are configured.
All 32 tasks in tasks.md are now complete -- all three user stories
(P1 trust boundary, P2 admin lifecycle, P3 rate limiting) are
implemented and covered by integration tests verified against a
live database, in addition to unit tests for the crypto/token
primitives. Full quality gate (typecheck/lint/format/architecture/
unit tests) passes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>