Files
cpa-plugin/docs/modules/operations.md
T

17 KiB
Raw Blame History

部署与运维模块

1. 定位

本模块规定 cpa-ext 如何构建、安装、启动、观察、备份、升级和恢复。它把 dev.md 的 native runtime 约束、security.md 的 fail-closed 前提和 persistence.md 的数据库规则转成可执行运维流程。

当前仓库仍是只声明 usage_plugin 的基础骨架,不具备本文所述完整生产能力。只有 test-plan.md 的相应发布门禁通过后,才能把某个版本标记为 production-ready。

2. 支持基线

设计验证基线:

项目 目标
CLIProxyAPI v7.2.130 / f43aad7637ad813745bf7d341acb5663617570c5
Native ABI 1
RPC schema 3
cpa-ext plugin ID cpa-ext
当前 module Go 1.24
CPA module Go 1.26.0
Home mode 不支持,必须关闭
CPA build 必须是 CGO/plugin-capable,不能使用 no-plugin 产物

生产兼容性按“精确 CPA tag + OS + arch + cpa-ext artifact”发布,不只写“ABI 1”。每次升级 CPA 都要重新跑 ABI、E2E、安全、性能和 soak 门禁。

目标发布矩阵:

  • Linux amd64/arm64 .so
  • Windows amd64 .dll
  • macOS amd64/arm64 .dylib(若实际维护);
  • WSL 构建的 .so 只供运行在 WSL/Linux 的 CPA,不能装入 Windows CPA。

Go c-shared 需要目标平台 C toolchain,不能只设置 GOOS/GOARCH 假装完成 CGO 交叉编译。

3. 运行拓扑

3.1 默认 MVP

reverse proxy / readiness gate
        │
        ▼
CLIProxyAPI + cpa-ext.so
        │
        ├─ synchronous short SQLite transactions
        ├─ callback-driven bounded maintenance
        └─ no long-lived plugin worker

第一版默认 callback-driven:认证、准入、事实和账本在回调内完成必要短事务;聚合追赶、清理和 checkpoint 只在安全宿主调用中按时间/页数预算推进。

3.2 Sidecar 拓扑

P0 runtime/24h soak 失败,或需要长期 quota refresh、备份、归档、大导出时:

CLIProxyAPI + thin cpa-ext plugin ── SQLite/IPC ── cpa-ext sidecar

sidecar 只承担长期任务/公共 API,不得形成第二套余额或价格权威。SQLite 单 writer、IPC 认证、文件锁和 crash ownership 必须另行验证。

3.3 Worker 拓扑

只有目标 CPA/Go/toolchain/SQLite driver 的双 runtime 24h soak 通过,才允许动态库启用有界 worker。发布元数据必须标出 topology;不能在补丁版本中静默从 callback-driven 改为 worker。

4. 文件与权限布局

建议 Linux 布局:

<cpa-root>/
├─ cliproxy
├─ config.yaml
├─ plugins/
│  └─ linux/amd64/cpa-ext-v0.1.0.so
└─ data/cpa-ext/
   ├─ cpa-ext.db
   ├─ cpa-ext.db-wal
   ├─ cpa-ext.db-shm
   ├─ backups/
   └─ diagnostics/

/etc/cpa-ext/
└─ hmac-keyring.json     # 或 OS secret store,绝不放进 data/backups

要求:

  • CPA 运行用户拥有 plugin/data,其他用户默认不可读;
  • keyring 0600、目录 0700
  • DB/backup 0600、目录 0700
  • plugin binary 只由发布/运维用户写,运行用户只读;
  • 数据目录不能位于临时目录、网络共享或会被自动清理的位置;
  • 不把 SQLite、WAL、keyring、Auth、日志放进发布归档;
  • Windows 使用等价 ACL,不能只依赖扩展名。

5. 目标配置

remote-management:
  allow-remote: false
  secret-key: "<strong-random-management-key>"

# 仅保留一个运维离线 sentinel;绝不分发给用户。
api-keys:
  - "<strong-random-sentinel-key>"

plugins:
  enabled: true
  dir: plugins
  configs:
    cpa-ext:
      enabled: true
      priority: 100
      store:
        version: "0.1.0"
      codex_only: true
      data_dir: data/cpa-ext
      database_file: cpa-ext.db
      settlement_currency: USD
      frontend_auth_exclusive: true
      unbound_key_policy: deny
      unpriced_usage_policy: deny_new_requests
      maintenance_mode: callback

