feat: 数据删除机制(purge 物理清空 + 报告页隐私区块 + 删后回同意门)+ 测试桩补 purge

This commit is contained in:
Jayway Liu
2026-10-04 07:42:47 +08:00
parent ade1f719e1
commit e022faf975
14 changed files with 330 additions and 14 deletions
+15 -3
View File
@@ -1,14 +1,18 @@
import type { ChoiceBehavior, DimensionTag, FollowUpDimension, IdentityProfile } from './types';
/**
* 选择/讲述事件存储(ADR-0004:历史不可涂改)。
* 接口只有 append 和 list —— 刻意不提供 update/delete,
* 选择/讲述事件存储(ADR-0004:历史不可涂改,删除权完整保留)。
* 接口只有 append / list / purge —— 刻意不提供单条 update/delete,
* 让"不允许单独编辑历史选择"成为类型层面的约束,而非约定。
* purge 是《个人信息保护法》数据删除权(账号注销语义)下的整库物理清空,
* 不是对单条历史的修改;append-only 纪律不变。
*/
export interface EventStore {
append(event: StoryEvent): Promise<void>;
/** 列出事件;传 sessionId 则只看该轨迹 */
list(sessionId?: string): Promise<StoryEvent[]>;
/** 整库物理清空(含 consent 存证);删除后应用回到未同意状态 */
purge(): Promise<void>;
}
/** 一次重玩 = 一条新轨迹(新 sessionId),旧事件原样保留 */
@@ -72,10 +76,18 @@ export class LocalStorageEventStore implements EventStore {
const all: StoryEvent[] = raw ? (JSON.parse(raw) as StoryEvent[]) : [];
return sessionId ? all.filter((e) => e.sessionId === sessionId) : all;
}
async purge(): Promise<void> {
try {
localStorage.removeItem(STORAGE_KEY);
} catch {
// 隐私模式等场景:静默降级(与 list 一致)
}
}
}
/**
* Tauri 原生端实现:见 ./sqliteEventStore.ts(tauri-plugin-sql + SQLite,
* 同一 EventStore 接口,SQL 层同样只写 INSERT/SELECT)。
* 同一 EventStore 接口,SQL 层同样无单条 UPDATE/DELETE;整库清空只走 purge)。
* 运行时选择在 App.tsx:window.__TAURI__ 存在用 SqliteEventStore,否则 localStorage。
*/