统一系统访问

系统访问属于主机能力边界,与模型工具审批、工作区权限规则、账号凭据和提供商授权相互独立。产品只有一个能力注册表、一份实时报告、一条显式设置路径、一种等待表示和一套恢复策略。状态读取从不打开原生提示。模型或远程客户端不能授予操作系统能力。

当前实现与已确认缺口

基础 runtime 原先使用两条硬编码 macOS 项:screen_recording 和 accessibility。后端报告、原生探测、请求路由、GUI 预检和 Web 设置各维护部分列表,其他类别的包声明则独立存在。这导致定义不一致,也可能把重连表现为未经请求的权限申请。

已实现的注册表移除重复能力定义,使普通聊天、浏览器和无界面使用不依赖可选桌面访问。原有双能力 API 保持 wire 兼容,其条目由注册表生成。包用途说明、entitlement、报告 schema、身份元数据、GUI 预检、设置 UI 和等待 manifest 现在使用同一份声明。

参考范围与边界

参考采用规则边界
Apple 屏幕与系统音频录制macOS 管理授权,用户在系统设置中控制。产品可打开对应设置页并验证执行身份,不能静默启用授权。
AXIsProcessTrustedWithOptions辅助功能单独查询,只有显式本地 owner 操作才能申请。信任属于具名 runtime 执行器;另一应用或匿名 Python 进程不能作为证据。
Apple 隐私控制每个隐私类别各自具有同意和撤销生命周期。plist 配置和 entitlement 签名只是前提,不等于授权。
macOS 文件与访问控制文件访问报告为针对具体操作的能力。一次路径读取成功不能证明完整磁盘访问权限,也不得将完整磁盘访问作为通用解决办法申请。
Electron systemPreferences查询与申请是不同操作。Electron API 不会取消 macOS 同意要求或针对目标的 Apple Events 授权。

Linux portal 和 Windows 桌面完整性规则仍各自遵循平台机制。注册表表示它们的状态,不假装这些平台存在 macOS 设置。浏览器和 VM 界面使用自身提供商及会话边界,不检查本机 macOS 权限。

能力注册表

openprogram.system_access 维护不可变注册表。每项包含稳定 id、类别、显示名称、平台、必需或可选策略、目标身份、不弹提示的检查、显式请求模式、设置目标、包声明、操作映射和恢复策略。后端报告、CLI/TUI doctor、HTTP 设置、Web 设置、等待 manifest 和测试共用该注册表,不独立定义能力 id。全部 macOS 原生检查与申请均通过已签名 runtime bundle 身份 ai.openprogram.runtime 执行;源码 checkout 可回退到开发解释器,但已安装 App 绝不注册裸 python3 进程。

字段含义
id稳定协议 id,例如 screen_recording, accessibility, apple_events, calendar, reminders, file_read, file_write, microphone 和 camera.
subject平台检查的身份:runtime, containing_app, target_app, user_selected_path 或 provider_session.
check不弹提示的探测,返回 granted, not_granted, unknown, unavailable 或 unsupported.
request_modenative 表示支持的操作系统申请,settings 表示只能通过设置授权,targeted 表示必须提供目标应用,operation 表示只能通过实际操作验证,none 表示平台没有申请 API。
settings固定的能力专属系统设置 URL 或文档说明。只有 owner 点击操作后才打开。
identityBundle id 和 designated requirement,或提供商/路径身份。匿名 python3, node 和过时缓存路径不作为 OpenProgram 身份。
operations需要此能力的工具与操作名称。GUI 桌面需要屏幕录制和辅助功能;浏览器、VM 和普通 CLI 操作不需要。

注册表在导入时验证:id 唯一,每个原生条目具有不弹提示检查和显式请求方式,具有作用域的条目声明状态语义,每个设置操作拥有固定目标,每个操作引用均指向已声明能力。构建测试对照相同 id 检查包用途说明与 entitlement。

状态与 API 合同

