Migrations and upgrades

Copy Markdown View Source

This page states the release stance for OSS v0.1.0 and future upgrades.

OSS v0.1.0 stance

OSS v0.1.0 is treated as a new-install release.

Do not assume compatibility with private/internal/pre-release KMS database schemas unless a migration is explicitly documented for that source version.

Session-protected aliases

Migration 20260906000000_create_kek_wrappings adds keks.protection, makes keks.master_key nullable, and creates kek_wrappings on SQLite and PostgreSQL. Existing rows default to "rmk"; their key material and application ciphertext remain unchanged. New aliases created with a session store recipient envelopes and leave master_key empty.

SQLite cannot alter a column, so this migration rebuilds the keks table with foreign keys temporarily disabled, then verifies PRAGMA foreign_key_check. It runs outside a DDL transaction. Back up the database file and its -wal/-shm sidecars first, as with any SQLite schema change.

Behavior changes:

  • Principal sessions creating new aliases now create cryptographically protected aliases and receive creator bindings. Implicit creation through encrypt_alias/3 also requires kek.create.
  • Passphrase sessions no longer provide unrestricted alias access. They need a matching envelope on a session-protected alias. Existing passphrase sessions can still be used for new envelopes created for their passphrase.
  • Existing RMK-only aliases are not auto-converted. create_alias/2 with a session refuses to claim them; existing principal binding-based encrypt/decrypt access remains supported.
  • create_principal/2 now enforces a supplied session's principal.create permission against the new principal's reference/tags, locally and over HTTP. The no-options bootstrap call is unchanged.
  • Protected aliases cannot use the legacy KMS.Keks.rotate_kek/2 operation, which would discard their recipient protection.

Run the migration on the KMS authority before deploying clients using the new API. For a stronger boundary on existing data, migrate to a new protected alias explicitly and account for old RMK-only copies/backups. No private Formfix schema migration is implied.

Do not roll old code back over protected data. Migration downgrade refuses while session-protected aliases exist, because dropping their envelopes would destroy access. Use a tested matching backup/restore plan instead. See Factor-bound aliases.

Before upgrade

For any deployment:

  1. back up KMS database;
  2. back up RMK material separately;
  3. back up application ciphertext rows;
  4. test restore in an isolated environment;
  5. read release notes and migration notes;
  6. run migrations before serving traffic.

SQLite upgrades

SQLite deployments must preserve:

  • main DB file;
  • WAL/SHM sidecars when present;
  • file permissions;
  • RMK key file.

Recommended flow:

systemctl stop my-kms-service
cp /var/lib/kms/kms.sqlite3 /backup/kms.sqlite3
cp /var/lib/kms/kms.sqlite3-wal /backup/kms.sqlite3-wal 2>/dev/null || true
cp /var/lib/kms/kms.sqlite3-shm /backup/kms.sqlite3-shm 2>/dev/null || true
cp /var/lib/kms/rmk.key /backup/rmk.key
mix ecto.migrate
systemctl start my-kms-service

Use your normal snapshot tooling in production. The example shows required material, not a full backup design.

PostgreSQL upgrades

Use standard database backup and migration practice:

pg_dump ... > kms_backup.sql
mix ecto.migrate

Keep RMK material outside the database backup and restore plan it separately.

RMK provider changes

Do not switch RMK providers for existing data without a rewrap/migration plan.

External RMK ciphertext envelopes include provider/key references. Provider mismatch fails closed.

Safe provider migration needs:

  1. old provider still available;
  2. decrypt/unwrap old RMK-protected material;
  3. re-encrypt under new provider;
  4. verify representative decrypts;
  5. only then remove old provider access.

Alias/AAD compatibility

Aliases and AAD are part of your application data contract.

Changing alias naming or AAD construction can make old ciphertext undecryptable unless you keep compatibility code.

Recommended:

  • version AAD prefixes for large app changes;
  • keep old AAD constructors for old rows;
  • migrate ciphertext deliberately if row identifiers or field names change.

Session compatibility

Sessions are short-lived bearer credentials. Prefer letting old sessions expire naturally during upgrades.

If session verifier format changes, KMS may support old verifiers temporarily so existing sessions can expire. Do not rely on sessions as long-term state.

Rollback

Rollback is safest before migrations.

After migrations:

  • restore DB backup if schema downgrade is not supported;
  • restore matching RMK material;
  • invalidate sessions if session state may be inconsistent;
  • run representative decrypt checks before serving traffic.

Release note expectations

Each release should state:

  • database migrations included;
  • RMK ciphertext format changes, if any;
  • session/factor format changes, if any;
  • deprecated config/env vars;
  • required operator action;
  • validation matrix.