# Security Baseline — Release 02.01.00

## Trust boundary

Only `examcert_v2_public/` is reachable through Apache. All source code, `.env`, logs, sessions, database files, migrations, tests and private uploads are stored in the sibling `examcert/` directory.

## Request controls

1. Each request receives a cryptographically random request ID.
2. The host is checked against an exact allowlist before the router runs.
3. Staging/production HTTP GET and HEAD requests redirect to the configured HTTPS origin.
4. Non-idempotent HTTP requests received without HTTPS are rejected rather than replayed through a redirect.
5. POST, PUT, PATCH and DELETE requests require a session-bound CSRF token.
6. Route handlers must return a controlled `Response` object.
7. Header names/values are validated to block CRLF response splitting.

## Browser policy

Dynamic responses include:

- Content-Security-Policy with no default external origin
- HSTS over HTTPS
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `frame-ancestors 'none'`
- strict referrer policy
- cross-origin opener/resource isolation
- no-store cache policy
- permissions policy that permits camera, microphone and display capture only from the same origin, anticipating future proctoring

The CSP will be expanded only for specific reviewed services. Wildcard script or frame origins are not permitted.

## Sessions

- Files are stored under `storage/sessions` with mode `0700`.
- Cookies default to `Secure`, `HttpOnly`, `SameSite=Lax`.
- Strict mode and cookie-only sessions are forced.
- Session identifiers rotate periodically.
- Idle and absolute lifetimes are enforced server-side.
- User-agent binding provides a conservative session-theft signal without binding to IP address.
- Authentication will explicitly rotate the session ID again after successful login.

## Database

- PDO exception mode is enabled.
- Native prepared statements are enforced.
- Persistent connections and stringified fetches are disabled.
- Connection timezone is UTC.
- Credentials are read only from the private `.env` file.
- SQL identifiers and dynamic clauses must never be sourced directly from user input; prepared statements protect values, not identifiers.

## Logging

- Logs use one JSON record per line and UTC timestamps.
- Request bodies are not logged.
- Keys resembling passwords, secrets, tokens, authorization headers, cookies, API keys, private keys or sessions are redacted recursively.
- HTTP 4xx failures are logged without stack traces; server failures retain diagnostic traces outside the document root.
- Client IP logging is explicit and currently retained for up to 30 daily log files. A formal privacy/retention policy will be attached to the audit subsystem later in Phase 02.

## Deferred security controls

The following intentionally belong to subsequent Phase 02 steps:

- database-backed users, roles and permissions
- login throttling and temporary lockouts
- password reset and email verification
- active-session registry and remote revocation
- database audit trail with tamper-evident metadata
- secure file-upload validation and malware workflow
- encryption service using `APP_KEY`
- operational backup/restore automation
