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:
Kelly
2025-12-10 19:01:44 -07:00
parent 9aefb554bc
commit 1fb0eb94c2
2 changed files with 48 additions and 1 deletions

View File

@@ -119,7 +119,42 @@ npx tsx src/db/migrate.ts
- Importing it at runtime causes startup crashes if env vars aren't perfect - 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 - `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:** **Quick Start:**
```bash ```bash
@@ -452,6 +487,7 @@ const result = await pool.query(`
16. **Running `lsof -ti:PORT | xargs kill`** or similar process-killing commands 16. **Running `lsof -ti:PORT | xargs kill`** or similar process-killing commands
17. **Using hardcoded database names** in code or comments 17. **Using hardcoded database names** in code or comments
18. **Creating or connecting to a second database** 18. **Creating or connecting to a second database**
19. **Creating API routes without authMiddleware** (all `/api/*` routes MUST be protected)
--- ---

View File

@@ -7,10 +7,17 @@
* Routes are prefixed with /api/analytics/v2 * Routes are prefixed with /api/analytics/v2
* *
* Phase 3: Analytics Engine + Rec/Med by State * 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 { Router, Request, Response } from 'express';
import { Pool } from 'pg'; import { Pool } from 'pg';
import { authMiddleware } from '../auth/middleware';
import { PriceAnalyticsService } from '../services/analytics/PriceAnalyticsService'; import { PriceAnalyticsService } from '../services/analytics/PriceAnalyticsService';
import { BrandPenetrationService } from '../services/analytics/BrandPenetrationService'; import { BrandPenetrationService } from '../services/analytics/BrandPenetrationService';
import { CategoryAnalyticsService } from '../services/analytics/CategoryAnalyticsService'; import { CategoryAnalyticsService } from '../services/analytics/CategoryAnalyticsService';
@@ -36,6 +43,10 @@ function parseLegalType(legalType?: string): LegalType {
export function createAnalyticsV2Router(pool: Pool): Router { export function createAnalyticsV2Router(pool: Pool): Router {
const router = 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 // Initialize services
const priceService = new PriceAnalyticsService(pool); const priceService = new PriceAnalyticsService(pool);
const brandService = new BrandPenetrationService(pool); const brandService = new BrandPenetrationService(pool);