# Security controls

## Secrets and data

Set `TOKEN_HASH_KEY`, `ACCESS_CODE_HASH_KEY`, and `ADMIN_TOTP_ENCRYPTION_KEY` to three independently generated random 32-byte values encoded in Base64. Use a managed secret store in production. The SQL URL, TOTP encryption key, and signing public key are runtime configuration, never source code. The signing private key does not belong on the API host.

Access code, refresh token, access token, and admin session values are random opaque bearer secrets. SQL stores keyed HMAC-SHA-256 digests with unique constraints. Access codes have 125 bits of entropy, so a deliberately slow password hash is unnecessary; a secret HMAC key also protects against database-only offline guessing. Admin passwords use PBKDF2-HMAC-SHA-256 with 600,000 iterations, random per-password salts and 256-bit output. TOTP secrets are encrypted with AES-256-GCM. The Windows SDK uses the current user's Credential Manager vault for its token bundle; it does not write tokens to a normal configuration file.

The database stores pseudorandom per-installation UUIDs, app/OS versions, activation timestamps, and HMACs of source IPs. It does not collect MAC addresses, disk serials, hardware fingerprints, process lists or sensor readings. Define retention and deletion periods before production launch.

## API and browser

- Terminate HTTPS with TLS 1.2 or newer. HSTS, CSP, frame denial, no-sniff, referrer policy, secure admin cookies and same-origin restrictions are applied by the app.
- Keep PostgreSQL private; compose does not publish its port. Store artifacts on a private volume or bucket and never expose storage credentials.
- Configure CORS only for the exact website origins. Do not use wildcard origins with credentials.
- The admin area uses independent password plus TOTP authentication, RBAC, eight-hour session expiry, CSRF token plus Origin verification, login throttling and audit events.
- Configure the reverse proxy to forward client IP and HTTPS scheme only from trusted proxy addresses. Do not trust client-supplied forwarded headers directly.
- Put a WAF/CDN or distributed limiter in front of multi-instance APIs; the in-process limiter is per instance.

## Release chain

The server checks the publisher signature before publishing. Core must pin the publisher public key and verify both SHA-256 and ECDSA signature before installing. Never trust a hash delivered beside a package unless the signature verifies. Keep signing private keys offline, rotate them with a controlled client trust update, and audit all publishes.

The server cannot prevent a person with local access from copying an installed file. The design protects access, provenance, integrity and download authorization; it is not aggressive DRM.

## Operations

Alert on repeated failed activations, admin login failures, unexpected release changes, database errors, backup failures, storage growth, and rate-limit spikes. Audit records exclude plaintext access codes and tokens. Restrict audit access. Back up the database, packages and configuration separately, encrypt backups, and test restores.