说明:

  • 上述是完整目标配置,当前基础插件只解析 codex_only
  • CPA Home 是由 -home-jwt 注入的 runtime-only 状态,YAML 中的 home: 会被当前 parser 忽略;生产启动命令不得使用 -home-jwt,并由 readiness 检查实际 runtime 状态;
  • enabledpriority 是 CPA host-owned 字段,也会出现在 config_yaml
  • store.version 用于选择版本化动态库;
  • database_file 相对 data_dir 解析,不能允许 .. 逃逸;
  • settlement_currency 第一版只能是 USD
  • HMAC keyring 通过受限 secret-file/OS store locator 注入,不把 key 值放进 YAML;
  • 生产不允许 observe-only、unbound allow 或 unknown price=0
  • 所有可互相绑定的 Codex Auth 应使用相同 CPA priority。

热配置:UI 展示、查询限制、非安全统计刷新参数、明确允许的业务阈值。冷配置:data/database path、keyring source、currency、plugin identity、runtime topology。冷配置变化由 LKG reconfigure 拒绝并提示排空重启。

6. 本地开发构建

6.1 WSL/Linux

cd /mnt/d/agent/cpa-plugin
./scripts/check-env.sh
go test ./...
go test -race ./...
./scripts/build.sh
file bin/cpa-ext.so
nm -D bin/cpa-ext.so | grep cliproxy_plugin_init

build.sh 会执行 gofmt、go mod tidy、单元测试和 c-shared 构建。正式 CI 应把“依赖文件是否被意外修改”作为检查,不能让 tidy 的变化无人审阅。

6.2 PowerShell 调用 WSL

./scripts/build.ps1
wsl file /mnt/d/agent/cpa-plugin/bin/cpa-ext.so
wsl nm -D /mnt/d/agent/cpa-plugin/bin/cpa-ext.so

当前产物是 Linux .so。Windows .dll 必须在 Windows CGO toolchain 下单独构建和验证 export。

6.3 当前测试宿主

仓库已有:

./scripts/run-test-host.sh
tail -f .runtime/cliproxy.log
./scripts/stop-test-host.sh

.runtime/ 只用于本地测试,不是生产目录。/healthz 只证明 CPA 进程存活,不证明 cpa-ext active、价格可用或不存在认证旁路。

7. 发布物

每个 artifact 必须包含/伴随:

  • cpa-ext 动态库;
  • version、git commit、build timestamp
  • target OS/arch、Go version、C toolchain
  • minimum/exact tested CPA version
  • ABI=1、max RPC schema=3、capability 清单;
  • runtime topology
  • LICENSE、NOTICE/THIRD_PARTY
  • SHA-256 checksum,推荐额外签名/provenance/SBOM。

CPA plugin store zip 根目录中的动态库文件名使用:

cpa-ext.so
# 或
cpa-ext-v0.1.0.so

安装目标可位于 plugins/<goos>/<goarch>/。发布包不能包含生成 .h,除非消费者明确需要。

8. 安装前检查

  1. 确认 CPA exact version、plugin-capable build 和平台架构;
  2. 确认 CPA 未使用 -home-jwt 启动,实际 runtime Home.Enabled=false
  3. 备份 CPA config、SQLite 和匹配 keyring
  4. 校验 artifact checksum/signature
  5. 校验动态库 export cliproxy_plugin_init
  6. 检查 data/keyring 目录权限和磁盘余量;
  7. 检查只有 sentinel 留在 CPA native api-keys,没有用户 Key
  8. 检查 management 仅 loopback/受信网关可达;
  9. 检查所有可绑定 Codex Auth priority
  10. 准备 gateway drain 和 rollback artifact
  11. 首次生产部署必须先有已审阅 published price version
  12. 确认 P0 runtime/performance/soak gate 结论与所选 topology 一致。

9. 首次安装

  1. 在排空环境停止 CPA
  2. 原子复制版本化 dynamic library 到目标目录;
  3. 创建 data/keyring 目录和权限;
  4. 写入/审阅配置,先不开放用户入口;
  5. 启动 CPA,观察 plugin load/register/schema/capabilities
  6. 等待 migration、integrity 基础检查、keyring、price 和 recovery 完成;
  7. 用 Management /plugins 确认 cpa-ext active 和版本;
  8. 调用 cpa-ext /readiness 与最小 /ready
  9. 执行无效用户 Key 负向探针,确认不能访问上游;
  10. 在隔离测试账户完成“签发 → 准入 → strict route → Usage → 金额账本”;
  11. 对比无插件 OAuth 基线的 TTFT/吞吐;
  12. gateway 才开始逐步放量。

任何一步失败都保持用户入口关闭。不能因为 CPA /healthz 为 200 就继续。

10. 启动顺序与 readiness

