Auto-commit 2026-05-02 09:37
This commit is contained in:
67
plans/FRE-4522-rate-limit-config.md
Normal file
67
plans/FRE-4522-rate-limit-config.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# FRE-4522 - Update spamshield.config.ts with per-minute + daily rate limit structure
|
||||
|
||||
## Parent Issue
|
||||
FRE-4507 - Implement Redis rate limiting middleware
|
||||
|
||||
## Goal ID
|
||||
2c5a8678-b505-4e9c-8ec4-c41faa9626ff
|
||||
|
||||
## Description
|
||||
Update the `spamshield.config.ts` file to include per-minute AND daily rate limit structure for each subscription tier.
|
||||
|
||||
### Current State
|
||||
The current `spamshield.config.ts` only has single value rate limits:
|
||||
```typescript
|
||||
export const spamRateLimits = {
|
||||
BASIC: 100,
|
||||
PLUS: 500,
|
||||
PREMIUM: 2000,
|
||||
} as const;
|
||||
```
|
||||
|
||||
### Required Changes
|
||||
Refactor `spamRateLimits` to include both per-minute and daily limits:
|
||||
|
||||
```typescript
|
||||
export const spamRateLimits = {
|
||||
BASIC: { perMinute: 100, perDay: 1000 },
|
||||
PLUS: { perMinute: 500, perDay: 5000 },
|
||||
PREMIUM: { perMinute: 2000, perDay: 20000 },
|
||||
} as const;
|
||||
```
|
||||
|
||||
### Type Definition
|
||||
Add type definition for the rate limit structure:
|
||||
```typescript
|
||||
export interface TierRateLimits {
|
||||
perMinute: number;
|
||||
perDay: number;
|
||||
}
|
||||
|
||||
export type SubscriptionTierRateLimits = Record<SubscriptionTier, TierRateLimits>;
|
||||
```
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Update `spamRateLimits` to include `perMinute` and `perDay` properties
|
||||
- [ ] Add `TierRateLimits` interface definition
|
||||
- [ ] Update `SubscriptionTierRateLimits` type
|
||||
- [ ] Ensure type safety with `as const` assertion
|
||||
- [ ] All existing imports/exports continue to work
|
||||
|
||||
## File to Modify
|
||||
`services/spamshield/src/config/spamshield.config.ts`
|
||||
|
||||
## Priority
|
||||
HIGH (Blocker for FRE-4523 - middleware depends on config structure)
|
||||
|
||||
## Status
|
||||
done
|
||||
|
||||
## Assigned To
|
||||
d20f6f1c-1f24-4405-a122-2f93e0d6c94a (Founding Engineer)
|
||||
|
||||
## Dependencies
|
||||
- None (foundational config change)
|
||||
|
||||
## Notes
|
||||
This is the first child issue in the FRE-4507 implementation sequence. The config structure must be updated before the middleware can be implemented.
|
||||
74
plans/FRE-4523-rate-limit-middleware.md
Normal file
74
plans/FRE-4523-rate-limit-middleware.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# FRE-4523 - Create spam-rate-limit.middleware.ts using Redis service
|
||||
|
||||
## Parent Issue
|
||||
FRE-4507 - Implement Redis rate limiting middleware
|
||||
|
||||
## Goal ID
|
||||
2c5a8678-b505-4e9c-8ec4-c41faa9626ff
|
||||
|
||||
## Description
|
||||
Create a new `spam-rate-limit.middleware.ts` file that implements Redis-backed rate limiting for the SpamShield service using the existing Redis service from `packages/shared-notifications/`.
|
||||
|
||||
### Requirements
|
||||
The middleware should:
|
||||
1. Use the RedisService from `@shieldai/shared-notifications`
|
||||
2. Implement per-minute AND daily rate limit tracking
|
||||
3. Check rate limits before processing spam classification requests
|
||||
4. Return appropriate HTTP 429 responses when limits are exceeded
|
||||
5. Support tier-based rate limiting (BASIC, PLUS, PREMIUM)
|
||||
|
||||
### Rate Limit Keys
|
||||
Use Redis key patterns:
|
||||
- Per-minute: `ratelimit:spam:{userId}:{tier}:min:{timestamp}`
|
||||
- Per-day: `ratelimit:spam:{userId}:{tier}:day:{date}`
|
||||
|
||||
Where:
|
||||
- `timestamp` = current minute (Date.now() / 60000)
|
||||
- `date` = current date (YYYY-MM-DD)
|
||||
|
||||
### Expected Behavior
|
||||
```typescript
|
||||
// Check rate limit before processing
|
||||
const rateLimitCheck = await rateLimitMiddleware.checkLimit(userId, tier);
|
||||
|
||||
if (rateLimitCheck.exceeded) {
|
||||
// Return 429 with retry-after header
|
||||
return reply.code(429).send({
|
||||
error: 'Rate limit exceeded',
|
||||
limit: rateLimitCheck.limit,
|
||||
remaining: rateLimitCheck.remaining,
|
||||
resetAt: rateLimitCheck.resetAt,
|
||||
});
|
||||
}
|
||||
|
||||
// Continue with spam classification
|
||||
```
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Create `services/spamshield/src/middleware/spam-rate-limit.middleware.ts`
|
||||
- [ ] Import and use RedisService from `@shieldai/shared-notifications`
|
||||
- [ ] Implement `checkLimit(userId, tier)` method returning rate limit status
|
||||
- [ ] Implement `incrementCounter(userId, tier)` method
|
||||
- [ ] Support per-minute and per-day limit tracking
|
||||
- [ ] Return proper rate limit metadata (remaining, resetAt, limit)
|
||||
- [ ] Handle Redis connection errors gracefully
|
||||
- [ ] Export middleware class and factory function
|
||||
|
||||
## File to Create
|
||||
`services/spamshield/src/middleware/spam-rate-limit.middleware.ts`
|
||||
|
||||
## Dependencies
|
||||
- FRE-4522 (spamshield.config.ts with rate limit structure)
|
||||
- `@shieldai/shared-notifications` (RedisService)
|
||||
|
||||
## Priority
|
||||
HIGH (Core middleware implementation)
|
||||
|
||||
## Status
|
||||
done
|
||||
|
||||
## Assigned To
|
||||
d20f6f1c-1f24-4405-a122-2f93e0d6c94a (Founding Engineer)
|
||||
|
||||
## Notes
|
||||
This middleware will be integrated into the spam classification pipeline to enforce rate limits before processing requests.
|
||||
134
plans/FRE-4524-spamshield-routes.md
Normal file
134
plans/FRE-4524-spamshield-routes.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# FRE-4524 - Create spamshield.routes.ts with spam classification endpoints
|
||||
|
||||
## Parent Issue
|
||||
FRE-4507 - Implement Redis rate limiting middleware
|
||||
|
||||
## Goal ID
|
||||
2c5a8678-b505-4e9c-8ec4-c41faa9626ff
|
||||
|
||||
## Description
|
||||
Create a new `spamshield.routes.ts` file that exposes spam classification API endpoints with rate limit middleware integration.
|
||||
|
||||
### Required Endpoints
|
||||
|
||||
#### POST /api/v1/spam/classify/sms
|
||||
Classify an SMS message as spam or not spam.
|
||||
|
||||
**Request Body:**
|
||||
```typescript
|
||||
{
|
||||
phoneNumber: string; // E.164 format
|
||||
message: string;
|
||||
userId: string;
|
||||
tier: 'BASIC' | 'PLUS' | 'PREMIUM';
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```typescript
|
||||
{
|
||||
isSpam: boolean;
|
||||
score: number;
|
||||
features: string[];
|
||||
rateLimit: {
|
||||
remaining: number;
|
||||
resetAt: Date;
|
||||
limit: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Rate Limit:** Applied via spam-rate-limit.middleware.ts
|
||||
|
||||
#### POST /api/v1/spam/classify/call
|
||||
Classify a call based on metadata and context.
|
||||
|
||||
**Request Body:**
|
||||
```typescript
|
||||
{
|
||||
phoneNumber: string; // E.164 format
|
||||
callMetadata: {
|
||||
duration?: number;
|
||||
timeOfDay?: string;
|
||||
frequency?: number;
|
||||
};
|
||||
userId: string;
|
||||
tier: 'BASIC' | 'PLUS' | 'PREMIUM';
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```typescript
|
||||
{
|
||||
decision: 'BLOCK' | 'FLAG' | 'ALLOW';
|
||||
confidence: number;
|
||||
reasons: string[];
|
||||
rateLimit: {
|
||||
remaining: number;
|
||||
resetAt: Date;
|
||||
limit: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Rate Limit:** Applied via spam-rate-limit.middleware.ts
|
||||
|
||||
#### GET /api/v1/spam/rate-limit/status
|
||||
Get current rate limit status for a user.
|
||||
|
||||
**Query Parameters:**
|
||||
- `userId`: string (required)
|
||||
- `tier`: 'BASIC' | 'PLUS' | 'PREMIUM' (required)
|
||||
|
||||
**Response:**
|
||||
```typescript
|
||||
{
|
||||
userId: string;
|
||||
tier: string;
|
||||
currentLimits: {
|
||||
perMinute: {
|
||||
used: number;
|
||||
limit: number;
|
||||
remaining: number;
|
||||
resetAt: Date;
|
||||
};
|
||||
perDay: {
|
||||
used: number;
|
||||
limit: number;
|
||||
remaining: number;
|
||||
resetAt: Date;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Create `services/spamshield/src/routes/spamshield.routes.ts`
|
||||
- [ ] Implement POST /api/v1/spam/classify/sms endpoint
|
||||
- [ ] Implement POST /api/v1/spam/classify/call endpoint
|
||||
- [ ] Implement GET /api/v1/spam/rate-limit/status endpoint
|
||||
- [ ] Integrate spam-rate-limit.middleware.ts for classification endpoints
|
||||
- [ ] Return rate limit metadata in responses
|
||||
- [ ] Handle 429 responses when limits exceeded
|
||||
- [ ] Proper TypeScript typing for request/response objects
|
||||
- [ ] Export route registrar function
|
||||
|
||||
## File to Create
|
||||
`services/spamshield/src/routes/spamshield.routes.ts`
|
||||
|
||||
## Dependencies
|
||||
- FRE-4522 (spamshield.config.ts with rate limit structure)
|
||||
- FRE-4523 (spam-rate-limit.middleware.ts)
|
||||
- `@shieldai/types` (for type definitions)
|
||||
|
||||
## Priority
|
||||
MEDIUM (Depends on middleware implementation)
|
||||
|
||||
## Status
|
||||
todo
|
||||
|
||||
## Assigned To
|
||||
d20f6f1c-1f24-4405-a122-2f93e0d6c94a (Founding Engineer)
|
||||
|
||||
## Notes
|
||||
Routes should follow the existing pattern in `packages/api/src/routes/` for consistency. The spamshield service routes will be registered in the API gateway.
|
||||
97
plans/FRE-4525-rate-limit-tests.md
Normal file
97
plans/FRE-4525-rate-limit-tests.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# FRE-4525 - Add rate limit tests
|
||||
|
||||
## Parent Issue
|
||||
FRE-4507 - Implement Redis rate limiting middleware
|
||||
|
||||
## Goal ID
|
||||
2c5a8678-b505-4e9c-8ec4-c41faa9626ff
|
||||
|
||||
## Description
|
||||
Add comprehensive unit and integration tests for the spam rate limiting functionality across the config, middleware, and routes.
|
||||
|
||||
### Test Coverage Requirements
|
||||
|
||||
#### 1. Config Tests (spamshield.config.test.ts)
|
||||
- [ ] Test `spamRateLimits` structure has correct perMinute and perDay values
|
||||
- [ ] Test BASIC tier: 100/min, 1000/day
|
||||
- [ ] Test PLUS tier: 500/min, 5000/day
|
||||
- [ ] Test PREMIUM tier: 2000/min, 20000/day
|
||||
- [ ] Test type safety with `as const` assertion
|
||||
- [ ] Test `TierRateLimits` interface compatibility
|
||||
|
||||
#### 2. Middleware Tests (spam-rate-limit.middleware.test.ts)
|
||||
- [ ] Test rate limit check for BASIC tier (per-minute)
|
||||
- [ ] Test rate limit check for BASIC tier (per-day)
|
||||
- [ ] Test rate limit check for PLUS tier (per-minute)
|
||||
- [ ] Test rate limit check for PLUS tier (per-day)
|
||||
- [ ] Test rate limit check for PREMIUM tier (per-minute)
|
||||
- [ ] Test rate limit check for PREMIUM tier (per-day)
|
||||
- [ ] Test counter increment functionality
|
||||
- [ ] Test rate limit reset after minute boundary
|
||||
- [ ] Test rate limit reset after day boundary
|
||||
- [ ] Test 429 response when limit exceeded
|
||||
- [ ] Test retry-after header calculation
|
||||
- [ ] Test Redis connection error handling
|
||||
- [ ] Test key pattern generation
|
||||
|
||||
#### 3. Route Tests (spamshield.routes.test.ts)
|
||||
- [ ] Test POST /api/v1/spam/classify/sms with valid request
|
||||
- [ ] Test POST /api/v1/spam/classify/sms with rate limit header
|
||||
- [ ] Test POST /api/v1/spam/classify/call with valid request
|
||||
- [ ] Test POST /api/v1/spam/classify/call with rate limit header
|
||||
- [ ] Test GET /api/v1/spam/rate-limit/status returns correct data
|
||||
- [ ] Test 429 response on classification endpoints when rate limited
|
||||
- [ ] Test rate limit metadata in successful responses
|
||||
- [ ] Test tier-based rate limit enforcement
|
||||
|
||||
#### 4. Integration Tests (spam-rate-limit.integration.test.ts)
|
||||
- [ ] End-to-end rate limit flow with mock Redis
|
||||
- [ ] Concurrent request handling
|
||||
- [ ] Rate limit key expiration
|
||||
- [ ] Multiple users with different tiers
|
||||
- [ ] Cross-day rate limit reset
|
||||
- [ ] Cross-minute rate limit reset
|
||||
|
||||
### Test Files to Create
|
||||
1. `services/spamshield/test/spamshield.config.test.ts`
|
||||
2. `services/spamshield/test/spam-rate-limit.middleware.test.ts`
|
||||
3. `services/spamshield/test/spamshield.routes.test.ts`
|
||||
4. `services/spamshield/test/spam-rate-limit.integration.test.ts`
|
||||
|
||||
### Mock Requirements
|
||||
- Mock RedisService for unit tests
|
||||
- Mock SpamShieldService for route tests
|
||||
- Use vitest for test framework (existing in project)
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] All config tests pass (5 tests)
|
||||
- [ ] All middleware tests pass (13 tests)
|
||||
- [ ] All route tests pass (8 tests)
|
||||
- [ ] All integration tests pass (6 tests)
|
||||
- [ ] Minimum 90% code coverage for rate limiting code
|
||||
- [ ] Tests follow existing test patterns in `services/spamshield/test/`
|
||||
- [ ] Use vitest framework with proper mocking
|
||||
|
||||
## Files to Create
|
||||
- `services/spamshield/test/spamshield.config.test.ts`
|
||||
- `services/spamshield/test/spam-rate-limit.middleware.test.ts`
|
||||
- `services/spamshield/test/spamshield.routes.test.ts`
|
||||
- `services/spamshield/test/spam-rate-limit.integration.test.ts`
|
||||
|
||||
## Dependencies
|
||||
- FRE-4522 (spamshield.config.ts)
|
||||
- FRE-4523 (spam-rate-limit.middleware.ts)
|
||||
- FRE-4524 (spamshield.routes.ts)
|
||||
- `vitest` (existing test framework)
|
||||
|
||||
## Priority
|
||||
LOW (Can be implemented in parallel with routes, but depends on middleware)
|
||||
|
||||
## Status
|
||||
todo
|
||||
|
||||
## Assigned To
|
||||
d20f6f1c-1f24-4405-a122-2f93e0d6c94a (Founding Engineer)
|
||||
|
||||
## Notes
|
||||
Tests should be written to validate the complete rate limiting flow. Integration tests require a running Redis instance or mock.
|
||||
Reference in New Issue
Block a user