| Credential / Key | Rotation Frequency | Trigger for Immediate Rotation |
|---|---|---|
| MariaDB table-encryption master key (keyfile) | Annually | Suspected compromise of the keyfile or host — highest-priority key, protects all patient PHI at rest |
| Database root password (MariaDB) | Annually | Suspected breach; personnel change |
| Cadence .env DB_PASS | Annually | Suspected breach; shared credential exposure |
| Cloudflare API Token | Annually | Token exposure; access revocation needed |
| Cloudflare Tunnel Token | On compromise suspicion | Unauthorized tunnel access detected |
| Resend API Key | Annually | Unexpected usage spikes; suspected leak |
| Backblaze B2 Application Key | Annually | Suspected exposure |
| GPG Backup Encryption Key | Every 2 years | Key material suspected compromised |
| PHP Session Secret (SESSION_NAME) | Annually | Session fixation attack detected |
| Cadence user API keys (per-user) | On user request or departure | User reports key compromise |
| Server SSH keys | On personnel change | SSH key suspected compromised |
This is the keyfile at /mnt/user/appdata/mariadb-<instance>/config/encryption/keyfile that the file_key_management plugin uses to encrypt every InnoDB tablespace (all patient PHI tables, per migration 0168_encrypt_all_tables.sql). This is the single highest-value key in the system — compromise means every table it protects is exposed. Rotation is more involved than a password change: the old key must remain available and valid until every page it encrypted has been re-encrypted under the new key, or that data becomes permanently unreadable.
file_key_management plugin documentation for the exact keyfile format in use, since this has changed across MariaDB releases.SHOW STATUS LIKE 'Innodb_encryption%' / INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION that the server recognizes the new key version.innodb_encryption_rotate_key_age so the background encryption threads re-encrypt existing tablespace pages onto the new key version over time, rather than requiring a manual full re-encrypt.INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION until all tablespaces report the new key version (`CURRENT_KEY_VERSION`) as current — do not remove the old key version from the keyfile until this is confirmed for every table.Each client deployment runs its own isolated MariaDB container alongside its own SWAG reverse proxy, on that client's own hardware — repeat this procedure per deployment, substituting the container names and host address for that client.
docker exec -it MariaDB-<instance> mariadb -u root -pALTER USER 'root'@'%' IDENTIFIED BY 'new_password';/mnt/user/appdata/swag-<instance>/webroot/.env — set DB_PASS to new passworddocker restart swag-<instance>.env file: update SESSION_NAME to a new unique string.envgpg --gen-keyUsers can manage their own API keys from Cadence Settings → API Keys. Administrators can see which keys exist but cannot view the actual key values. On departure or compromise:
| Date | Credential Rotated | Rotated By | Reason |
|---|---|---|---|
| Jun 29, 2026 | Initial documentation of rotation schedule | Jacob Russell | Policy establishment |