Wires the sensitive-conversation plumbing into ChatService + Settings:
- Settings gains a persisted local sensitive set (isChatSensitive /
setChatSensitive / sensitiveChatConversations), mirroring the blocked set, for
INSTANT effect the moment the user marks a conversation (before the on-chain
signal is harvested back).
- ChatService::isConversationSensitive() OR-combines that local mark with the
on-chain reduction, and setPersistence() wires it as the DB's per-row key
selector (sensitive rows -> vault key).
- ingest() withholds a sensitive conversation's messages while the vault key is
absent (fail-closed: not shown, not persisted); they re-import + persist under
the vault key once it is unlocked and a scan runs. loadFromDatabase() already
withholds via the DB's two-key try.
Service-tested end to end against a real ChatDatabase (ingest + reload).
Phase B, step 4 (service gating). App vault lifecycle + UI next.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>