feat(chat): service-level sensitive gating + local sensitive marks
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>
This commit is contained in:
@@ -180,6 +180,14 @@ bool Settings::load(const std::string& path)
|
||||
(c.contains("name") && c["name"].is_string())
|
||||
? c["name"].get<std::string>() : std::string()});
|
||||
}
|
||||
if (j.contains("sensitive_chat_convs") && j["sensitive_chat_convs"].is_array()) {
|
||||
sensitive_chat_convs_.clear();
|
||||
for (const auto& c : j["sensitive_chat_convs"])
|
||||
if (c.is_object() && c.contains("cid") && c["cid"].is_string())
|
||||
sensitive_chat_convs_.push_back({c["cid"].get<std::string>(),
|
||||
(c.contains("name") && c["name"].is_string())
|
||||
? c["name"].get<std::string>() : std::string()});
|
||||
}
|
||||
// Chat-tab customization (re-clamped through the setters so hand-edited JSON stays in range).
|
||||
loadScalar(j, "chat_emoji_color", chat_emoji_color_);
|
||||
loadScalar(j, "chat_poll_rate_sec", chat_poll_rate_sec_); setChatPollRateSec(chat_poll_rate_sec_);
|
||||
@@ -544,6 +552,13 @@ bool Settings::save(const std::string& path)
|
||||
o["name"] = b.name;
|
||||
j["blocked_chat_convs"].push_back(o);
|
||||
}
|
||||
j["sensitive_chat_convs"] = json::array();
|
||||
for (const auto& s : sensitive_chat_convs_) {
|
||||
json o;
|
||||
o["cid"] = s.cid;
|
||||
o["name"] = s.name;
|
||||
j["sensitive_chat_convs"].push_back(o);
|
||||
}
|
||||
j["chat_emoji_color"] = chat_emoji_color_;
|
||||
j["chat_poll_rate_sec"] = chat_poll_rate_sec_;
|
||||
j["chat_bubble_style"] = chat_bubble_style_;
|
||||
|
||||
Reference in New Issue
Block a user