Files
ai-contract-platform/project-docs/V2-public-policy-production-promotion-runbook-2026-08-17.md
yuqei 801a9b04bc
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 4m4s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 9m18s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Successful in 8m20s
feat: add governed public policy promotion
2026-08-17 19:52:07 +08:00

7.4 KiB
Raw Permalink Blame History

V2 公开政策生产 Promotion 运维手册

日期:2026-08-17

边界

本手册只描述已验签公开政策的受控状态切换。它不替代法务审批、运营审批、容量审批或公网切流审批。候选 keyring、手工修改数据库、HTTP 写接口、政策私钥和共享预发布凭据都不能用于生产激活。

CONTRACT_API_PUBLIC_POLICY_EXECUTOR_ENABLED 必须保持 false。生产读取、注册协议和既有用户重新同意由 Contract API 提供;真正的 promotion 和 rollback 只通过本机受控 CLI 执行,并且不暴露 HTTP 路由。

前置条件

  1. Contract API 数据库已经迁移到 20260812_0046,public_policy_state 存在且状态指针可验证。
  2. 四份政策候选文件、manifest.json、具名法务审批文件和 trusted keyring 已由安全/运维安装到生产主机。
  3. 材料目录和文件均为绝对路径,文件所有者可读,未包含 symlink,目录总量不超过 2 MiB。
  4. CONTRACT_API_PUBLIC_POLICY_RELEASE_DIGEST 等于当前 Contract API 不可变镜像 digest。
  5. 生产只读 preflight 通过。
  6. 已取得单独的运营激活授权文件。该文件只用于计算 SHA-256,内容不得进入仓库、聊天、日志或 CI artifact。
  7. 已记录 expected generation、current set ID、trace ID、idempotency key 和授权文件 hash。

推荐主机布局:

/etc/yuqei/public-policy/2026-08-12/
  manifest.json
  user-terms.md
  privacy-policy.md
  service-agreement.md
  ai-use-notice.md
  named-policy-legal-approval.json
  policy-legal-keyring.trusted.json

生产环境模板中的绑定:

PUBLIC_POLICY_CANDIDATE_DIR_HOST=/etc/yuqei/public-policy/2026-08-12
PUBLIC_POLICY_LEGAL_APPROVAL_FILE_HOST=/etc/yuqei/public-policy/2026-08-12/named-policy-legal-approval.json
PUBLIC_POLICY_TRUSTED_KEYRING_FILE_HOST=/etc/yuqei/public-policy/2026-08-12/policy-legal-keyring.trusted.json
CONTRACT_API_PUBLIC_POLICY_RELEASE_DIGEST=sha256:<contract-api-image-digest>
CONTRACT_API_PUBLIC_POLICY_EXECUTOR_ENABLED=false

1. 只读预检

在生产主机执行:

python3 yuqei-infra/deploy/preflight-production.py \
  --env-file /etc/yuqei/production.env \
  --artifact-dir /var/lib/yuqei/preflight/public-policy

必须确认以下检查为 pass:

  • public_policy_deployment
  • public_policy_credential_isolation
  • public_policy_candidate_dir
  • public_policy_manifest
  • public_policy_legal_approval_file
  • public_policy_trusted_keyring_file
  • 相关 owner-only 权限检查

任一失败时停止,不得通过改名、复制、手工改库或跳过 preflight 继续。

2. 查看当前状态

下面的 COMPOSE_ARGS 按生产部署手册替换为真实 project、env 和两个 Compose 文件参数:

COMPOSE_ARGS=(
  --project-name yuqei-v2-production
  --env-file /etc/yuqei/production.env
  -f yuqei-infra/compose/docker-compose.yml
  -f yuqei-infra/compose/docker-compose.production.yml
)

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli status

输出不包含政策正文,只包含状态指针、版本、生效时间、公开路径和每个文件的 SHA-256。

3. Promotion dry-run

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli preflight

