防窥膜解决不了的软件问题:桌面隐私保护状态机设计

2 阅读3分钟

防窥膜能缩小侧面可视角度,却管不了突然弹出的通知,也不能阻止人离开后别人继续操作电脑。超级看门狗 SuperWatchDog 是 Windows 本地隐私保护工具,使用用户预设的自动触发处理有人突然靠近、来不及操作电脑,以及离开电脑后没有及时保护三类情况,并提供本地加密文件保险箱。

从桌面程序的角度看,“防窥”至少跨越当前画面、登录会话和本地文件三个软件状态。把它做成一个 bool isPrivate,很快会碰到无法解释的中间态。

一个布尔值为什么不够

下面几种状态都可能同时成立:

窗口仍显示          true / false
Windows 会话可操作  true / false
私密文件仍被打开    true / false
用户仍在电脑前      present / uncertain / away
保护动作正在执行    idle / running / partial

因此更适合把状态拆成正交维度,而不是枚举所有组合。

type PrivacySnapshot = {
  presence: "present" | "uncertain" | "away";
  visibleContent: boolean;
  sessionAccessible: boolean;
  privateFilesOpen: boolean;
};

触发信号先经过确认层

输入来源的可靠度不同。快捷键是明确命令,USB 拔出通常是清晰变化,蓝牙断开可能抖动,摄像头结果可能只出现一帧。确认层需要允许候选被撤销:

RawSignal
   ↓
Candidate(version=N)
   ├─ 新状态到达 → version=N+1,旧候选失效
   └─ 条件持续   → ConfirmedSignal

伪代码:

async function confirm(signal: RawSignal) {
  const version = versions.advance(signal.subject);
  await rules.for(signal.source).observe(signal);

  if (!versions.isCurrent(signal.subject, version)) return null;
  if (!facts.stillMatch(signal)) return null;

  return { ...signal, confirmedAt: now() };
}

不同来源可以拥有不同 observe 实现,但最终输出同一种确认事件。

策略层只看确认事件和当前暴露

传感器不直接决定动作:

function selectActions(event: ConfirmedSignal, s: PrivacySnapshot) {
  const actions: Action[] = [];

  if (s.visibleContent) actions.push(preferences.screenAction);
  if (s.presence === "away" && s.sessionAccessible)
    actions.push("lock-session");
  if (s.privateFilesOpen) actions.push("protect-private-files");

  return freezePlan(dedupe(actions), event.id);
}

这里的 screenAction 由用户提前选择。仍在电脑前时,隐藏指定窗口可能比锁屏更符合目标;确认离开后,会话锁定则更重要。

执行态要允许部分完成

如果执行器只有 success/failed,一个窗口操作失败就会掩盖其它步骤已经完成。更合理的结果是:

type StepResult = {
  action: Action;
  state: "done" | "already-satisfied" | "cancelled" | "failed";
};

完整数据流:

原始信号
   ↓
候选确认与撤销
   ↓
读取 PrivacySnapshot
   ↓
固化 ActionPlan
   ↓
SingleFlight 防止重复执行
   ↓
每一步先探测目标状态
   ↓
记录 done / already-satisfied / failed

重新连接设备不应自动恢复所有内容。恢复同样需要独立的用户意图,否则刚保护好的窗口可能在旁人仍在时重新出现。

防窥膜与软件状态机怎样配合

物理防窥适合长期缩小旁观角度;软件状态机适合处理内容已经显示、会话可能被操作和文件需要重新锁定的时刻。两者互补,不存在“一项替代全部”的关系。

我们在开发超级看门狗时,保留手动触发,也允许用户配置 USB、蓝牙以及可选的手势或离席触发,再执行提前选择的屏幕、窗口和保险箱保护。本地加密文件保险箱负责长期文件边界;产品不判断用户正在查看什么,也不保证自动信号在所有环境中都准确。

如果想先按实际场景判断需要保护哪一层,可以查看电脑防窥四层指南

桌面隐私状态机最重要的性质不是“自动”,而是候选可撤销、动作可去重、结果可核验、恢复由用户决定。