切换 LLM Router 凭据到专用账号表
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / Repository checks (pull_request) Failing after 16s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled

- 将 Router 账号、API Key 元数据和密文统一保存到 llm_router_account

- 增加 Router API Key 的进程内缓存并清理旧 external_api_key 兼容路径

- 更新 SpacetimeDB 绑定、后端架构文档和决策记录
This commit is contained in:
2026-09-03 19:03:40 +08:00
parent c12d744d91
commit 6d41dc2f89
10 changed files with 317 additions and 769 deletions
@@ -7974,17 +7974,17 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
## 2026-08-29 AGC 官方 LLM 代理与 Windows 私有路径修复
## 2026-08-29 AGC 官方 LLM 代理与 Windows 私有路径修复
- AGC 正式发行版不再让用户配置 Provider、Base URL、模型或 API Key。客户端只携带登录 access token 调用 `api-server``api-server` 按 access token 的 owner 查询 `external_api_key``purpose=llm-router` 的账号记录,解密服务端密文后调用固定 `https://router.genarrative.world/v1``gpt-5.6-sol` Responses 路由。真实 Router Key 不进入聊天、manifest、trace、日志、项目文件、Codex argv/环境变量或普通 IPC payload。
- AGC 正式发行版不再让用户配置 Provider、Base URL、模型或 API Key。客户端只携带登录 access token 调用 `api-server``api-server` 按 access token 的 owner 查询 `llm_router_account`,解密服务端密文后调用固定 `https://router.genarrative.world/v1``gpt-5.6-sol` Responses 路由。真实 Router Key 不进入聊天、manifest、trace、日志、项目文件、Codex argv/环境变量或普通 IPC payload。
- 注册成功后视为账号已有余额;当前不实现真实扣费,LLM 代理在 Router 成功返回后再记泥点,扣费失败只记录日志,不影响已经成功的响应。注册入口和首次 LLM 请求都会幂等确保账号 Router Keyapi-server 只通过 New API 管理员 Token 执行正式“创建用户 → 查询用户 ID → 设置分组 → 登录 → 创建无限额度 token → 签发 API Key”流程并加密落库,不再生成或使用任何 Router fallback token。远端结果不确定时写入 reconciliation 标记;本地签发落库失败可安全重试,不制造第二个账号。客户端不会退回手工 Key;真实管理员 Token、注册和生产 Router 联通仍待受控部署 smoke。
- `external_api_key` 继续复用一次性明文返回和 hash/prefix 元数据链路LLM Router 用途固定名称 `llm-router``llm:responses` scope,并额外保存加密密文、Router account id 和固定路由元数据。登出、切换账号或服务器只清理进程内 access token/Provider Proxy,不删除其它账号或设备的本地/远端 Key;Router 确定返回 401/403 时标记当前账号 Key revoked。
- `external_api_key` 继续复用一次性明文返回和 hash/prefix 元数据链路,仅承载普通外部 OpenAPI/MCP Key。LLM Router `llm-router` 用途`llm:responses` scope加密密文、Router account id 和固定路由元数据统一保存在 `llm_router_account`。登出、切换账号或服务器只清理进程内 access token/Provider Proxy,不删除其它账号或设备的本地/远端 Key;Router 确定返回 401/403 时标记当前账号 Key revoked。
- 后台只允许管理员通过专用 API Key 查询接口按 owner、公开用户编号、keyId、精确 prefix、名称、时间、状态和 purpose 筛选;未给出 owner/keyId/prefix 时拒绝无界扫描,永不返回 `key_hash`、密文或原始表行。通用 `external_api_key` 表浏览被拒绝。
- Windows 私有路径严格拒绝 reparse/symlink、非普通对象、路径类型冲突和候选路径冲突。只有本次调用新建的目录/临时文件可在普通进程内初始化 owner;owner 已正确但仅继承 ACL 不合规时,正式 prepare 入口先完成归属校验,再通过当前用户私有、禁止继承、单一 ACE 的 DACL 收紧。用户通过原生选择器明确选中的项目根/文件,或 AGC managed 路径,在发现 owner/DACL 权限不足时由一次性 UAC helper 将普通对象接管为当前 TokenUser 并复核;取消/失败保持失败关闭,未经过正式选择或项目根入口的内部路径不得触发任意提权。
- 规划、Runtime sidecar、UI workflow、资源桥、Skill 隔离目录和图片读取统一经过私有路径准备,并在原子写入后复核类型、owner/DACL 与文件身份。真实 Windows UAC、foreign owner 修复、继承 DACL 收紧、注册后 Router 签发和生产 `/v1/responses` 联通仍需在受控实机/部署环境验证。
## 2026-08-31 LLM Router 独立账号与后置扣费修订
- 每个 Genarrative 用户在认证成功后都必须幂等准备独立 Router 账号:api-server 使用管理员 Token 创建随机密码普通用户,查询用户 ID,设置用户 `group=taonier`,登录、创建或复用固定标识 `agc_auto_generate` 的无限额度 TokenToken/API Key 使用 `default` 分组;发现旧 Token 为其它分组时先更新为 `default`)并签发 API Key。Router 账号用户名、随机密码、access token(如需)和 API Key 作为一个服务端加密 bundle 保存到 `llm_router_account.credential_ciphertext`,脱敏账号信息保存到 `llm_router_account.account_json`,并在 `external_api_key` 中保存正式 `purpose=llm-router` 行与 `credential_version`;客户端和普通用户永远不可见 Router Key。管理员 Token 仅存在 api-server 私有配置,不写入数据库或日志;Router 凭据只来源于这条正式账号流程。
- 该账号 provisioning 使用持久 saga 状态:远端注册、登录、token 或 Key 签发结果不确定时进入 `unknown` / `reconciliation_required`,禁止重复注册;远端 Key 已确定签发但本地 `external_api_key` 写入失败时保持 `key_issued`,后续使用确定 key id 重试落库。Router 确定返回 401/403 时撤销当前 Key 并把账号状态置为 `retryable`,复用已保存的账号密码重新签发替代 Key。
- 每个 Genarrative 用户在认证成功后都必须幂等准备独立 Router 账号:api-server 使用管理员 Token 创建随机密码普通用户,查询用户 ID,设置用户 `group=taonier`,登录、创建或复用固定标识 `agc_auto_generate` 的无限额度 TokenToken/API Key 使用 `default` 分组;发现旧 Token 为其它分组时先更新为 `default`)并签发 API Key。Router 账号用户名、随机密码、access token(如需)和 API Key 作为一个服务端加密 bundle 保存到 `llm_router_account.credential_ciphertext`,脱敏账号信息和 API Key 核心字段保存到 `llm_router_account`;客户端和普通用户永远不可见 Router Key。管理员 Token 仅存在 api-server 私有配置,不写入数据库或日志;Router 凭据只来源于这条正式账号流程。
- 该账号 provisioning 使用持久 saga 状态:远端注册、登录、token 或 Key 签发结果不确定时进入 `unknown` / `reconciliation_required`,禁止重复注册;远端 Key 已确定签发但本地 `llm_router_account` 写入失败时保持 `key_issued`,后续使用确定 key id 重试落库。Router 确定返回 401/403 时撤销当前 Key 并把账号状态置为 `retryable`,复用已保存的账号密码重新签发替代 Key。
- AGC 调用固定为客户端 access token -> api-server -> Router。Router 成功返回后再扣泥点,按临时规则每开始 10,000 token 扣 1 点且至少 1 点;ledger id 由 `Idempotency-Key`(缺省请求 ID)哈希得到,Router 失败不扣费。余额足够时全额扣除;余额不足时按当前可消费余额扣光,差额记为赠送并继续返回已成功的 LLM 响应。该计费规则是过渡实现,待产品定价确认后替换,不能视为 Router 真实成本结算。
- AGC 状态面收口:Tauri `check_game_creator_llm_config``/llm-status``/llm-routes` 只返回账号凭据状态、官方路由锁定状态和运行参数;不序列化 Router 地址、模型、协议名或任何密钥/凭据字段,内部固定路由仅留在运行时配置与服务端代理中。