插件内部:

  1. 解析 lifecycle config/schema
  2. 验证冷配置和路径;
  3. 打开 SQLite、migration、quick integrity
  4. 加载 HMAC keyring
  5. 加载 active PriceVersion
  6. 恢复 pending/Usage/settlement/outbox
  7. 加载账户、Credential、route 和统计 Snapshot
  8. 装配 callback runner/sidecar
  9. 原子发布 Runtime
  10. 返回 registration。

Readiness component

Component 失败影响
runtime/schema/capabilities 不注册/不开放流量
SQLite/migration/ledger fail closed
HMAC keyring fail closed
active pricing fail closed
Credential/account directory fail closed
statistics projection 可降级,显示 lag
quota refresh 可降级,显示 stale
UI resources 不影响计费,但管理页不可用
backup/archive runner 告警,不允许掩盖核心 readiness

外部 gate 组合:

  • CPA process health
  • Management plugin active/version/capabilities
  • cpa-ext self readiness
  • resource /ready 存在;
  • Home 关闭;
  • 负向认证探针;
  • gateway 自己确认 sentinel 未被分发。

11. 监控与告警

最低指标:

类别 指标
Runtime active/fused/reconfigure rejected/schema/topology
RPC 每 method 调用数、错误、panic、耗时、payload bytes
Auth success/reject/unknown/dependency failure、rate limit
Access terminate code、strict mismatch、scheduler fallback
Billing settlement、amount、late revision、unpriced、unmeasured、negative balance
Persistence transaction latency/error/busy、WAL/DB size、integrity、backup age
Projection event_seq、checkpoint、lag、rebuild status
Upstream account active/missing/priority shadow、quota age/error
Performance TTFT、total latency、chunk gap、alloc/GC、stream RPC bytes
Gateway open/drained、last readiness/negative probe

必须告警:

  • plugin route/active 状态消失或 fuse
  • readiness 核心 component 失败;
  • persistence gap、账本不一致;
  • active price 缺失/未知 GPT-5.6
  • unpriced/unmeasured 超阈值;
  • keyring mismatch
  • DB/WAL/磁盘逼近上限;
  • backup 超过目标 RPO
  • projection lag
  • priority 变化导致 binding 不可用;
  • stream 性能相对基线退化。

指标端点默认只在 Management/受信 sidecar 暴露,不把账户数、金额或错误详情放进公开 /ready

12. 日常维护

12.1 每日

  • 检查 readiness、gateway 和关键告警;
  • 检查 unpriced/unmeasured/persistence gap
  • 检查 backup 成功和磁盘;
  • 检查 quota stale、missing Auth 和 strict mismatch
  • 检查异常 Credential 消费和负余额。

12.2 每周

  • 运行账本余额 reconciliation
  • 检查 projection checkpoint 与 archive eligibility
  • 审阅价格候选,但不自动发布;
  • 审阅 audit、Key rotation/expiry 和管理员操作;
  • 抽样恢复 backup 到隔离目录。

12.3 每月/发布前

  • 完整离线 restore drill
  • 容量/查询计划检查;
  • 依赖、CPA 和价格来源复审;
  • sentinel/Management/HMAC/key rotation 演练;
  • 安全故障注入和 24h soak(涉及 runtime/toolchain/SQLite 变化时)。

13. 备份与恢复

13.1 备份

  • 使用 SQLite online backup API,不直接复制 WAL 模式 .db
  • 备份包含 schema/version/content hash/created_at
  • keyring 单独加密备份,记录非秘密 fingerprint/key IDs
  • 保留 730 天并至少一份异地副本;
  • 备份目录不由 public API 任意下载;
  • 每次破坏性 migration 和版本升级前强制备份;
  • backup 成功必须通过打开、integrity 和基本账本检查。

13.2 离线恢复

  1. gateway 排空并停止 CPA/sidecar
  2. 保存损坏现场副本;
  3. 选择匹配时间点的 SQLite + keyring
  4. 在隔离目录验证 checksum、schema、integrity、key fingerprint
  5. 替换明确目标文件,不操作宽泛目录;
  6. 启动时运行 migration/recovery
  7. 从权威事实重建 projection
  8. 运行账本、Credential 和 PriceVersion reconciliation
  9. 完成全套 readiness/负向/计费探针;
  10. 逐步恢复流量并记录事件审计。

缺失/不匹配 keyring 时不得自动生成新 key 后继续;保持 fail closed。

14. 升级与回滚

14.1 禁止热替换生产动态库

当前 CPA binary hot reload 会把旧 native 实例放入 retired 集合,直到宿主整体 shutdown 才真正 shutdown。旧 runtime/worker/SQLite handle 可能继续存在,因此生产升级固定为:排空 → 停 CPA → 替换/切换 version pin → 启动。

