# Security Plan

## 1. Authentication

- Passwords hashed with **Argon2id** (`password_hash($pw, PASSWORD_ARGON2ID)`), CI4 default bcrypt acceptable fallback if Argon2 unavailable on host — never MD5/SHA1/plain.
- Optional TOTP-based 2FA (`two_factor_enabled`, secret stored encrypted).
- Session: CI4 native session driver backed by DB or Redis (not file, for multi-server readiness); `session.cookie_httponly=1`, `session.cookie_secure=1` (HTTPS-only), `SameSite=Lax`.
- API auth: short-lived JWT access token (15 min) + long-lived refresh token (30 days, rotated on use, revocable via `api_tokens.revoked_at`).
- Account lockout: 5 failed logins → 15-minute lockout, logged to `login_history` with `status='failed'`.

## 2. Authorization

- Defense in depth: Route filter (`RoleGuard`) + Service-layer permission check (`PermissionService::can()`) + Tenant scope filter — a bug in one layer doesn't expose data, because the others still enforce.
- Super Admin cross-tenant queries require an explicit `withoutTenantScope()` call, itself gated behind `role_slug === 'super_admin'` at the repository level (impossible to accidentally call from an agency-scoped controller).

## 3. Input Validation & Injection Prevention

- **SQL Injection:** 100% Query Builder / parameterized queries via CI4's `Query Builder` and `Model`; raw queries banned by code-review checklist, and where unavoidable (complex reporting queries) must use bound parameters (`?` placeholders), never string concatenation.
- **XSS:** CI4 auto-escaping in views (`esc()`), CSP header (`Content-Security-Policy`) restricting inline scripts, all user-generated rich text (job descriptions, agency bio) sanitized server-side with an allow-list HTML purifier before storage.
- **CSRF:** CI4 CSRF filter enabled globally for all state-changing web routes (POST/PUT/DELETE), token rotated per request; API routes use bearer-token auth instead (stateless, CSRF N/A per OWASP guidance for token-based APIs).
- **File upload validation:** MIME-type + extension allow-list (resumes: pdf/doc/docx; images: jpg/png/webp), max size enforced server-side, files renamed to random UUIDs on storage (never trust original filename for path), stored outside web-root where possible or served through a controller that re-checks ownership/permission on every download — never a directly browsable upload directory for private documents (resumes, verification docs).
- **Mass assignment:** CI4 Entities with explicit `$allowedFields` per model — no blind `$_POST` dumping into `save()`.

## 4. Rate Limiting

- Redis token-bucket (primary) or DB-backed `rate_limit_hits` (fallback) per user/IP/API-key.
- Tiered limits: auth endpoints (login/register) stricter (e.g. 10/min/IP) to blunt credential stuffing; search endpoints moderate (30/min); general API 60/min.
- 429 responses include `Retry-After` header.

## 5. Data Protection

- **Encryption at rest:** payment gateway secrets, SMTP password, and any stored API keys in `settings.value` are encrypted using CI4's `Encryption` library (AES-256) before storage (`is_encrypted` flag), decrypted only in-memory when the Service needs to call the gateway.
- **PII minimization:** candidate privacy controls (`hide_email`, `hide_mobile`, `hide_employer`) enforced at the **query/serialization layer** (API resource transformer strips fields), not just hidden in the UI — an agency without an unlock cannot retrieve raw contact fields via the API even by inspecting network requests.
- **Transport:** HTTPS enforced (HSTS header), HTTP requests redirected.
- **Backups:** encrypted daily DB backups (mysqldump → gpg-encrypted → offsite storage), retention policy configurable in deployment (see Deployment Guide).

## 6. Activity Monitoring & Device Tracking

- Every login records IP, device, browser into `login_history`.
- `user_devices` fingerprints recognize new devices; a login from an unrecognized device triggers an email alert ("New login from Lahore, Pakistan — was this you?") — reuses the Notification Engine, not a bespoke system.
- `activity_logs` (see SaaS Architecture §6) provides the forensic trail for security investigations independent of billing usage tracking.

## 7. Session Management

- Idle timeout (configurable, default 2 hours web / access-token expiry for API).
- "Log out all devices" action revokes all `api_tokens` for the user and destroys server-side sessions.
- Privilege changes (password change, role change, 2FA toggle) invalidate all other active sessions/tokens immediately.

## 8. Webhook Security

- All payment gateway webhooks verified via provider signature (Stripe signing secret, PayPal webhook verification API, HMAC for JazzCash/Easypaisa) **before** any DB write; unverified payloads rejected with 400 and logged (not silently dropped, so tampering attempts are visible in audit).
- Idempotency: webhook events deduped by `gateway_transaction_id` to prevent double-crediting on retry delivery.

## 9. Multi-Tenant Isolation Testing

- Automated test suite includes a dedicated "tenant leak" test class: for every tenant-scoped table, attempt cross-tenant read/write as Agency B against Agency A's records and assert 403/empty-result — run in CI on every PR touching a Repository or Controller.

## 10. Dependency & Infra Hardening

- `composer audit` / `npm audit` in CI pipeline, blocking merge on high/critical CVEs.
- `.env` never committed (`.gitignore`), secrets injected via deployment environment, not baked into images.
- Admin panel accessible at a non-guessable path option (configurable), plus optional IP allow-list for `/admin/*` at the web-server level (documented in Deployment Guide, not enforced in-app since that's infra-layer).
- Security headers baseline: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy: strict-origin-when-cross-origin`, CSP as above.
