Files
qinglong/docs/operations/ql3-approval-management.md
T

106 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QingLong 3.0 本机人工 Approval 检查与决定
`ql3-approval` 是 Edge/Standalone 的短生命周期 Owner CLI。它不会启动 daemon、监听端口、执行 migration、消费 Approved
Action 或运行 Tool;未调用时资源占用为零。MCP 可帮助发现和查看脱敏 preview,但不能批准或拒绝。
## 前置条件
- QingLong 3.0 SQLite 已由正常部署流程完成 migration/readiness。
- 当前 POSIX User 拥有私有 deployment root、Owner Pepper keyring、active User credential presentation 和 command file。
- credential 的 User 在目标 Project 对检查具有 `approval.read` + `artifact.read`,对决定具有 `approval.decide`
- command、credential、数据库与 keyring 路径必须位于同一私有 deployment root;文件为当前 UID 的 `0600` regular file,目录为
`0700`,不得使用 symlink。
## 第一步:检查 Approval
创建 `/opt/qinglong3/commands/approval-inspect.json`
```json
{
"schemaVersion": 1,
"operation": "approval.inspect",
"options": {
"deploymentRoot": "/opt/qinglong3",
"databasePath": "/opt/qinglong3/data/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/opt/qinglong3/owner-pepper-keyring",
"credentialFilePath": "/opt/qinglong3/owner/credential.json",
"busyTimeoutMs": 500
},
"request": {
"projectId": "default",
"approvalRequestId": "approval-1",
"requestId": "owner-review-1",
"auditEventId": "10000000-0000-4000-8000-000000000001",
"failureAuditEventId": "10000000-0000-4000-8000-000000000002"
}
}
```
```sh
chmod 0600 /opt/qinglong3/commands/approval-inspect.json
ql3-approval run --command-file /opt/qinglong3/commands/approval-inspect.json
```
检查输出的 Project、request/version/state/risk、requester、过期时间、preview 和完整 `expectedAction`。不要从 MCP 输出、日志或
猜测重建 action reference/digest;下一步必须复制本次 Owner inspect 返回的整个 `expectedAction`
## 第二步:批准或拒绝
创建新的私有文件,使用新的 request/audit/failure event ID`expectedVersion` 固定为 1
```json
{
"schemaVersion": 1,
"operation": "approval.decide",
"options": {
"deploymentRoot": "/opt/qinglong3",
"databasePath": "/opt/qinglong3/data/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/opt/qinglong3/owner-pepper-keyring",
"credentialFilePath": "/opt/qinglong3/owner/credential.json",
"busyTimeoutMs": 500
},
"request": {
"projectId": "default",
"approvalRequestId": "approval-1",
"requestId": "owner-decision-1",
"auditEventId": "20000000-0000-4000-8000-000000000001",
"failureAuditEventId": "20000000-0000-4000-8000-000000000002",
"expectedVersion": 1,
"expectedAction": {
"permission": "run.start",
"actionType": "tool.invoke",
"actionRef": "<copy-from-inspect>",
"actionDigest": "<64-lowercase-hex-from-inspect>",
"previewDigest": "<64-lowercase-hex-from-inspect>"
},
"decisionId": "approval-decision-1",
"decision": "approved",
"reasonCode": "reviewed"
}
}
```
`decision` 改为 `rejected` 可拒绝;`reasonCode` 是稳定的低敏 snake_case 分类,不写自由文本、Secret 或个人信息。
```sh
chmod 0600 /opt/qinglong3/commands/approval-decide.json
ql3-approval run --command-file /opt/qinglong3/commands/approval-decide.json
```
成功返回 `decided` 与 version 2 receipt。命令响应丢失时可用同一个 decision ID、decision、reason、User 与 exact action 重试;
返回 `existing` 表示原决定已持久化。不要修改语义后复用 decision ID。
## 安全与故障处理
- action/preview digest 漂移:重新运行 inspect,确认新内容后创建新的 decision command;不要手工替换摘要绕过检查。
- version/state/expiry 冲突:Approval 已变化或过期,不得强制回写;重新检查或创建新的 Approval request。
- credential/Policy fence rejected:检查 credential 是否 active、User RoleBinding 是否仍允许 `approval.decide`。撤权后重试必须失败。
- separation of duty:请求者与决定者相同时会失败;使用另一个具备强认证和权限的 User,不要复制 credential。
- database/audit unavailable:先修复可写性、容量或锁等待。成功 audit 与决定同事务,不需要也不允许手工补写状态。
- CLI 只作决定,不会 consume/dispatch/execute。决定成功后由对应的受信执行面按自己的 start barrier 和恢复协议处理。
Cluster 部署不运行本机 Owner CLI;其独立 mTLS/OIDC 管理面、一次性 client Job 和 PostgreSQL HA 恢复流程见
[`ql3-cluster-approval-management.md`](./ql3-cluster-approval-management.md)。