feat(memory): sensitive 标记 + 提取器敏感判据,私事退出受限车道召回
M63(M60 审计 P0-1/P0-2)。作用域 ≠ 敏感度:`scope='user'` 是共享域,里 面却装着住址(花溪 64 条 active)/私称(叶酱 63)/作息(早睡 38),于是受限车 道(群聊/陌生人)把共享域整锅注入上下文 —— 2026-10-29 群 531082168 的住址泄漏 即此路径。本片给 memory_items 加 `sensitive` 列,把「这条归谁」(scope)与 「这条能不能外说」(sensitive)拆成两根正交的轴。 - 迁移 0028:加列(INTEGER NOT NULL DEFAULT 0)+ **同迁移幂等回填**(精确短语 白名单 花溪/叶酱/早睡,`AND sensitive=0`,不改 updated_at),down 只撤结构; memory 包内 `ensureSensitiveSchema` 同形前滚(任意 *sql.DB 自举)。 - 受限判据:新增 `MemoryItem.SharedVisible()` = 共享域 且 !sensitive,成为 restricted 侧唯一起点;`loop.FilterSharedVisible` 与复用它的 knowledge 工具 自动跟随。主人车道不过这道判据,照常读到全部记忆(sensitive 不是权限系统)。 - 提取器:prompt 追加 sensitive 位(住址/私人称呼/家人/健康/作息与行程 → true, 口味/兴趣/项目约定 → false,含正反例);产出侧与落库侧共用 `resolveSensitive`(模型的类目判断 ∨ 已实证短语白名单),只加标不撤标。 - 回填入口 `BackfillSensitive(ctx, db, dryRun)`:幂等、可 dry-run、返回候选池 前后规模与逐短语计数(生产快照实测 3116 → 2948,标 725 行)。 - 读路径并到 15 列(scanItem + 7 处 SELECT);store.go 拆分 store_insert.go 守住 500 行上限。 验收:go build/vet/test 全绿(memory + loop 单包复跑绿);删实现三处变异分别打红 (sensitiveColumn 恒 0 / SharedVisible 忽略 Sensitive / Extractor 跳过白名单); 生产库快照上跑 0028 后 Go 侧回填 marked=0(迁移 SQL 与 privateFacts 等价)。
This commit is contained in:
1 parent
a8bc2b4470
commit
44fbd29836
22 files changed
+1360
-102
No files matched your search
@@ -46,21 +46,27 @@ func scanItems(rows *sql.Rows, op string) ([]MemoryItem, error) {
|
||||
// retention_tier 是**第 14 列**(迁移 0026):它与 `kind` 是两根独立的轴,
|
||||
// 因此这里只做「读出来」,不参与任何推导。空串原样成为
|
||||
// RetentionTierUnset(= 尚未分型),绝不被折成某一档。
|
||||
//
|
||||
// sensitive 是**第 15 列**(迁移 0028):SQLite 的 INTEGER 0/1 在这里折回 bool。
|
||||
// 它被读出来的**唯一**理由是要给受限车道的可见性判据用(SharedVisible)——
|
||||
// 条目不带这一位,过滤就无从过滤;它不参与任何排名/判定。
|
||||
func scanItem(sc rowScanner) (MemoryItem, error) {
|
||||
var (
|
||||
it MemoryItem
|
||||
scope, kind, tier string
|
||||
tagsJSON string
|
||||
sensitive int
|
||||
createdAt, updatedAt string
|
||||
)
|
||||
if err := sc.Scan(&it.ID, &it.PersonaID, &it.RoleID, &it.ProjectID, &scope, &kind,
|
||||
&it.Content, &tagsJSON, &it.Confidence, &it.SourceConversation,
|
||||
&createdAt, &updatedAt, &it.DecayWeight, &tier); err != nil {
|
||||
&createdAt, &updatedAt, &it.DecayWeight, &tier, &sensitive); err != nil {
|
||||
return MemoryItem{}, err
|
||||
}
|
||||
it.Scope = Scope(scope)
|
||||
it.Kind = Kind(kind)
|
||||
it.RetentionTier = RetentionTier(tier)
|
||||
it.Sensitive = sensitive != 0
|
||||
if err := json.Unmarshal([]byte(tagsJSON), &it.Tags); err != nil {
|
||||
return MemoryItem{}, fmt.Errorf("memory: decode tags: %w", err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user