Skip to content

OperationGuard

OperationGuard 是 LD-Notion 的权限网关 + 审计系统。它把用户点击、批量导入和 AI Agent 工具调用统一收束到同一条安全边界:先判断授权与权限,再决定允许、确认、拒绝或降级,最后记录可追踪的审计事件。

Mental model

OperationGuard 不替代 Notion 权限,也不绕过 Integration 的连接范围。它负责在浏览器侧回答四个问题:

  1. 当前 actor 是用户直接操作,还是 AI 代为执行。
  2. 当前 operation 需要什么权限等级。
  3. 是否需要用户确认或只允许预览。
  4. 结果应该如何进入 audit event。

权限等级表

LevelNameCapability boundaryTypical operations
0只读搜索、读取、查看详情,不写入远端目标。searchfetchPagefetchBlocksqueryDatabase
1标准创建页面、追加块、更新属性和普通导入。createDatabasePageupdatePageappendBlockscreateComment
2高级移动、复制、归档、恢复、替换正文和 Agent 批量任务。movePageduplicatePagedeletePagerestorePageagentTask
3管理员管理类或结构类高风险操作。数据库结构调整、维护类操作

默认使用标准权限。只读权限适合初次体验;高级和管理员权限应短期开启,用完后降回标准或只读。

Guard lifecycle

mermaid
flowchart TD
  Request[用户或 AI 请求操作] --> IdentifyActor[识别 actor 与 source]
  IdentifyActor --> Classify[识别 operation 与 risk]
  Classify --> Auth{Notion auth ready?}
  Auth -->|否| AuthRequired[拒绝或停在 preview-only]
  Auth -->|是| Permission{权限等级足够?}
  Permission -->|否| Deny[拒绝并返回 required/current level]
  Permission -->|是| Dangerous{危险操作?}
  Dangerous -->|否| Execute[执行目标操作]
  Dangerous -->|是| Confirm[请求用户确认]
  Confirm -->|取消| Cancel[取消且不写入]
  Confirm -->|确认| Execute
  Execute --> Result[收集 Notion API 或目标结果]
  AuthRequired --> Audit[写入 audit event]
  Deny --> Audit
  Cancel --> Audit
  Result --> Audit
  Audit --> Reply[展示用户可见结果]

Permission decision table

Operation familyExample operationsRequired levelConfirmationAudit eventFallback
Workspace readsearchfetchPagefetchDatabase只读Noread.workspace.searched / optional read event显示读取失败原因。
Page create / appendcreateDatabasePageappendBlocks标准Nowrite.page.createdwrite.block.inserted停在预览,不调用 Notion API。
Property updateupdatePageupdateDatabase标准Nowrite.property.updated提示提升到标准权限。
AI agent taskagentTask高级When write is plannedagent.tool.requestedguard.decision降级为只读建议或操作草案。
Move / duplicatemovePageduplicatePage高级Yes for broad changespage.movedpage.duplicated要求确认或拆分为小批次。
Archive / restoredeletePagerestorePage高级Yespage.archivedpage.restored用户取消时不写入。自动同步归档(BookmarkAutoImporter)同样经 canExecute 闸门,权限不足时跳过并记 guard.denied,不裸调 API(v3.7.7,CWE-862/639)。
Permanent block deletedeleteBlock高级Yes, stricter promptblock.deleted取消或拒绝;不承诺可撤销。
Unknown operation未登记工具或动作N/AN/Aguard.denied默认拒绝。

Decision outputs

DecisionMeaningUser-visible result
allow权限、授权和目标都满足要求。执行操作并展示成功或失败结果。
confirm_required权限足够,但操作风险高或影响范围大。展示确认框;确认前不写入。
deny权限不足、授权缺失、目标不可达或操作未知。显示拒绝原因和下一步配置建议。
preview_only内容可生成,但不能安全写入。展示即将写入的 payload,等待用户修正配置。

Failure / override policy

SituationPolicy
权限不足写入前停止,返回所需权限等级和当前等级。
Notion auth missing or expired不调用写入 API,提示 OAuth 重新授权或 manual token 配置。
用户取消危险确认不写入;如果启用审计,记录取消事件。
Notion API failure返回原始失败状态的可读摘要,不伪造成功,不自动重复危险写入。
AI 建议高风险动作AI 只能提出计划,OperationGuard 决定是否可执行。
审计日志关闭权限规则仍然生效;UI 应让用户知道审计关闭。
用户要求 override只能通过提升权限等级和完成确认实现;不能跳过 Guard。
可撤销性只对明确支持恢复的动作提供撤销提示;永久删除块不承诺可撤销。

setLevel 验证

setLevel 方法强制校验输入值必须为 0-3 的整数,拒绝 NaNInfinity、负数或超范围值。这防止了无效权限级别绕过权限系统。

javascript
setLevel: (level) => {
    if (!Number.isFinite(level) || !Number.isInteger(level) || level < 0 || level > 3) {
        throw new Error(`无效的权限级别: ${level},应为 0-3 的整数`);
    }
    Storage.set(CONFIG.STORAGE_KEYS.PERMISSION_LEVEL, level);
},

AI prompt injection 防御

AI 触发的写入操作除了经过 OperationGuard 权限检查外,还受到 prompt injection 多层防御保护:

  1. 输入隔离:用户内容包裹在 <user_content> XML 标签中,与系统指令分离。
  2. 输出净化escapeHtml + safeMarkdown 确保聊天 UI 不会渲染注入的 HTML/JS。
  3. UI 全局转义:所有用户可控文本在插入 HTML 前统一经过 Utils.escapeHtml

详见 Prompt Injection Defense

Audit contract

每次受控写入都应生成 audit event,至少包含 actor、source、operation、target、decision、result 和 redaction 信息。Token、OAuth Client Secret、AI API Key、GitHub Token 与 Obsidian API Key 必须被脱敏。

更多事件格式见 Audit Events