security: Add authMiddleware to analytics-v2 routes
- Add authMiddleware to analytics-v2.ts to require authentication - Add permanent rule #6 to CLAUDE.md: "ALL API ROUTES REQUIRE AUTHENTICATION" - Add forbidden action #19: "Creating API routes without authMiddleware" - Document authentication flow and trusted origins 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
38
CLAUDE.md
38
CLAUDE.md
@@ -119,7 +119,42 @@ npx tsx src/db/migrate.ts
|
||||
- Importing it at runtime causes startup crashes if env vars aren't perfect
|
||||
- `pool.ts` uses lazy initialization - only validates when first query is made
|
||||
|
||||
### 6. LOCAL DEVELOPMENT BY DEFAULT
|
||||
### 6. ALL API ROUTES REQUIRE AUTHENTICATION — NO EXCEPTIONS
|
||||
|
||||
**Every API router MUST apply `authMiddleware` at the router level.**
|
||||
|
||||
```typescript
|
||||
import { authMiddleware } from '../auth/middleware';
|
||||
|
||||
const router = Router();
|
||||
router.use(authMiddleware); // REQUIRED - first line after router creation
|
||||
```
|
||||
|
||||
**Authentication flow (see `src/auth/middleware.ts`):**
|
||||
1. Check Bearer token (JWT or API token) → grant access if valid
|
||||
2. Check trusted origins (cannaiq.co, findadispo.com, localhost, etc.) → grant access
|
||||
3. Check trusted IPs (127.0.0.1, ::1, internal pod IPs) → grant access
|
||||
4. **Return 401 Unauthorized** if none of the above
|
||||
|
||||
**NEVER create API routes without auth middleware:**
|
||||
- No "public" endpoints that bypass authentication
|
||||
- No "read-only" exceptions
|
||||
- No "analytics-only" exceptions
|
||||
- If an endpoint exists under `/api/*`, it MUST be protected
|
||||
|
||||
**When creating new route files:**
|
||||
1. Import `authMiddleware` from `../auth/middleware`
|
||||
2. Add `router.use(authMiddleware)` immediately after creating the router
|
||||
3. Document security requirements in file header comments
|
||||
|
||||
**Trusted origins (defined in middleware):**
|
||||
- `https://cannaiq.co`
|
||||
- `https://findadispo.com`
|
||||
- `https://findagram.co`
|
||||
- `*.cannabrands.app` domains
|
||||
- `localhost:*` for development
|
||||
|
||||
### 7. LOCAL DEVELOPMENT BY DEFAULT
|
||||
|
||||
**Quick Start:**
|
||||
```bash
|
||||
@@ -452,6 +487,7 @@ const result = await pool.query(`
|
||||
16. **Running `lsof -ti:PORT | xargs kill`** or similar process-killing commands
|
||||
17. **Using hardcoded database names** in code or comments
|
||||
18. **Creating or connecting to a second database**
|
||||
19. **Creating API routes without authMiddleware** (all `/api/*` routes MUST be protected)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,10 +7,17 @@
|
||||
* Routes are prefixed with /api/analytics/v2
|
||||
*
|
||||
* Phase 3: Analytics Engine + Rec/Med by State
|
||||
*
|
||||
* SECURITY: All routes require authentication via authMiddleware.
|
||||
* Access is granted to:
|
||||
* - Trusted origins (cannaiq.co, findadispo.com, etc.)
|
||||
* - Trusted IPs (localhost, internal pods)
|
||||
* - Valid JWT or API tokens
|
||||
*/
|
||||
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { Pool } from 'pg';
|
||||
import { authMiddleware } from '../auth/middleware';
|
||||
import { PriceAnalyticsService } from '../services/analytics/PriceAnalyticsService';
|
||||
import { BrandPenetrationService } from '../services/analytics/BrandPenetrationService';
|
||||
import { CategoryAnalyticsService } from '../services/analytics/CategoryAnalyticsService';
|
||||
@@ -36,6 +43,10 @@ function parseLegalType(legalType?: string): LegalType {
|
||||
export function createAnalyticsV2Router(pool: Pool): Router {
|
||||
const router = Router();
|
||||
|
||||
// SECURITY: Apply auth middleware to ALL routes
|
||||
// This gate ensures only authenticated requests can access analytics data
|
||||
router.use(authMiddleware);
|
||||
|
||||
// Initialize services
|
||||
const priceService = new PriceAnalyticsService(pool);
|
||||
const brandService = new BrandPenetrationService(pool);
|
||||
|
||||
Reference in New Issue
Block a user