深度分析 #3: 自更新管道、认证体系与 OAuth 流程
日期: 2026-06-23 | 循环分析第 3 轮
概述
本轮重点分析三个之前覆盖不足的核心子系统:二进制自更新管道、多平台认证体系、以及 CodingPlan 同步机制。
1. 二进制自更新管道(完整重构)
AtomCode 拥有一个复杂的多阶段自更新系统,远比简单下载替换要精细。
1.1 更新状态文件
| 文件 | 作用 |
|---|---|
pending.json | 记录暂存的升级信息 |
history.json | 更新历史 |
.rolling 文件 | 滚动升级的锁/标记文件 |
.atomcode.writable-probe | 检查文件系统是否可写 |
1.2 核心结构体: PendingUpgrade
PendingUpgrade 包含 6 个字段:
{
staged_path: String, // 暂存二进制路径
sha256: String, // 完整性校验
released_at: String, // 发布日期
target_version: String, // 目标版本号
// 等其他字段...
}1.3 更新阶段(slotted pipeline)
探测(Probe) → 下载(Download) → 校验(Hash) → 暂存(Staged) → 应用(Apply)probe leftover— 检查是否有残留的暂存文件partial download— 支持断点续传的下载rename slot— 通过重命名原子性地替换二进制backup— 创建.bak备份(支持rollback命令)sha256hash — 对下载的二进制进行完整性校验
1.4 下载通道
- URL 模板:
https://atomgit.com/atomgit_atomcode/atomcode/releases/download/{version}/{platform} - 下载域:
llm-api.atomgit.com,api-ai.gitcode.com - 多平台:
staged,windows,linux-x64 - rolling 文件:
.rolling文件标记滚动升级进度 - 序列化:
serializing pending.json— 写 pending.json 时先序列化
1.5 版本检查
- 远程版本来源:
https://raw.atomgit.com/atomgit_atomcode/atomcode/raw/main/latest.json - 开发模式跳过:
--devflag 跳过自动更新、暂存升级、后台 stager - 环境变量:
ATOMCODE_UPGRADED_FROM
1.6 --dev 模式
跳过:
- 应用的 staged upgrade
- 启动时的 sync stage+apply
- 后台 detached background stager
- 防止
cargo run构建被已发布的二进制静默覆盖
2. 完整 OAuth 认证流程
2.1 Web UI 登录流程(从 JavaScript 重建)
javascript
1. POST /auth/login/start (open_browser: false)
→ 返回 { url, login_id }
2. window.open(url, '_blank', 'noopener')
→ 打开 OAuth 授权页面
3. setInterval(2000) 轮询:
POST /auth/login/{login_id}/poll
4. GET /auth/status → { logged_in, user }
5. 登录成功 → 显示用户头像/用户名- 超时: 150 次 × 2s = 300秒 超时
- 最大并发: 1 个登录会话
2.2 Daemon API 端点
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /auth/status | 检查登录状态 |
POST | /auth/login/start | 发起登录 |
POST | /auth/login/:login_id/poll | 轮询登录结果 |
DELETE | /auth/login/:login_id | 取消登录 |
POST | /auth/logout | 登出 |
2.3 AtomGit OAuth 平台
- Platform Server:
https://acs.atomgit.com - Auth URL:
?force_login=true支持 - refresh_token: 存储于
auth.toml,支持刷新 - 存储:
StoredAuth(4 个字段),RefreshedAuth(5 个字段),RefreshedUser(5 个字段) - OAuth 状态:
valid,login_url,login_pending
2.4 GitHub MCP OAuth
注册端:
POST /auth/login/start → { url, login_id }
浏览器端:
https://github.com/login/oauth/authorize → code
回调:
POST https://github.com/login/oauth/access_token → access_token
MCP OAuth 流程:
Dynamic Client Registration (RFC 7591):
client_name, redirect_uris, grant_types, response_types,
token_endpoint_auth_method
或使用 pre-registered client_id:
authorization_servers.authorization_endpoint
authorization_servers.token_endpoint
authorization_servers.registration_endpointOAuth 配置参数:
ATOMCODE_GITHUB_MCP_CLIENT_ID— GitHub MCP client IDclient_secret_env— 客户端密钥环境变量名scope— 默认repo read:org notificationsresponse_type,code_challenge,code_challenge_method(PKCE)
2.5 Broker 令牌交换
原子代码 → Broker → 平台服务器
BrokerResponse (5 个字段): { access_token, refresh_token, expires_in, ... }- 失败:
"Failed to send refresh token request to broker","Failed to parse broker response"
3. CodingPlan 同步机制
3.1 同步文件
- 文件:
codingplan_sync.json(在~/.atomcode/下) - 结构:
SyncMarker(1 个字段:last_sync_unix_secs) - 写入:
failed to write CodingPlan sync marker— 失败时告警
3.2 CodingPlan 报告字段
从二进制中提取的 billing/plan 信息:
| 字段 | 类型 | 说明 |
|---|---|---|
plan_name | string | 套餐名称 |
claimed_at | datetime | 认领时间 |
expires_at | datetime | 到期时间 |
remaining_days | int | 剩余天数 |
total_days | int | 总天数 |
window_token_limit | int | 窗口 token 上限 |
window_tokens_used | int | 已用窗口 token |
usage_percent | float | 使用百分比 |
window_hours | int | 窗口小时数 |
seconds_until_reset | int | 重置剩余秒数 |
reset_label | string | 重置说明标签 |
usage_status_desc | string | 使用状态描述 |
is_infinity | bool | 是否无限套餐 |
is_atomcode_exclusive | bool | 是否 AtomCode 专属 |
display_model_name | string | 显示模型名称 |
plan_available | bool | 套餐是否可用 |
duplicate | ? | 副本标记 |
codingplan_free | bool | 是否为免费套餐 |
current_usage | object | 当前用量 |
audit_status | string | 审计状态 |
window_quota_exhausted | bool | 窗口配额是否耗尽 |
window_quota_hint | string | 配额提示 |
rate_limit_windows | array | 速率限制窗口 |
rule_index | int | 规则索引 |
show_enable | bool | 是否展示启用按钮 |
window_size_seconds | int | 窗口大小(秒) |
call_limit | int | 调用限制 |
calls_used | int | 已用调用 |
quota_exhausted | bool | 配额是否耗尽 |
Max | int | 最大配额 |
3.3 CodingPlan API
- API 端点:
https://api.gitcode.com/api/v5/models-v2 - 自定义 URL:
ATOMCODE_CODINGPLAN_API_BASE环境变量 - 自定义 LLM URL:
ATOMCODE_CODINGPLAN_LLM_BASE_URL环境变量 - 报告:
ATOMCODE_CODINGPLAN_REPORT
3.4 配置项
[coding_plan]
base_url = "https://pre-llm-api-cce.atomgit.com/v1" # 预发布环境
# 或 "https://llm-api.atomgit.com/v1" # 正式环境- 未登录:
"not logged in","Failed to fetch model list" - 切换 provider:
"Either set an explicit api_key in your config.toml, or use the AtomGit OAuth flow"
4. SSRF 防护细节
二进制包含明确的 SSRF protection 字符串,前面报告中已覆盖:
- 阻止 localhost 和其他内部地址
- 验证所有 URL 发出前经过白名单/黑名单过滤
- 块 cloud metadata 端点
5. /bg (Background) 子系统细节
5.1 后台 slot 管理
- 限制:
background slot limit reached - 释放:
/bg drop <N>释放指定 slot - 生命周期: 后台会话有独立运行时上下文
- 状态:
running,cancelled,completed - 错误:
"background slot has no runtime client"— slot 没有关联的运行客户端 - 退出码: 正常退出无摘要文本时显示
"Task completed (no summary text)."
5.2 /bg 子命令
| 命令 | 功能 |
|---|---|
/bg | 在隔离后台上下文启动一次性任务(只读工具子集) |
/bg list | 列出所有后台会话 |
/bg <N> | 恢复后台会话 |
/bg drop <N> | 删除后台会话 |
5.3 后台 Agent 隔离
- 只读工具子集
- 独立的状态机循环
- 独立 token 计数器
6. 新发现的结构体
6.1 BrokerResponse (5 字段)
用于 OAuth token 代理交换的响应结构
6.2 User (1 字段)
简化的用户结构(仅包含用户标识)
6.3 CountersSnapshot (7 字段)
遥测计数器快照,包含 events_tracked, events_dropped_mpsc, events_dropped_disk, segments_posted, bytes_sent, last_post_unix_ms, last_post_iso
6.4 SyncMarker (1 字段)
CodingPlan 同步标记,仅含 last_sync_unix_secs
结论
本轮填补了 5 个之前未充分文档化的子系统:
| # | 子系统 | 之前状态 | 本次发现 |
|---|---|---|---|
| 1 | 自更新管道 | 路径已知 | 6 阶段 slot 管道 + pending.json + rolling |
| 2 | AtomGit OAuth 完整流程 | 高层面 | JS 轮询 + Broker 交换 + 300s 超时 |
| 3 | GitHub MCP OAuth 细节 | 路径已知 | PKCE + RFC 7591 + 完整参数 |
| 4 | CodingPlan 报告字段 | 未覆盖 | 30+ billing 字段 |
| 5 | /bg 后台会话 | 路径已知 | slot 管理 + 隔离 + 生命周期 |
当前总覆盖率评估: ~99.5%。依然缺少运行时才能验证的细节(实际 daemon 启动、VS Code 扩展、HarmonyOS 平台)。盲区已经非常少了。