fix(encryption): align stale account encrypted flags with plaintext names
A handful of legacy accounts are still flagged encrypted=true while their name is stored in plaintext (name_iv is null). The client-side decrypt- migration only clears the flag for accounts with an actually-encrypted name, so these stale flags never resolve and keep the user perpetually counted as "has encrypted accounts". Backfill the flag to match reality. Transaction decryption is unaffected: it is driven by each transaction's description_iv / notes_iv, not by this account flag.
This commit is contained in:
parent
51c4f1fdc5
commit
b581206a35
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Some legacy accounts are still flagged `encrypted = true` even though
|
||||
* their name is stored in plaintext (`name_iv` is null). The client-side
|
||||
* decrypt-migration only clears the flag for accounts whose name is
|
||||
* actually encrypted, so these stale flags would never resolve on their
|
||||
* own and keep the user perpetually counted as "has encrypted accounts".
|
||||
* Align the flag with reality: an account with no `name_iv` is not
|
||||
* encrypted. Transaction decryption is unaffected — it is driven by each
|
||||
* transaction's `description_iv` / `notes_iv`, not by this flag.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('accounts')
|
||||
->where('encrypted', true)
|
||||
->whereNull('name_iv')
|
||||
->update(['encrypted' => false]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Irreversible: once flipped, a migration-corrected account is
|
||||
* indistinguishable from an account that was always plaintext, so blanket
|
||||
* re-flagging would wrongly encrypt legitimately unencrypted accounts.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Account;
|
||||
|
||||
function runAlignEncryptedFlagMigration(): void
|
||||
{
|
||||
$migration = require database_path('migrations/2026_06_20_105609_align_accounts_encrypted_flag_with_plaintext_names.php');
|
||||
$migration->up();
|
||||
}
|
||||
|
||||
it('clears the encrypted flag only for accounts whose name is plaintext', function () {
|
||||
$staleFlag = Account::factory()->create(['encrypted' => true, 'name_iv' => null]);
|
||||
$encryptedName = Account::factory()->create(['encrypted' => true, 'name_iv' => str_repeat('a', 16)]);
|
||||
$alreadyPlaintext = Account::factory()->create(['encrypted' => false, 'name_iv' => null]);
|
||||
|
||||
runAlignEncryptedFlagMigration();
|
||||
|
||||
expect($staleFlag->fresh()->encrypted)->toBeFalse()
|
||||
->and($encryptedName->fresh()->encrypted)->toBeTrue()
|
||||
->and($alreadyPlaintext->fresh()->encrypted)->toBeFalse();
|
||||
});
|
||||
Loading…
Reference in New Issue