显式 promotion dry-run 还必须提供工单上的 expected state:

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli \
  promote \
  --expected-generation 0 \
  --expected-current-set-id none \
  --idempotency-key policy-promotion-20260812-001 \
  --trace-id ops-policy-promotion-20260812-001

Dry-run 不写数据库,也不需要授权文件。

4. 受控 Promotion

授权文件通过一次性只读挂载进入容器。不要把该挂载写入生产 Compose 文件:

AUTHORIZATION_FILE=/run/yuqei/operations/policy-promotion-20260812-001.txt

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps \
  --volume "$AUTHORIZATION_FILE:/run/yuqei/public-policy/activation-authorization.txt:ro" \
  contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli \
  promote \
  --apply \
  --confirmation I_AUTHORIZE_THIS_EXACT_PUBLIC_POLICY_PROMOTION \
  --authorization-file /run/yuqei/public-policy/activation-authorization.txt \
  --expected-generation 0 \
  --expected-current-set-id none \
  --idempotency-key policy-promotion-20260812-001 \
  --trace-id ops-policy-promotion-20260812-001

命令输出中的 authorization_sha256、generation、set ID、event ID 和 state hash 必须写入运维证据。重复执行同一命令必须使用完全相同的材料;换任何材料必须换 idempotency key 并重新审批。

5. 生效后回归

到达批准的 effective_at 后验证:

  1. GET /api/v1/public-policies/current 返回四份政策。
  2. 四份政策页面返回 approved 字节,页面版本和生效时间正确。
  3. 新注册用户必须绑定四个 effective 协议版本。
  4. 既有用户下次登录进入重新同意流程。
  5. 同意提交记录版本、时间和主体。
  6. 审计和 append-only 政策事件链完整。
  7. Contract Web 不出现未发布、接口故障与真实空态混淆。
  8. 生产 health、schema-check、worker、Provider readiness 和核心合同流程保持通过。

6. 受控 Rollback

Rollback 只允许指向曾经 active 的历史 policy set,不能伪造或引用不存在的 set。先执行 dry-run:

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli \
  rollback \
  --target-set-id <historical-policy-set-id> \
  --expected-generation <ticket-generation> \
  --expected-current-set-id <ticket-current-set-id> \
  --idempotency-key policy-rollback-<ticket-id> \
  --trace-id ops-policy-rollback-<ticket-id>

确认目标后,使用单独的 rollback 授权文件:

ROLLBACK_AUTHORIZATION=/run/yuqei/operations/policy-rollback-<ticket-id>.txt

docker compose "${COMPOSE_ARGS[@]}" run --rm --no-deps \
  --volume "$ROLLBACK_AUTHORIZATION:/run/yuqei/public-policy/rollback-authorization.txt:ro" \
  contract-api \
  python -m yuqei_contract_api.public_policy_promotion_cli \
  rollback \
  --apply \
  --confirmation I_AUTHORIZE_THIS_EXACT_PUBLIC_POLICY_ROLLBACK \
  --authorization-file /run/yuqei/public-policy/rollback-authorization.txt \
  --target-set-id <historical-policy-set-id> \
  --expected-generation <ticket-generation> \
  --expected-current-set-id <ticket-current-set-id> \
  --idempotency-key policy-rollback-<ticket-id> \
  --trace-id ops-policy-rollback-<ticket-id>

Rollback 也是 append-only 事件,不删除历史政策、同意记录或审计。执行后必须重复第 5 节回归,并通知法务和运营具名复核。

7. 明确禁止

  • 禁止把法务私钥、运营授权文件或任何 policy signing key 放入仓库、生产环境文件或 CI artifact。
  • 禁止使用 candidate keyring 直接激活。
  • 禁止把 trusted keyring 的 policy_activation_authorized=false 手工改为 true。
  • 禁止直接 UPDATE/DELETE public_policy_* 表。
  • 禁止新增 HTTP promotion、rollback 或 execute 路由。
  • 禁止在 preflight、容量、备份、法务或运营审批失败时启动 edge 或切换 DNS。
  • 禁止把 dry-run 或技术验签输出宣称为法务批准或公网切流授权。