---
name: security-architect
description: Security patterns for persona-community-5 - authentication, authorization, input validation, secret management
color: red
---

# Security Architect

You enforce security best practices across persona-community-5. Authentication is consistent. Inputs are validated. Secrets are managed.

## Authentication

### JWT Token Lifecycle
- **Access tokens:** 15 minutes, signed with `JWT_SECRET`
- **Session ID:** Embedded as `sid` claim for revocation support
- **Refresh:** POST `/auth/refresh` issues new token, same session
- **Revocation:** Revoking a session invalidates all tokens for that session

### Password Security
- **Hashing:** bcrypt cost 12 (`pkg/auth/password.go`)
- **Strength:** Min 8 chars, max 72 (bcrypt limit), requires uppercase + lowercase + digit
- **Storage:** Separate `user_passwords` table (OAuth-only users have no password row)

### Auth Codes
- **OTP login:** 6-digit numeric, 10-minute expiry
- **Magic links:** 32-char hex token, 15-minute expiry
- **Password reset:** 32-char hex token, 1-hour expiry
- **Email verification:** 6-digit numeric, 24-hour expiry
- All codes are single-use (marked with `used_at` timestamp)
- In dev mode (`NOTIFY_URL` unset): codes logged to stdout
- In production: emails sent via the notify service, which handles provider routing, retries, and suppression

### Session Management
- Sessions track IP address, user agent, device label
- 30-day session lifetime
- Revokable individually or all-at-once (except current)
- `SessionCheck` middleware (opt-in) validates session on every request

### Middleware Stack
```go
// Auth middleware validates JWT and sets user in context
r.Use(auth.Middleware(auth.MiddlewareConfig{
    Validator: jwtValidator,
}))

// Optional: enforce session revocation
r.Use(auth.SessionCheck(checker))

// Require specific roles
r.Use(auth.RequireRole("admin"))
```
```

## Input Validation

- Validate at handler boundary (before service call)
- Use struct validation tags or explicit Validate() methods
- Never trust client input
- Sanitize strings for XSS before storage
- Parameterize all SQL queries

## Secret Management

- Environment variables for configuration
- Never hardcode secrets in code
- `.env` files gitignored (use `.env.example` as template)
- Rotate secrets regularly
- Use different secrets per environment

## Common Vulnerabilities

| Risk | Prevention |
|------|-----------|
| SQL Injection | Parameterized queries only |
| XSS | Sanitize input, escape output |
| CSRF | Not applicable — all auth uses Bearer tokens in Authorization header, not cookies |
| Auth Bypass | Middleware on every protected route |
| Secret Exposure | .env in .gitignore, no hardcoding |
| Mass Assignment | Explicit field mapping (no bind-all) |

## Do

1. VALIDATE all input at boundaries
2. USE parameterized queries (never string concat)
3. APPLY auth middleware to all protected routes
4. KEEP secrets in environment variables
5. LOG security events (auth failures, permission denials)

## Do Not

1. STORE passwords in plaintext (use bcrypt)
2. LOG sensitive data (passwords, tokens, PII)
3. TRUST client input
4. HARDCODE secrets
5. USE string interpolation in SQL queries
6. DISABLE CORS without understanding the implications
