Repository navigation
fix(chat): reuse trusted host model auth in isolated sessions - #6008
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=xhigh
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewed exact head f2ee7e8a1d6d040022485b1d17afb966c47fb017; immutable base c96fd4f550d46256cc12724f1348123b57d4d01c. Independent code/entrypoint review; the publishing account is also the PR author, so this is a COMMENTED approval conclusion.
动机
已授权隔离项目聊天的操作者在已有可信宿主模型登录时启动或恢复群话题会话。基础版本即使宿主已登录,隔离聊天仍需要另一份项目登录;本版本通过原生模型认证接口借用短期凭据,工作区、历史与工具权限继续隔离。已独立验证原生隔离启动、同线程恢复、凭据不写入项目文件以及工作区外与 symlink 的拒读。这次评审不认证真实 OAuth 刷新、模型实际回答、在线飞书群准出、延迟改善或已安装发布版本。真实账号刷新、实时模型与群聊黄金查询仍需原有发布验收,不能由本地协议与界面 fixture 代替。重复登录造成的配置负担确实存在;直接复制凭据虽省步骤,却破坏独立项目存储边界。本 PR 用已有原生协议解决这一个认证缺口,保留工作区授权与群选择,属于有用的阶段增量。
改动思路
权限决策继续由现有 TypeScript 项目上下文 owner 持有;Python 新模块只承担 Codex 原生认证 IO,界面只解释已有连接入口,不新增登录或权限控制面。本 PR 交付隔离聊天的模型认证桥、失败恢复与对应界面说明;公开群完整准出保留在已有验收边界。认证文件读取只选短期访问令牌和账号标识,经 app-server 私有 stdin 传递;模型上下文、命令行与工具环境不接收它们。已独立登录的项目优先;普通 host_default 和执行模式不走新增认证桥。回调仅处理原生 unauthorized 请求,刷新仍委托原生 account/read,前后核对同一账号,失败使用固定脱敏信息并允许原会话重试。它不授予管理者、全局技能、MCP、任意网络或发布权限。
具体改动
先以不可变基础版本阅读 既有 RFC:docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,spec_revision c96fd4f550d46256cc12724f1348123b57d4d01c,再审全部六个文件(+355/-11)。基线要求独立存储单独登录;本次任务明确允许把登录前置条件改成可信宿主的模型认证复用,因此 RFC 修改是需要证明的语义变化,不能用修改后的文字自证。范围映射如下:
Selected group topics: isolated ordinary project Chat:implemented。保留 workspace_only、独立历史/home、禁全局技能/MCP/账号环境;仅把“另一份登录”调整为原生短期模型认证桥,不复制凭据或个人历史。Managed:implemented。已有项目登录优先;账号不一致、坏文件、symlink、刷新失败均拒绝且脱敏;原线程恢复不替换模型账号。Authority:implemented。现有 TypeScript 权限 owner 保留,工作区外和 symlink 真实拒读,原有撤权/身份/群范围测试通过,普通入口保持原行为。Packaging:deferred。当前 head 已构建并检查打包 EN/ZH 提示及不可用/恢复状态;完整已安装版本首次请求/返回、窄屏及真实模型旅程仍属于既有发布验收。Delivery boundary:deferred。实际接收方采纳与 GQ02–04/社区群黄金查询继续保留原有验收,协议与 UI fixture 不替代它们。
关键代码讲解
codex_auth.py:_native_refresh(29):只初始化并调用原生account/read(refreshToken=true),带时间预算且 finally 关闭;不创建模型线程、不实现第二套 OAuth。CodexHostModelAuth.read(80):过滤两字段、同账号校验、按 home 锁合并刷新;刷新后再校验账号,任何异常只输出固定错误,令牌不进入 repr。for_isolated_process(112):项目自己的登录优先;坏 symlink 不转用宿主账号,宿主无登录时保持独立登录路径。CodexChatAgentSession.start(554)及_check_server_gate(932):新增 private login 只在既有 permissions_profile 分支发生,启动/恢复继续核验唯一根与 profile;原生刷新回调不放行一般命令批准。
界面只替换 PrivateConversationPanel 群连接说明;两份 RFC 同步阐明短期模型认证与个人存储/工具授权的区别。没有新开关、持久化 schema 或平行的 Python 权限决策 owner。协议依据另查 原生 app-server 文档:external-token 登录及刷新回调由宿主提供短期凭据,原生服务重试原请求;同时用已安装二进制生成 schema 并实际验证登录/启动/恢复。
对主干的风险
最危险的反例是认证复用同时把个人令牌、历史或工具权限带进群聊,或刷新时悄悄换账号。全路径阅读与负例覆盖两字段过滤、私有 RPC、项目登录优先、错误脱敏、并发刷新、一般批准拒绝及现有隔离配置;未复现这类阻塞缺陷。原生文件权限实际测试允许工作区文件、拒绝工作区外与 symlink,工具环境仅含 PATH 和原生 sandbox 标记。此处是同一 Core profile 的原生 standalone command/exec,不冒称已经测试模型实际工具采纳。
本次独立结果:head 核心 140 项加边界 57 项,共 197 passed;不可变基础版本同工作负载 126+57,共 183 passed(新增认证 14 项仅存在 head)。三组普通/host_default/执行入口的独立 base/head RPC 对照一致,宿主凭据“存在”没有激活认证桥。标准 premerge 的 4 direct、4 catalog、8 risk、1 boundary 检查通过,零失败/人工 hold;bundle 构建通过。打包界面用合成 App/工作区/群数据检查中英文完整视口,群列表 503 清空旧选择并禁用连接,恢复后可重读。
真实 Codex 0.162.0-alpha.2 的原生 external-token 登录与同线程重启恢复通过;凭据是合成 JWT,恢复历史是独立构造的公开合成内容,未调用模型、未读取个人账号,项目 auth 文件与令牌落盘扫描为空。先前合成凭据 account/read 返回 401、空线程无 rollout 无法恢复,以及错误测试文件名、probe 导入/mock 和 UI fixture 设置失败均保留记录;它们不被计为通过或宣称产品修复。当前证据分别覆盖协议接受、公开合成历史恢复及隔离引擎;真实 OAuth 刷新、模型回答/工具采纳、实时飞书与跨服务刷新并发仍未验证。CI 按当前 review 策略未查询、未等待。
语义与 CI 对齐
本次复用既有 workspace_only 类型化权限词汇;新字符串是 Codex 外部协议输入,不建立通用共享状态 vocabulary。开发 advisory 支持范围内没有候选,完整 semantic vocabulary canary 通过;动态构造与模型理解不能因此算已验证。登录前置条件与 UI 说明的改变已明确披露;隔离、原话题返回、单独公开群准出这些条件保持,失败与恢复入口可观察。
我的整体评价
APPROVE,交付判断为 justified_increment。long_horizon 为 preserved:原线程和账号边界、失败重试与既有队列 owner 保留;user_experience 为 improved:已有可信登录可服务模型认证,免去另一份登录而不省略 App/群/工作区的必要授权。没有证明模型质量、端到端延迟或社区上线。未来向前的有界重构检查已做:原生认证 IO 留在最近 native_chat owner,通用状态/权限仍由 TypeScript 持有;未发现本 PR 必须再加抽象或兼容分支的理由。实验性原生协议版本兼容及真实账号/群旅程保留在原发布验收,批准不授予合并或上线权限;head 改变需要重新评审。
English verdict: APPROVE - HEAD f2ee7e8. A justified model-authentication bridge for explicitly isolated Chat, preserving project-native login precedence, filesystem/history/tool isolation and account pinning. Independent head 197/base 183 tests, standard premerge, packaged EN/ZH hint/unavailable recovery, native synthetic-token start/resume and real sandbox negatives passed. Live OAuth/model/Lark rollout remains unqualified; CI was not consulted.
An isolated Chat workspace currently needs another Codex login even when its trusted host already has a valid native ChatGPT account. This change supplies short-lived model authentication through the native app-server token interface, so isolation does not require a duplicate login.
Only
workspace_onlysessions use this path. An existing independent workspace login takes precedence. Workspace roots, permissions, history, skills, filtered tool environment, and Core session identity stay under their existing authorities. Credentials are sent over private app-server stdio and are not copied into the isolated home, model text, command arguments, or application logs. Ordinary host-default sessions keep their existing behavior.The adapter lives in the existing native Chat provider IO layer. The native account store still owns OAuth refresh; a bounded per-host lock and account checks coordinate concurrent callbacks without another persistent credential cache. Missing credentials, account changes, and refresh failures return a fixed recovery message. The bilingual owning RFC and the existing group-connection hint describe this behavior without adding a setting or permission grant.
Validation on this head:
Limits: the first real model probe exceeded its artificial 120-second budget; resuming the same thread with a 300-second budget completed in about 128 seconds. This change does not establish a latency improvement. The host bridge currently supports file-backed native ChatGPT accounts; keyring-only and API-key accounts are not covered. Live refresh failure/recovery is covered by synthetic provider tests rather than deliberately breaking a personal account. This PR is not installed locally yet, and does not certify the community Bot's real-group golden queries, privacy rounds, or public launch.