Encryption at rest
Sensitive fields stored in the platform database are encrypted using AES-256-GCM before being written to disk.
| What | How |
|---|---|
| Tenant API keys (Anthropic, OpenAI-compat., SMTP) | AES-256-GCM, MASTER_ENCRYPTION_KEY |
| User password hashes | bcrypt (cost 12) |
| BYOD connection strings | AES-256-GCM, MASTER_ENCRYPTION_KEY |
| IMAP / email channel credentials | AES-256-GCM, MASTER_ENCRYPTION_KEY |
| Database files on disk | MySQL InnoDB tablespace on encrypted volume TODO: confirm full-disk encryption status with ops |
The MASTER_ENCRYPTION_KEY is injected via the server environment at boot time and is never written to the codebase or database. Rotation requires a re-encryption run and is documented in the ops runbook. TODO: link ops runbook once published
Encryption in transit
- All public endpoints served over HTTPS only; HTTP is redirected to HTTPS (Apache HSTS header).
- Minimum TLS version: TLS 1.3 (TLS 1.0 / 1.1 disabled).
- Widget widget.js is served with Access-Control-Allow-Origin: * but the chat API endpoints validate widget_key + origin allowlist.
- Internal service calls (Redis, MySQL on localhost) communicate over the loopback interface. No data leaves the host unencrypted.
Backups
The following backup schedule applies to the platform database and tenant databases:
| Item | Frequency | Retention | Location |
|---|---|---|---|
| Platform DB (einstein_saas_platform) | Daily, overnight (UTC, automated) | 7 daily backups (rolling) | Local volume + encrypted offsite replica |
| Tenant DBs (einstein_saas_tenant_*) | Daily, overnight (UTC, automated) | 7 daily backups (rolling) | Local volume + encrypted offsite replica |
| Uploaded files / document store | Daily, overnight (UTC, automated) | 7 daily backups (rolling) | Local volume + encrypted offsite replica |
Backups run per database via mysqldump --single-transaction, are stored compressed and age-encrypted, replicated to a separate offsite volume, and every run is checked for a non-empty dump and logged with success/failure status.
Backup archives are encrypted at rest with age (X25519 / ChaCha20-Poly1305); the decryption key is held separately from the archives. Fields protected with column-level encryption (AES-256-GCM) stay encrypted inside every archive. Recoverability is verified by an automated monthly restore-test.
Access control
4.1 Role-based access control (RBAC)
Every portal user is assigned a role. Roles carry granular permissions (51+ individual flags). The platform enforces permission checks server-side on every API endpoint.
4.2 Two-factor authentication
- 2FA via TOTP (RFC 6238 — Google Authenticator, Authy, etc.) is mandatory for the owner role and is enforced at login.
- Account owners can enforce 2FA for all team members via the settings panel.
- Backup recovery codes are generated at enrolment and must be stored securely by the user.
4.3 Tenant isolation
Authentication requires a tenant context (slug-based login). Session tokens are scoped to a single tenant. Cross-tenant resource access is prevented at the application layer by mandatory tenant_id filters on all queries.
Audit logging
Significant actions performed on platform resources are recorded in the audit_log table (platform database). Each entry captures:
- Actor: user ID, role and tenant ID.
- Action: verb (create, update, delete, login, export, …).
- Resource: entity type and ID.
- Metadata: changed field names and old/new values (sensitive fields redacted).
- Timestamp: stored in UTC (ISO 8601).
- IP address: source IP from the request.
Audit log entries are retained for 2 years. The log is append-only at the application level.
A dedicated insert-only database user (einstein_audit_writer) is used for audit writes, preventing modification or deletion of log entries by the application database user.
Vulnerability management
6.1 CVE monitoring
Composer dependencies are monitored via composer audit on every deployment pipeline run. Critical CVEs in runtime dependencies trigger an out-of-band patch within 72 hours of publication. TODO: confirm SLA with ops
6.2 Patch cycle
- OS security patches: applied during the weekly maintenance window. TODO: confirm window day/time with ops
- PHP runtime: kept at the latest stable minor release of the active branch (currently PHP 8.2.x).
- Web server: Apache 2.4.x — kept up to date with distribution security updates.
6.3 Responsible disclosure
External security researchers are invited to report vulnerabilities under our coordinated disclosure policy. Read the responsible disclosure policy →
Hosting & infrastructure
| Component | Detail |
|---|---|
| Hosting region | EU — Netherlands |
| Production server | dev01-aionized (Ubuntu) |
| Web server | Apache 2.4 (mod_rewrite, mod_ssl) |
| Runtime | PHP 8.2+ |
| Database | MySQL / MariaDB (platform + per-tenant) |
| Cache / sessions | Redis (loopback, password-protected) |
| Cross-border data transfers | None by default. Optional cloud-AI calls (Anthropic/OpenAI-compat.) are user-consent-gated and covered by Standard Contractual Clauses. |