feat(v1.1.8): F1 drop plaintext realtime_signing_key (migration 0032)
v1.1.7 added at-rest encryption for app_secrets.realtime_signing_key
plus a startup task that backfilled encryption over the plaintext
column. v1.1.7's CHANGELOG committed v1.1.8 to dropping the
plaintext column; this commit follows through.
Migration 0032:
* Guard query: refuses to apply if any row still has
realtime_signing_key IS NOT NULL but realtime_signing_key_encrypted
IS NULL. Forces operators who skipped v1.1.7 to apply it first.
* ALTER TABLE app_secrets DROP COLUMN IF EXISTS
realtime_signing_key.
app_secrets_repo:
* decode_signing_key now reads encrypted+nonce only; the plaintext
fallback is gone. (The schema still allows it via DROP IF EXISTS
semantics on replay; once dropped, the column doesn't exist —
the SELECT no longer requests it.)
* Removed migrate_plaintext_keys (the v1.1.7 startup sweep).
* Tests for the falls-back-to-plaintext path are gone with it; the
remaining tests cover the encrypted-only happy path, the
missing-columns None case, and the wrong-master-key Crypto error.
picloud/lib.rs: removed the migrate_plaintext_keys startup call
+ replaced with a comment explaining the upgrade-path requirement.
LOAD-BEARING: v1.1.8 requires v1.1.7 to have been applied first.
Operators upgrading directly from v1.1.6 or earlier must apply
v1.1.7 (which performs the encryption pass) before applying v1.1.8.
This is enforced both by the migration guard and by the CHANGELOG
(in a later commit).
Brief mentioned dropping a "realtime_signing_key_nonce_LEGACY_IF_EXISTS"
column — recon confirmed migration 0025 only added the plaintext
column + the encrypted/nonce pair, so no legacy nonce column exists
to drop. Documented in HANDBACK §7.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
-- v1.1.8 F1 — drop the plaintext realtime_signing_key column.
|
||||
--
|
||||
-- v1.1.7 added at-rest encryption (migration 0025) and a startup task
|
||||
-- that backfilled encryption over the plaintext column. Once every
|
||||
-- existing row has an encrypted counterpart, the plaintext column is
|
||||
-- pure dead weight (and a footgun: anyone with DB-read access can
|
||||
-- still read the signing key for any app that lived through the
|
||||
-- migration).
|
||||
--
|
||||
-- The guard refuses to drop if any row still has a plaintext value
|
||||
-- without an encrypted counterpart. This makes the migration safe to
|
||||
-- replay and forces operators who skipped v1.1.7 to apply it first:
|
||||
-- the v1.1.7 startup task is the only thing that knows how to
|
||||
-- encrypt the existing plaintext rows.
|
||||
--
|
||||
-- Operators upgrading from v1.1.6 or earlier MUST apply v1.1.7
|
||||
-- first (and let its startup encryption sweep complete) before
|
||||
-- applying this migration. The CHANGELOG and HANDBACK make this
|
||||
-- mandatory; the guard below is the belt-and-suspenders.
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM app_secrets
|
||||
WHERE realtime_signing_key IS NOT NULL
|
||||
AND realtime_signing_key_encrypted IS NULL
|
||||
) THEN
|
||||
RAISE EXCEPTION
|
||||
'v1.1.8 migration 0032 refused: unencrypted realtime_signing_key rows still present. Apply v1.1.7 first and ensure its startup encryption sweep has completed.';
|
||||
END IF;
|
||||
END$$;
|
||||
|
||||
ALTER TABLE app_secrets DROP COLUMN IF EXISTS realtime_signing_key;
|
||||
Reference in New Issue
Block a user