每份报告包含 schema, platform、host、执行身份、时间戳和能力数组。条目包含 id、类别、状态、详情、说明、请求模式、设置可用性、所需操作及恢复元数据。状态含义如下:

GET /api/system/access 返回注册表派生报告。POST /api/system/access/setup 是仅限 owner、仅限回环的首次设置操作:通过已签名 runtime 申请全部注册原生 runtime 能力,并返回一份汇总报告。POST /api/system/access/{id} 是逐项显式回退操作:重新检查,按声明可选执行原生申请,然后返回最新条目。open_settings=true 只打开已声明设置目标,从不声称已经授权。现有 /waits 记录使用同一套 id 和 schema。响应禁止缓存且不含秘密。

首次设置与操作流程

  1. 首次使用时,Web 设置页按产品领域分组显示注册表,解释各能力用途,并在页面加载时对全部条目执行一次只读检查。
  2. 用户为首次原生能力组选择“设置 OpenProgram 全部访问权限”,或为单项选择“请求授权”或“打开系统设置”。页面挂载、重连、状态轮询、历史回放和模型输出渲染从不发送原生申请。
  3. 后端针对每个执行身份串行处理原生申请,使用具名 runtime 执行原生检查和申请,随后重新检查。不同隐私类别或目标应用仍可能分别弹出 macOS 对话框;UI 逐项报告结果,不声称一次点击能授权未知未来目标。
  4. 执行操作前,该操作声明所需能力。worker 生成最新报告,仅针对缺失的必需能力创建持久化 system_access 等待。浏览器和 VM 操作不经过此主机检查。等待保存原始检查点,全部必需条目获授权后继续同一次执行。
  5. 用户返回 App 后,焦点或可见性变化触发只读刷新。授权通过 worker 协调路径解除等待;不提交假回答,不调用重试函数,也不创建新执行。

恢复与身份

普通状态读取、启动协调、重试和重复事件从不运行 tccutil,也不重置其他应用。已验证的过时回执可授权针对固定 OpenProgram bundle 身份的一次显式迁移;标记在操作系统调用前写入以防循环。未验证代码、未知检查、未变化要求、辅助功能迁移和其他全部应用都要求用户使用系统设置。具名 runtime 及所属应用保留稳定 bundle id 和持久本地签名 requirement。标记为 python3 或 node 的构建或缓存路径不作为受认可身份。

第三方 Apple Events 授权针对具体目标。原生后端支持时,日历和提醒事项使用 EventKit 类别同意。文件访问限于用户选择的路径或 security-scoped bookmark。麦克风与摄像头仅由实际使用它们的操作声明和申请。产品不能预先授权从未访问的应用、用户从未选择的路径或已被用户撤销的权限。

信任、隐私与并发

只有执行主机的本地 owner 可以申请或打开设置。回环和 Origin 检查始终必需;转发请求及远程客户端被拒绝。模型可说明缺失能力,但不能调用设置端点。原生探测在新的有限时进程中运行,每轮协调共用一份报告,不枚举屏幕内容。请求按执行器串行处理。等待解除受 execution id、generation、checkpoint version 和取消状态保护。探测失败保持等待;终止或取消的执行不能恢复。

兼容性与迁移

旧客户端可继续发送 screen_recording 和 accessibility。API 保留这些 id 并添加注册表元数据。现有回执以旧屏幕录制格式读取。未知 id 返回客户端错误且不打开设置。现有权限规则与 Auto 模式保持不变。不创建额外应用 profile、worker 或端口。

验收条件

实现状态

本文是统一注册表的权威设计。统一注册表、原生 EventKit/AVFoundation 检查与申请、带版本 schema 报告、身份元数据、包一致性检查、显式设置 UI、不自动申请的恢复、操作预检一致性,以及桌面访问 unavailable 或 unsupported 时的终止处理均已实现。剩余验收取决于安装环境:验证默认已安装的 /Applications/OpenProgram.app(端口 18100) 及其当前 macOS 授权;授权仍由 macOS 控制。