SubLaneSubLane

架构与设计边界

单进程、SQLite 与明确的凭据和权限所有权。

轻量部署结构

SubLane 由一个 Go 进程提供 HTTP 服务,生产构建将 React/Vite 前端嵌入可执行文件。SQLite 是唯一持久化服务依赖,纯 Go 驱动不要求 CGO。运行时不要求单独的 Node.js 服务、Redis 或 PostgreSQL。

浏览器与 AI 客户端进入同一个 chi HTTP 服务:浏览器走会话与管理接口,客户端走网关密钥与模型协议。网关执行组权限、模型策略、请求准入与账号选择,再通过供应商适配器转发。

这是适合团队内部自部署的结构选择,不是未经测量的内存或吞吐量承诺。一个数据库只运行一个实例进程。

模块职责

模块负责
internal/auth本地用户、角色、成员与浏览器会话
internal/apikey个人网关密钥摘要、加密原文与生命周期
internal/groups资源组、成员授权与模型策略
internal/accounts订阅凭据生命周期、账号模型快照、工作区代理与账号绑定
internal/resets重置卡规则、规范化可用性与到期排序、卡片和请求的持久化预留、每日上限及有界调度
internal/vault本地密钥与 AES-GCM 加解密
internal/gateway准入、冷却、亲和性、请求记录与汇总
internal/upstreamSDK 执行器、供应商协议转换与上游出口选择
internal/storageSQLite、合并结构初始化与 SQL
internal/backup归档校验与隔离恢复
internal/versionsCodex、Grok 与 Claude 的独立版本策略及官方发布元数据同步
internal/updates有界的 SubLane 正式版检查与单任务宿主机更新队列;不负责供应商版本策略、命令执行、Docker 控制或数据库恢复
internal/timezone实例时区配置与运行时位置发布
internal/audit有界管理审计
internal/server路由、认证边界与静态资源

数据与事务

SQLite 使用 WAL、外键和有界等待。新数据库先应用 001_schema.sql,再按顺序执行增量迁移,其中包含工作区代理表与账号的可选代理绑定。更早且不兼容的开发数据库仍会被拒绝,应保留旧目录后另建数据目录。SQL 查询由 sqlc 生成,领域服务保留事务所有权;公开响应不直接暴露数据库行中的密码、代理认证信息或令牌摘要。

事务应短小,不能持有事务等待供应商网络请求。凭据刷新先加密持久化,再发布结果供请求使用。credentials.key 与数据库必须一起备份;缺失或不匹配时启动失败,不能用新密钥覆盖。

供应商边界

Codex、Grok 与 Claude 的客户端版本策略由平台所有者在系统设置中管理,分别保存在现有 settings 表。后台默认每 6 小时检查官方稳定版:Codex 使用 GitHub 发布元数据,Grok 使用官方 npm latest 标签,Claude 使用官方 npm stable 标签。手动指定优先,检查失败时保留上次成功版本,保存成功后才发布;退出时先等待同步任务结束,再关闭 SQLite。Grok 推理和额度查询使用同一生效版本声明。Claude 推理为每次请求捕获不可变 SDK 配置,保持 User-Agent、正文计费版本和最终 CCH 签名一致;临时版本引导监听器立即关闭,凭据存储保持为空。

SubLane 通过公开 CLIProxyAPI SDK 管理 Codex、Claude、Antigravity、Grok Build 订阅和 API 渠道的执行,持久化凭据生命周期仍归 SubLane 所有。SDK 不保存持久凭据或独立自动刷新,客户端只访问 SubLane 主服务。API 渠道将平台、协议、密钥和基础地址一起加密保存,按配置选择公开 SDK 执行器;Responses 使用公开认证 HTTP 接口和转换器。模型发现按平台及协议进行有界请求,不假设统一的 /models 格式。API 密钥不进入 OAuth 刷新或 SDK 凭据库。渠道复用资源组权限、会话绑定和用量统计;更换密钥保留身份、平台、协议和地址,调整这些配置需新建渠道。

管理员可给账号绑定一个加密保存的网络代理。服务端令牌交换、刷新、模型发现、额度读取和模型执行选用该账号的出口;即使 SDK 创建新的请求上下文,请求级传输仍保留绑定。修改代理不会迁移正在进行的响应流或改变会话选中的订阅账号,浏览器授权页面也不经过此服务端出口。

模型目录按账号保存,组目录按当前权限派生。原生请求支持跨供应商候选,已有会话记录原模型并保持具体账号绑定。主动换模型且携带完整可重放历史时,原账号不支持新模型可重选;上游续接和同模型请求保留原绑定。HTTP previous_response_id 不能依赖无状态上游保存历史,客户端需提供完整输入;WebSocket 对话状态保留在连接内并受限。

额度读取器把 Codex 用量、Claude 时间窗口和 Antigravity 模型额度归一化到共享持久缓存,成功写入后才发布快照。重置时间或比例缺失时保持未知,失败时保留旧观察值;账号停用和重新授权会使旧快照失效。Responses 压缩仍仅适用于 Codex。新鲜主额度窗口限制 Codex 和 Claude 账号;Antigravity 按请求原生模型精确匹配额度。选路事务只读取持久元数据,有界共享刷新在事务外执行。

Grok Build 使用有界、绑定会话的设备码授权,由服务端限制轮询间隔并保证完成操作只能执行一次。设备密钥仅保留在服务端,取消或过期后不会保存迟到的凭据。xAI SDK 执行器通过显式 OAuth 标记选择订阅通道;令牌刷新在现有账号持久化流程内调用固定的 xAI 端点。Grok 额度通过相同账号代理读取官方 CLI 额度元数据,并复用已有持久化缓存;仅将订阅内额度归一化。

前端与权限

TanStack Router 管理路由,TanStack Query 管理服务端状态。登录门禁等待真实服务端状态,管理员页面不对成员发起管理查询。切换身份清理私有缓存,权限最终仍由后端执行。

应用提供英文、简体中文、繁体中文、日语、韩语、西班牙语、法语、德语、葡萄牙语、俄语和阿拉伯语,共 11 种语言,以及浅色、深色、跟随系统主题。新增词典按需加载,阿拉伯语采用从右向左的布局,代码和标识符保持从左向右。官网是独立的 Next.js/Fumadocs 项目,不是运行 SubLane 网关所需的服务。

验证边界

协议测试使用合成凭据与模拟上游。真实订阅、桌面客户端、目标机器上的资源基线需要单独证据。不要把协议单元测试等同于所有真实客户端兼容性。

模型限流元数据由 internal/upstream 归一化,不保存或返回原始错误正文。网关持有账号与模型冷却、带版本条件的写入、有界活动状态和正常请求恢复。Antigravity SDK 的本地冷却交由该所有者处理,避免隐藏计时器丢失模型范围或跨越授权生命周期。

API channel management

internal/channels exposes a distinct API-channel management contract over the shared encrypted execution-resource owner. Subscription listing excludes API channels; /api/channels provides administrator-only channel lifecycle and model management. Storage resource IDs remain stable so existing memberships, affinity and key bindings survive.

internal/groups owns typed subscription/channel resource membership and persisted routing preferences. New UI groups prefer subscriptions with API fallback off; migration preserves existing protocol preference. Admission, model catalogs, availability, readiness and alert capacity share the same routing policy. Existing conversations are not moved between resources automatically; explicit model changes with portable history follow the gateway model-routing rules.