refactor(insights): drop the readable cached-text column

Every write has gone to insights_cached_text_encrypted since 0411, and
the boot-time free-text backfill sealed the rows written before it.
Migration 0430 drops insights_cached_text and the backfill index that
served it. A host that skipped the intervening releases loses only a
cache of model output; the next warm writes a fresh, sealed payload.

The cipher module now reads and writes the sealed column only, the
backfill job loses its insights step, and consent withdrawal, the wipe
plan, the backup plan and the session projection follow the schema.
Backups never carried the column, and restore ignores unknown account
settings; a round-trip test now proves an old backup naming the field
still restores cleanly. The access guard pins exact counts for where
the sealed name may appear. Fixtures, the demo seed and the demo
migration script seed the sealed column instead of plaintext.
This commit is contained in:
Marc-André Bombeck committed 2026-10-21 19:24:21 +02:00
1 parent 45da8ae971
commit 9941db1549
49 files changed
+381 -497

No files matched your search

+2 -2
View File
@@ -327,7 +327,7 @@ readonly USERS_COLS="id, username, email, password_hash, role, created_at, updat
height_cm, date_of_birth, gender, timezone,
codex_access_token_encrypted, codex_refresh_token_encrypted, codex_token_expires_at,
codex_connected_at, codex_connection_status,
insights_privacy_mode, insights_cached_at, insights_cached_text, insights_cached_text_encrypted,
insights_privacy_mode, insights_cached_at, insights_cached_text_encrypted,
insights_exclude_metrics,
global_excluded_injection_sites,
telegram_bot_token, telegram_chat_id, telegram_enabled,
@@ -360,7 +360,7 @@ readonly USERS_SELECT="id, username, email, password_hash,
NULL::timestamptz AS codex_token_expires_at,
NULL::timestamptz AS codex_connected_at,
'disconnected' AS codex_connection_status,
insights_privacy_mode, insights_cached_at, insights_cached_text, insights_cached_text_encrypted,
insights_privacy_mode, insights_cached_at, insights_cached_text_encrypted,
insights_exclude_metrics,
global_excluded_injection_sites,
NULL::text AS telegram_bot_token,
+1 -3
View File
@@ -3555,15 +3555,13 @@ async function seed() {
await client.query(
`UPDATE users
SET insights_cached_text_encrypted = $2,
insights_cached_text = NULL,
insights_cached_at = NOW(),
insights_snapshot_hash = $3,
insights_briefing_reroll_date = $4
WHERE id = $1`,
[
userId,
// Sealed like every write since v1.43.7; the app never reads the
// readable column while a ciphertext is there.
// Sealed like every write since v1.43.7.
Buffer.from(
sealInsightsCachedText(JSON.stringify(comprehensiveInsight)),
),