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

@@ -26,7 +26,7 @@ import type { BriefingFailureClass } from "@/lib/insights/briefing-failure-marke
*
* Why a POST under a `useQuery` rather than a dedicated GET endpoint:
* the route already cache-returns the most recent generation (24h TTL on
* `User.insightsCachedAt` / `User.insightsCachedText`) without burning a
* `User.insightsCachedAt` / `User.insightsCachedTextEncrypted`) without burning a
* rate-limit token, so a single POST-without-`force` is functionally a
* GET-or-generate. Adding a separate GET would duplicate the cache-read
* branch and split the audit-log surface; the reconcile report deferred
@@ -540,7 +540,7 @@ export function useInsightsAdvisorQuery(
// re-fetches.
queryClient.invalidateQueries({ queryKey: queryKeys.insightsRoot() });
// v1.18.10 / v1.32.19 — the dashboard hero surfaces the briefing
// headline from the SNAPSHOT (server-lifted `User.insightsCachedText`),
// headline from the SNAPSHOT (server-lifted `User.insightsCachedTextEncrypted`),
// and the Today hero's lead line is the SAME briefing lifted into the
// digest — neither is this advisor cache. A regenerate rewrites that
// server cache, so both the snapshot and the digest must refetch.