# Fix Unprotected Tracking Endpoints Plan

## Problem
`/api/intelligence/*` and `/api/frontend/*` endpoints have no rate limiting beyond the global 300/min limit. These endpoints write to the database on every call, making them vulnerable to:

1. **DoS attacks** - Flood database with fake tracking events
2. **Database bloat** - `track-batch` accepts unlimited array sizes
3. **Cost attacks** - Fill Supabase storage quota with garbage data

**Affected Endpoints:**
| Endpoint | Current Limit | Risk Level |
|----------|---------------|------------|
| `POST /api/intelligence/track` | 300/min (global) | HIGH |
| `POST /api/intelligence/track-batch` | 300/min (global) | **CRITICAL** |
| `POST /api/frontend/vitals` | 300/min (global) | MEDIUM |
| `POST /api/frontend/error` | 300/min (global) | MEDIUM |
| `GET /api/intelligence/*` | 300/min (global) | LOW |

## Why No Auth?
These endpoints intentionally skip auth because:
- Frontend tracking happens before/without user login
- Error tracking must work even when auth fails
- Usage analytics need to capture anonymous visitors

**No auth is correct, but rate limiting is required.**

## Solution

### 1. Add Dedicated Tracking Limiter
Add to `src/middleware/rateLimiter.js`:

```javascript
/**
 * Tracking endpoints - public but rate limited
 * Higher than strict, lower than global
 */
const trackingLimiter = rateLimit({
  ...baseOptions,
  windowMs: 60 * 1000, // 1 minute
  max: 60, // 60 tracking requests per minute per IP
  message: { error: 'Tracking rate limit exceeded' },
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: ipKeyGenerator, // IP-based since no auth
});

/**
 * Batch tracking - very restrictive
 * Prevents bulk insert abuse
 */
const trackingBatchLimiter = rateLimit({
  ...baseOptions,
  windowMs: 60 * 1000, // 1 minute
  max: 10, // 10 batch requests per minute per IP
  message: { error: 'Batch tracking rate limit exceeded' },
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: ipKeyGenerator,
});
```

### 2. Apply Limiters in index.js
Change lines 142-143 from:
```javascript
app.use('/api/intelligence', intelligenceRoutes);
app.use('/api/frontend', frontendTrackingRoutes);
```

To:
```javascript
app.use('/api/intelligence', trackingLimiter, intelligenceRoutes);
app.use('/api/frontend', trackingLimiter, frontendTrackingRoutes);
```

### 3. Add Array Size Limit to track-batch
In `src/routes/intelligence.js`, add validation:

```javascript
router.post('/track-batch', async (req, res) => {
  const { events } = req.body;

  // Limit array size to prevent bulk abuse
  const MAX_BATCH_SIZE = 50;
  if (!events || !Array.isArray(events)) {
    return res.status(400).json({ error: 'events array is required' });
  }
  if (events.length > MAX_BATCH_SIZE) {
    return res.status(400).json({
      error: `Maximum ${MAX_BATCH_SIZE} events per batch`,
      received: events.length
    });
  }
  // ... rest of handler
```

## Database Migration
None required.

## API Endpoints
No new endpoints - modifying existing rate limits.

## UI Components
None - backend only change.

## Implementation Steps
- [x] Phase 1: Add `trackingLimiter` and `trackingBatchLimiter` to rateLimiter.js ✅
- [x] Phase 2: Export new limiters from rateLimiter.js ✅
- [x] Phase 3: Import and apply in index.js for intelligence and frontend routes ✅
- [x] Phase 4: Add MAX_BATCH_SIZE validation to track-batch endpoint ✅
- [ ] Phase 5: Test rate limiting works (should get 429 after 60 requests) - QA

## Build Progress

### ✅ All Code Changes Complete
**Commit:** 5b118ab "Add rate limiting to tracking endpoints"
**Pushed:** main branch

**Files changed:**
- `src/middleware/rateLimiter.js` - Added trackingLimiter (60/min) and trackingBatchLimiter (10/min)
- `src/index.js` - Applied trackingLimiter to /api/intelligence and /api/frontend
- `src/routes/intelligence.js` - Added MAX_BATCH_SIZE = 50 validation

## Success Criteria
1. `POST /api/intelligence/track` returns 429 after 60 requests/minute from same IP
2. `POST /api/intelligence/track-batch` returns 429 after 10 requests/minute
3. `POST /api/intelligence/track-batch` with 100+ events returns 400 error
4. Legitimate frontend tracking still works (normal usage is <10 events/minute)

## Notes for Builder

### Files to Modify:
1. `src/middleware/rateLimiter.js`
   - Add `trackingLimiter` (60/min per IP)
   - Add `trackingBatchLimiter` (10/min per IP)
   - Export both new limiters

2. `src/index.js`
   - Import `trackingLimiter` from rateLimiter
   - Apply to `/api/intelligence` route
   - Apply to `/api/frontend` route

3. `src/routes/intelligence.js`
   - Add `MAX_BATCH_SIZE = 50` constant
   - Add array length validation in `track-batch` handler

### Rate Limit Values:
| Limiter | Window | Max | Per |
|---------|--------|-----|-----|
| trackingLimiter | 1 min | 60 | IP |
| trackingBatchLimiter | 1 min | 10 | IP |

These values are generous for legitimate use but prevent abuse.

## Notes for QA
1. Test with curl from same IP:
   ```bash
   # Should work
   for i in {1..60}; do curl -X POST https://yourapp/api/intelligence/track -H "Content-Type: application/json" -d '{"event_type":"test","event_name":"test"}'; done

   # 61st should return 429
   curl -X POST https://yourapp/api/intelligence/track ...
   ```

2. Test batch size limit:
   ```bash
   # Should fail with 400
   curl -X POST .../track-batch -d '{"events":[...100 items...]}'
   ```

3. Verify frontend tracking still works normally

## Why This Matters
Without these limits, an attacker could:
- Insert millions of fake events, bloating the database
- Trigger expensive queries by flooding with data
- Exhaust Supabase row limits or storage quotas
- Cause legitimate tracking to fail due to resource exhaustion

With these limits:
- Max 60 events/min per IP = 86,400 events/day per IP (still plenty)
- Max 10 batch requests/min × 50 events = 500 batch events/min
- Legitimate apps won't hit these limits
- Attackers get blocked quickly