14.2 升级流程

  1. 阅读 release notes、CPA compatibility、migration 和 topology 变化;
  2. staging 完成 test-plan 全门禁;
  3. 备份 SQLite + keyring + config
  4. gateway drain
  5. 停止 CPA 并确认进程退出;
  6. 安装新版本化 artifact、更新 version pin
  7. 启动、migration/recovery/readiness
  8. 执行负向认证、金额 golden、route、cancel/stream 和性能 smoke
  9. 小流量观察;
  10. 标记升级完成并保留旧 artifact/backup。

14.3 回滚

如果 migration 保持旧版兼容,可以停机切回旧 artifact。若 schema 已不兼容:

  • 停机;
  • 恢复升级前 SQLite + 对应 keyring
  • 恢复旧 config/artifact
  • 重新完成 readiness/探针;
  • 对升级窗口产生的真实上游消费人工 reconciliation,不能静默丢账。

价格回滚不需要二进制回滚,走 pricing.md 的“创建新发布版本”。

15. 配置变更

  • 使用 CPA Management API/YAML 变更前保存当前 revision
  • 安全敏感变更必须双人复核和 reason;
  • 写入后检查 LKG/reconfigure_rejected
  • capability shape 不因热配置错误消失;
  • 冷配置只在排空重启中修改;
  • 不用手改 SQLite 代替管理 API;
  • 不在 config 中放 Management/downstream/HMAC/OAuth secret 的副本;
  • 变更 Codex Auth priority 前预览受影响 binding。

16. 常见故障 Runbook

16.1 CPA 正常但 /ready 404

立即撤流量 → 检查 Home、plugin global/instance enabled、文件名/版本 pin、架构、export、load/register 日志 → 不要临时删除 sentinel 或放开 native Key。

16.2 Readiness 显示 DB/keyring/price unhealthy

撤流量 → 保留现场 → 检查权限、磁盘、key ID、migration、active price → 修复后运行 integrity/reconciliation → 不切 observe-only。

16.3 用户请求突然变慢

先 A/B 比较同 CPA/OAuth/model/tier/transport:无插件、空 hook、collection-only、完整插件 → 检查 schema=3、每 chunk RPC 字节、HistoryChunks、response-before 重复 body、DB/锁和 GC → 超过 dev.md 阈值即回滚/撤下相关 hook。

16.4 strict binding 不可用

检查 CPA Auth active/disabled/unavailable、模型和 priority → 查看 scheduler candidates/bindable reason → priority_shadowed 时统一 priority 或调整产品绑定,不强行返回隐藏 Auth ID。

16.5 quota stale

不影响已由 CPA candidate 证明可用的基础 strict 请求,但 UI 标 stale → 手动小批 refresh → 检查 provider allowlist、Auth ref、限流和 sidecar → 不把 stale 写成 0/无限。

16.6 persistence gap/unmeasured 激增

撤流量或收紧并发 → 检查 callback、DB、response correlation 和 CPA 版本 → 保存上游证据 → 修复后追加 settlement/adjustment;禁止猜 Token 或覆盖旧账本。

17. 容量与保留

发布前用真实形状数据验证:

  • 50/500/更多 Credential 与上游账户;
  • 百万级 Request/Execution/Usage/Ledger
  • 30/90 天查询;
  • streaming 长 Prompt/多 chunk
  • 并发 1/8/32 及计划上限;
  • WAL、backup、rebuild 和 archive
  • 磁盘增长、峰值内存、CPU、p95/p99。

容量结论记录最后成功点和最小失败点,生产持续负载取安全折扣。可参考 usage-keeper internal/benchmark/capacity-v1 的 canonical dataset、clone、cgroup memory peak 和 p99 方法,但需要增加 native plugin/CPA/stream 维度。

18. 验收标准

  • 文档明确当前骨架与 production-ready 版本的差别;
  • artifact、CPA、ABI/schema、OS/arch/toolchain 可追溯;
  • 安装前 checksum/export/权限/version pin 均验证;
  • 生产 gateway、sentinel、exclusive 和负向探针缺一不可;
  • /healthz 不被误用为插件 readiness
  • SQLite/keyring 成对备份和隔离恢复演练通过;
  • 升级一定排空并重启 CPA,不热替换;
  • migration 失败、keyring mismatch、price 缺失时保持 fail closed
  • 关键指标/告警/日常检查和故障 runbook 可执行;
  • WSL/Linux 与 Windows artifact 不混用;
  • 生产配置不使用 000、observe-only、用户 native CPA Key 或未确认价格;
  • 发布流程引用并满足 test-plan.md 全部门禁。