# API Security

## Overview

This document describes the security measures implemented for Fire-OS API endpoints.

## Authentication

### Session-Based Authentication

All API routes require authentication via NextAuth.js sessions:

```typescript
// Every API route starts with auth check
const session = await auth();
if (!session?.user) {
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
```

### Session Properties
- Stored in httpOnly, secure cookies
- 24-hour expiration
- Rotated on each request
- Invalidated on password change

## Authorization

### Tenant Isolation

Every request is scoped to the user's authorized projects:

```typescript
// Get user's accessible projects
const userProjects = await getUserProjects(session.user.id);

// Query only within those projects
const data = await db
  .select()
  .from(customers)
  .where(inArray(customers.projectId, userProjectIds));
```

### Role-Based Access (Roadmap)

Future implementation will support:
- Owner: Full access
- Admin: Full access, team management
- Finance: Revenue and billing only
- Sales: Pipeline and customers only
- Support: Customer service only

## Input Validation

### Schema Validation

All inputs validated using Zod schemas:

```typescript
const createCustomerSchema = z.object({
  projectId: z.string().uuid(),
  primaryContactEmail: z.string().email(),
  primaryContactName: z.string().min(1).optional(),
  companyName: z.string().min(1),
});

const parsed = createCustomerSchema.safeParse(body);
if (!parsed.success) {
  return NextResponse.json(
    { error: 'Validation failed', details: parsed.error.flatten() },
    { status: 400 }
  );
}
```

### Validation Rules
- UUIDs validated for format
- Emails validated for format
- Strings trimmed and length-limited
- Numbers validated for range
- Enums validated against allowed values

## Rate Limiting

### Tier-Based Limits

Defined in `packages/core/src/config/tier-limits.ts`:

| Tier | API Calls/Hour | Concurrent Requests |
|------|---------------|---------------------|
| Free | 100 | 5 |
| Starter | 1,000 | 10 |
| Growth | 10,000 | 25 |
| Scale | 100,000 | 100 |
| Agency | Unlimited | Unlimited |

### Implementation
- Token bucket algorithm
- Sliding window rate limiting
- Headers indicate remaining quota:
  - `X-RateLimit-Limit`
  - `X-RateLimit-Remaining`
  - `X-RateLimit-Reset`

### Exceeded Response
```json
{
  "error": "Rate limit exceeded",
  "retryAfter": 3600
}
```
Status code: `429 Too Many Requests`

## Error Handling

### Secure Error Responses

Errors never expose:
- Stack traces
- Database queries
- Internal paths
- Configuration details

### Standard Error Format
```json
{
  "error": "Human-readable message",
  "code": "ERROR_CODE",
  "details": {}  // Optional, for validation errors
}
```

### Status Codes Used
| Code | Meaning |
|------|---------|
| 400 | Bad Request (validation failed) |
| 401 | Unauthorized (no session) |
| 403 | Forbidden (no access to resource) |
| 404 | Not Found |
| 409 | Conflict (duplicate resource) |
| 429 | Too Many Requests |
| 500 | Internal Server Error |

## Request Security

### Headers Required
- `Content-Type: application/json` for POST/PUT
- Session cookie (automatic via browser)

### Headers Returned
- `Content-Type: application/json`
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `Strict-Transport-Security: max-age=31536000`

### Request Size Limits
- JSON body: 1MB max
- File uploads: 10MB max
- Query string: 2KB max

## SQL Injection Prevention

### Drizzle ORM

All database queries use Drizzle ORM with parameterized queries:

```typescript
// Safe - parameterized
await db.select().from(customers).where(eq(customers.id, id));

// Never used - string concatenation
// await db.execute(`SELECT * FROM customers WHERE id = '${id}'`);
```

### Query Building
- No raw SQL from user input
- All values parameterized
- Type-safe query builders

## XSS Prevention

### Output Encoding
- React automatically escapes output
- No `dangerouslySetInnerHTML` without sanitization
- Content-Security-Policy headers configured

### Input Sanitization
- HTML stripped from text inputs
- URLs validated for allowed protocols
- File types validated on upload

## CSRF Protection

### SameSite Cookies
- All cookies set with `SameSite=Strict`
- Origin header validated for mutations
- No CORS wildcards

## API Versioning

### Current Version
- All endpoints unversioned (v1 implicit)
- Future breaking changes will use `/api/v2/`

### Deprecation Policy
- 6-month notice for deprecation
- Migration guides provided
- Old versions supported for 12 months

## Webhook Security

### Outgoing Webhooks
- Signed with HMAC-SHA256
- Signature in `X-Fire-OS-Signature` header
- Timestamp included to prevent replay

### Incoming Webhooks
- Signature verification required
- IP allowlist option
- Idempotency keys supported

## API Audit Logging

### Logged for Every Request
```json
{
  "timestamp": "2024-01-15T10:30:00Z",
  "method": "POST",
  "path": "/api/customers",
  "userId": "user_123",
  "projectId": "proj_456",
  "statusCode": 201,
  "duration": 45,
  "ip": "192.168.1.1"
}
```

### Not Logged
- Request/response bodies (privacy)
- Authentication tokens
- File contents

## Security Testing

### Automated
- SAST scanning in CI/CD
- Dependency vulnerability checks
- API fuzzing (quarterly)

### Manual
- Security code review for auth changes
- Penetration testing (annual)
- Bug bounty program (coming soon)

## Reporting Vulnerabilities

Found a security issue? Please report responsibly:

1. Email: security@fire-os.com
2. Include: Steps to reproduce, impact assessment
3. Do not: Disclose publicly before fix
4. We will: Acknowledge within 24 hours, fix critical issues within 72 hours
