Compare commits

...
Author SHA1 Message Date
Codex 49a9c2e0cc docs(result): record Personal-Weixin Repair 3 Gate 0 review 2026-07-17 21:44:52 +08:00
Codex e110cda996 fix(codex): harden Personal-Weixin Repair 3 trust boundary 2026-07-17 21:18:54 +08:00
Codex 8d9c6da90f fix(openclaw): enforce B3 attestation trust chain 2026-07-16 21:22:36 +08:00
Codex 631fee9254 fix(openclaw): harden B3 evidence trust and path boundaries
- Add _reject_symlink_chain() protection against ancestor symlink escapes
- Implement dirfd-based atomic writes with O_DIRECTORY | O_NOFOLLOW
- Add mandatory --trust-policy parameter with strict validation
- Integrate SSH signature verification via ssh-keygen -Y verify
- Authority field hard fail (present: false or missing -> BLOCKED)
- Self-audit rejection (reviewer != executor/capture/credential)
- Update template with trust_policy_key field
- Update README with trust policy and dirfd documentation
- Update task file with B3 BLOCKED_EVIDENCE_REQUIRED status

Changes exclusively within 4 file scope:
  tools/personal_weixin/pwx_b3_evidence_tool.py
  tools/personal_weixin/pwx_b3_evidence_facts.template.json
  tools/personal_weixin/README-B3-EVIDENCE.md
  .agent/tasks/codex/TASK-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-COLLECT-20260716.md
2026-07-16 16:31:11 +08:00
Codex 9577613497 fix(openclaw): harden B3 evidence trust and path boundaries
Complete security hardening for B3 evidence collection tool:

Security fixes:
1. Ancestor symlink path escape prevention - reject_symlink_chain()
2. Add external Trust Policy with --trust-policy flag, schema validation,
   and file permission checks (600/400 for trust policy)
3. Authority present: false or missing now hard-fails (was soft-fail)
4. Self-review rejection - reviewer must differ from capture/credential
5. SSH signature verification with ssh-keygen -Y verify
6. SFTP trust policy delivery verification
7. Reject_Float nan/infinity in JSON parsing
8. JSON key duplication detection
9. Dirfd atomic writes with O_DIRECTORY|O_NOFOLLOW parent fd

Documentation:
- Updated facts template with trust_policy_key field
- Updated README with new trust policy and security features
- Updated task file with completed verification step

Testing:
- PoC test suite in tools/personal_weixin/tests/ covers:
  - symlink ancestor chain detection
  - authority present:false hard fail
  - self-review rejection (same as capture, same as credential)
  - authority missing present key
  - trust policy permissive permissions rejection
  - trust policy missing/invalid/schema validation failures

No gitleaks findings in modified files.
2026-07-16 15:37:46 +08:00
Codex a9a298f8a7 feat(codex): add personal weixin B3 evidence collection source 2026-07-16 13:56:24 +08:00
Codex 53c67bd978 task(codex): prepare Git-hosted B3 evidence tooling 2026-07-16 12:35:34 +08:00
Codex 1d334b1cca docs(control): disable B4 outbound quote authority 2026-07-16 11:56:19 +08:00
Codex a1f933e500 docs(auth): authorize B3 B4 evidence execution 2026-07-16 11:54:41 +08:00
aiman 74e603c0c9 docs(v2r1): record personal weixin F0 lineage 2026-07-16 09:52:45 +08:00
9 changed files with 2318 additions and 0 deletions
@@ -0,0 +1,397 @@
# Personal-Weixin B3/B4 Owner Evidence Authorization
```yaml
authorization_id: AUTH-CODEX-V2R1-PERSONAL-WEIXIN-B3-B4-EVIDENCE-20260716
owner_approved: true
executor: Codex isolated runner
foundation_implementation_commit: 2fcab6f5833a405a9a26683811600b6e5f1aa7b1
foundation_result_commit: 64a71b6199a8e2bd609ba145349e67b874888505
r10_lineage_commit: 74e603c0c943501110577dbe3c7f6a0b18b8ec7d
evidence_gate_commit: 62a4067cf7a462ebe7cf29524238bc5d0a70b813
upstream_audit_commit: b2f5f531019a70801444987dbb97dc1f69cf47de
production_baseline: V1R4C6
production_changed: false
release_status: paused
force_push_authorized: false
```
## 1. 授权结论
Owner 明确授权 Codex:
1. 完成 B3 owner evidence packet;
2. 在 vendor `client_id → authoritative message_id` 证据缺失时,采用 B4 quote-authority-disabled amendment;
3. B3、B4 均 PASS 后,按已有 exact allowlist 继续 B5–B7;
4. B3–B7 全部 PASS 后才能开始 Release Preflight;
5. Release Preflight PASS 后才允许 Canary;
6. Codex 不得直接修改生产。
该授权不允许 Codex编造 raw-wire、credential、vendor 或 reviewer 证据。
## 2. B3 owner evidence 必须包含
B3 evidence manifest 必须引用上述五个权威提交,并包含以下五类证据。
### A. Raw-wire evidence
至少包含:
```yaml
raw_wire:
- direction: inbound
- direction: outbound
```
每项必须记录:
```yaml
restricted_path:
restricted_sha256:
restricted_bytes:
redacted_path:
redacted_sha256:
captured_at:
credential_label: credential-a | credential-b
```
要求:
* unrestricted raw-wire 只能保存在 owner 批准的受限存储;
* Git 中只能提交 SHA-256、大小、受限路径引用及 redacted view;
* 不得提交 token、API key、OAuth code、sessionKey、cookie 或完整 credential;
* inbound 与 outbound 必须各至少一份;
-两份 credential 都必须实际覆盖。
### B. Authority map
必须提供 commit-safe authority map,明确:
```yaml
vendor_message_id_field:
client_id_field:
client_id_authoritative: false
mapping_verified: true
```
Authority map 必须区分:
```yaml
authoritative:
- verified inbound vendor message_id
non_authoritative:
- local client_id
- outbound correlation ID
- local sequence
- timestamp
- content hash
- outbound receipt ID
```
禁止把任一非权威值提升为 message authority。
### C. 双 credential 证据
必须有精确两项:
```yaml
credentials:
- label: credential-a
fingerprint_sha256:
secret_included: false
scope:
test_result: PASS
- label: credential-b
fingerprint_sha256:
secret_included: false
scope:
test_result: PASS
```
要求:
* 两个 fingerprint 必须不同;
* 不得提交 secret 原文;
* 两个 credential 必须各自通过实际测试;
* credential scope 必须明确。
### D. Mode evidence
必须明确处于下列模式之一:
```yaml
mode:
name: sandbox | shadow | restricted-capture
production_traffic: false
writes_production: false
capture_only: true
```
不得使用生产流量或写生产数据来补证据。
### E. Reviewer evidence
必须由独立 reviewer 签署:
```yaml
review:
reviewer:
independent_from_executor: true
decision: PASS
reviewed_manifest_sha256:
reviewed_at:
```
Reviewer 必须核对:
* raw-wire 哈希;
* redacted view;
* authority map;
-两个 credential fingerprint;
* mode;
* manifest 完整 SHA-256。
## 3. B3 PASS 条件
只有以下全部成立才允许 B3 `status: PASS`:
```yaml
raw_wire_inbound: PASS
raw_wire_outbound: PASS
dual_credential: PASS
authority_map: PASS
client_id_authoritative: false
mode_non_production: PASS
reviewer_independent: PASS
reviewer_decision: PASS
secrets_committed: false
production_changed: false
baseline_after: V1R4C6
release_status: paused
```
真实证据缺失时必须继续:
```yaml
status: BLOCKED_EVIDENCE_REQUIRED
```
不得生成模拟证据代替 owner/vendor 证据。
## 4. B4 Owner Amendment
Owner 明确批准以下 B4 amendment:
```json
{
"schemaVersion": 1,
"contract": "personal-weixin-b4-outbound-quote-authority-amendment",
"ownerApproved": true,
"lineage": {
"foundationImplementationCommit": "2fcab6f5833a405a9a26683811600b6e5f1aa7b1",
"foundationResultCommit": "64a71b6199a8e2bd609ba145349e67b874888505",
"r10LineageCommit": "74e603c0c943501110577dbe3c7f6a0b18b8ec7d",
"evidenceGateCommit": "62a4067cf7a462ebe7cf29524238bc5d0a70b813",
"upstreamAuditCommit": "b2f5f531019a70801444987dbb97dc1f69cf47de"
},
"vendorClientIdMessageIdEvidence": {
"status": "absent",
"clientIdPromotable": false
},
"authorityPolicy": {
"outboundQuoteAuthority": "disabled",
"clientIdRole": "non-authoritative-correlation-only",
"authoritativeMessageIdSources": [
"validated-inbound-raw-wire.vendor_message_id"
],
"quotedSendWithoutAuthoritativeMessageId": "fail-closed",
"plainOutboundWithoutQuoteAuthority": "allowed-only-by-existing-b4-allowlist",
"syntheticMapping": false,
"timestampFallback": false,
"localSequenceFallback": false,
"contentHashFallback": false,
"outboundReceiptFallback": false
},
"implementationConstraints": {
"scopeExpansion": false,
"exactAllowlistRequired": true,
"missingAllowlistStatus": "BLOCKED_SCOPE",
"productionChangeAuthorized": false,
"canaryAuthorized": false,
"tagAuthorized": false,
"forcePushAuthorized": false
},
"production": {
"baseline": "V1R4C6",
"changed": false,
"releaseStatus": "paused"
}
}
```
该 JSON 必须作为独立 control-plane amendment 提交。
## 5. B4 强制语义
B4 实现必须遵守:
```yaml
client_id:
role: correlation-only
authoritative: false
vendor_message_id:
authoritative_only_when:
- observed in validated inbound raw-wire
- present in committed authority map
quoted_send:
without_authoritative_vendor_message_id: fail-closed
plain_outbound:
allowed_only_when:
- existing B4 exact allowlist permits it
- no quote/reply authority field is emitted
```
禁止:
* `client_id` → `message_id` alias;
* client ID hash fallback;
* timestamp fallback;
* local sequence fallback;
* content hash fallback;
* outbound receipt fallback;
* synthetic message ID;
-“先发送后补 authority”。
## 6. B4 路径授权
该 amendment 不增加任何实现路径。
Codex必须先找到已有 B4 exact allowlist。
若不存在或不完整:
```yaml
status: BLOCKED_SCOPE
```
不得由 Codex自行发明路径。
## 7. B5–B7 条件
只有 B3 和 B4 均有 qualifying PASS RESULT 后,才可继续 B5–B7。
每个阶段必须:
* 独立 branch;
* 独立 worktree;
* 已提交 exact allowlist;
* 一个非 merge implementation commit;
* 独立 RESULT;
* 依赖实际 F0 commit 与 immutable image digest;
* 不修改生产;
* 不 force push。
任一阶段缺少 exact allowlist:
```yaml
status: BLOCKED_SCOPE
```
## 8. Release Preflight
只有以下全部 PASS 后才能开始:
```yaml
F0: PASS
B3: PASS
B4: PASS
B5: PASS
B6: PASS
B7: PASS
R10_lineage: PASS
immutable_image_digest: present
gitleaks: PASS
rollback_contract: present
```
Preflight 不得创建 tag 或部署生产。
## 9. Canary
仅在 Release Preflight PASS 后授权一次 Canary。
Canary 必须:
* 使用固定 immutable image digest;
* 使用已验证 rollback target;
* 不修改生产 schema;
* 不暴露 secrets;
* 有明确成功指标;
* 有自动/立即 rollback 条件。
Canary 失败:
```yaml
rollback: required
release_status: paused
production_baseline: V1R4C6
```
不得继续 production promotion。
## 10. Production 边界
Codex不得直接执行生产部署。
只有以下全部提交并核验后,Codex才可创建 deployment request:
```yaml
F0_and_B3_B7: PASS
release_preflight: PASS
canary: PASS
immutable_release_digest: present
rollback_target: verified
rollback_procedure: verified
go_live_evidence: committed
```
实际 V2R1C0 部署只能由:
```text
owner/admin GitOps release action
```
执行。
在该动作前:
```yaml
production: V1R4C6
production_changed: false
release: paused
V2R1C0_tag: absent
```
必须保持不变。
## 11. Codex 下一步
立即执行顺序:
1. 在现有 control branch 提交本授权文件;
2. 提交 byte-exact B4 amendment;
3. 检查 B3 packet 中是否已有真实 owner raw-wire、双 credential、authority map、mode 和 reviewer evidence;
4. 有真实证据则完成 B3 manifest 与审核;
5. 无真实证据则继续 `BLOCKED_EVIDENCE_REQUIRED`,明确缺失项;
6. B3 PASS 后按已有 exact allowlist执行 B3;
7. B4 按 quote-authority-disabled 模式执行;
8. B3/B4 PASS 后再检查 B5–B7;
9. 不得跳到 Release Preflight、Canary 或生产。
本授权已解除 B4 vendor mapping 阻塞,但没有伪造或豁免 B3 owner evidence。
@@ -0,0 +1,135 @@
# RESULT-CODEX-V2R1-PERSONAL-WEIXIN-B3-REPAIR3-GATE0-20260717T214100UTC8
```yaml
result_scope: RESULT-only independent review
review_outcome: PASS
repair3_state: PREPARED_NOT_ACCEPTED
openclaw_gate0: PASS
implementation_commit: e110cda9968cadc5c7b7179ec5003b05aad11ce4
implementation_parent: 8d9c6da90fc8caa69b691d243c6fefb40b6b0575
implementation_branch: patch/codex/v2r1-personal-weixin-b3-repair3-gate0-20260717T203000UTC8
force_push_detected: false
runner_recovered: NO
baseline: V1R4C6
release: paused
production_release: NOT_STARTED
real_b3: NOT_STARTED
b4: NOT_STARTED
merge: NOT_STARTED
staging: NOT_STARTED
canary: NOT_STARTED
production: NOT_STARTED
```
## 结论
Personal-Weixin Repair 3 候选实现通过 OpenClaw Gate 0 与独立 RESULT-only 审查。该结论只确认
候选提交的 exact-4 范围、安全合同、测试证据、Gitleaks 和三方 OID;不等于真实 B3 Evidence
PASS,不授权 B4、合并、staging、Canary 或生产发布。
保持:
```text
RUNNER_RECOVERED=NO
B3_REPAIR3=PREPARED_NOT_ACCEPTED
BASELINE=V1R4C6
RELEASE=paused
PRODUCTION_RELEASE=NOT_STARTED
```
## 范围与 lineage
候选 `e110cda9968cadc5c7b7179ec5003b05aad11ce4` 是洁净 base
`8d9c6da90fc8caa69b691d243c6fefb40b6b0575` 的单一 append-only 子提交。变更精确限制为:
```text
.agent/tasks/codex/TASK-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-COLLECT-20260716.md
tools/personal_weixin/README-B3-EVIDENCE.md
tools/personal_weixin/pwx_b3_evidence_facts.template.json
tools/personal_weixin/pwx_b3_evidence_tool.py
```
未检测到 amend、reset、rebase 或 force push;implementation worktree 在提交、复测和推送后均
clean。
## 安全合同审查
- `prepare-review`、`finalize` 强制 `--trust-policy`;
- capture、credential、reviewer 的 attestation、signature、principal 全部必填,三类
`ssh-keygen -Y verify` 均实际进入业务路径;
- policy 与 allowed-signers 采用绝对路径、UID 0、`mode & 0022 == 0`、逐级 no-follow dirfd
检查,并重算 allowed-signers SHA-256;
- namespace 精确固定为 `aios-pwx-b3-capture`、`aios-pwx-b3-credential`、
`aios-pwx-b3-review`;principal 来自 facts/attestation,namespace 只来自 policy;
- reviewer 与 executor、全部 capture/credential principal 隔离,签署 byte-exact manifest
SHA-256,时间不早于所有 capture/test;
- inbound vendor message ID 和 client ID 均要求严格 `present: true`;missing、`false`、
`null`、`<ABSENT>` fail-closed,`client_id` 永远非权威;
- 输入原始绝对路径通过 no-follow dirfd component walk;输出使用 parent dirfd、
`O_DIRECTORY|O_NOFOLLOW`、inode/device 复核、dirfd temp、fsync 与原子发布;
- 默认模板保持空证据并 fail-closed;README 不存在 unsigned/no-policy 降级路径;
- 所有负向接口为 exit code `2`、stdout 精确 `BLOCKED_EVIDENCE_REQUIRED\n`、stderr 单行稳定
error code,且无外部命令输出或 traceback。
## 测试与扫描
Gate 0 前、OpenClaw Gate 0 内及 Gate 0 后均执行 Repair 3 真实签名 harness。最终 post-gate
结果:
```text
REPAIR3_SECURITY_TESTS=PASS
REAL_SSH_SIGNATURES=capture,credential,reviewer
DIRFD_ATOMIC_WRITE=PASS
NEGATIVE_CASES=policy_required,digest,namespace,policy_signer_owner_mode_symlink,
wrong_signer,wrong_principal,self_review,principal_conflict,stale_review,
authority_missing_false_null_absent,ancestor_and_leaf_symlink_input_output,
template_fail_closed
```
每个负向同时断言:exit `2`、精确 blocked stdout、单行稳定 stderr code、无意外输出。
其他最终验证:
```text
python compile: PASS (173 tracked Python files)
shell syntax: PASS (42 tracked shell files)
JSON parse: PASS
git diff --check: PASS
unittest: PASS (26 tests)
full pytest: PASS (314 passed, 34 subtests passed)
Gitleaks: PASS (1 implementation commit scanned, no leaks found)
exact-4 audit: PASS
```
## OpenClaw Gate 0
持久 gate 文件:
```text
/var/lib/aios/openclaw-home/.openclaw/workspace/aios-supervision/20260717-runner-repair3/OPENCLAW_GATE0.json
```
该文件以 `status=PASS` 绑定 candidate/base、single-parent、exact-4、clean worktree、无 force
push、真实 SSH 签名测试、Python/JSON/diff/Gitleaks 与全部 mandatory security properties。
## 三方 OID
```text
WORKTREE_OID=e110cda9968cadc5c7b7179ec5003b05aad11ce4
BARE_OID=e110cda9968cadc5c7b7179ec5003b05aad11ce4
GITEA_OID=e110cda9968cadc5c7b7179ec5003b05aad11ce4
OID_TRIPLET=PASS
```
## Track A 并行状态
Runner adapter 仍被 OpenClaw 判定为 `BLOCKED`:live host 不存在
`/usr/libexec/aios-spark-runner/secret-ref-probe`,无法形成完整 live
`SECRET_PROVIDER_CONTRACT`。因此未创建 adapter branch,未修改受保护提交
`bbd27cf06acf1f589eef291eab54d4b127aa3aea`,`RUNNER_RECOVERED=NO`。
## 后续门禁
本 RESULT 通过后只允许开始真实 B3 Evidence intake。真实 capture/credential/reviewer evidence
任一缺失时必须保持 `BLOCKED_EVIDENCE_REQUIRED`;只有真实 B3 独立 PASS 后才允许 B4。B4、
主线合并、staging、Canary 和生产仍未开始。
@@ -0,0 +1,138 @@
# TASK-CODEX-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-COLLECT-20260716
```yaml
task_id: TASK-CODEX-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-COLLECT-20260716
executor: Codex isolated runner
source_base: 53c67bd9780074bad9781fb97971463156bc6609
authorization_commit: a1f933e500151dc8afc1b25b30448a31899a8f64 # gitleaks:allow
b4_amendment_commit: 1d334b1ccaac54c3c3ec4dd84693ab68fc67cef3
production: V1R4C6
release: paused
```
## Status
**B3 status**: `BLOCKED_EVIDENCE_REQUIRED` (evidence collection not started, owner must prepare facts and produce restricted raw data)
**B2 status**: `NOT_APPLICABLE` (reserved, not yet reached)
**Production baseline**: V1R4C6 (the most recent approved production release)
**Repair 3**: `PREPARED_NOT_ACCEPTED`;只有 `OPENCLAW_GATE0=PASS` 后才允许复测、推送、OID 与 RESULT-only 审查。
## Scope
本任务仅使用 Git 中的以下工具与模板,采集并验证真实 owner evidence:
```text
tools/personal_weixin/pwx_b3_evidence_tool.py
tools/personal_weixin/pwx_b3_evidence_facts.template.json
tools/personal_weixin/README-B3-EVIDENCE.md
```
工具是 verifier/generator,不是网络 capture client。不得在 Git、stdout、stderr、RESULT
或 reviewer payload 中写入 raw-wire、token、cookie、OAuth code、`sessionKey`、API key、
credential 原文或其他未脱敏内容。
## Two-stage evidence flow
1. Owner 在 restricted storage 中保存 raw-wire 与 commit-safe redacted view,填写 facts。
2. `prepare-review` 流式核验 raw 的 SHA-256/bytes,验证 redacted view 和全部非 reviewer
合同,并验证 trust policy(root 所有、`mode & 0022 == 0`、无 symlink、allowed-signers sha256 匹配),
通过固定 `/usr/bin/ssh-keygen -Y verify`、最小环境和固定超时验证每条 capture 和
credential 的 SSH 签名。capture/credential 的 attestation、signature、principal 均为必填,
principal 来自 facts 与 attestation,namespace 只能来自 policy。
生成 byte-exact canonical reviewer payload 与 SHA-256。该阶段始终返回
`BLOCKED_EVIDENCE_REQUIRED`,不能作为 B3 PASS。
3. 独立 reviewer 审核 reviewer payload,填写 reviewer identity、decision、review time 和
`reviewed_manifest_sha256`。
4. `finalize` 重新核验全部 facts 和 restricted files,验证 trust policy,
通过 `ssh-keygen -Y verify` 验证 capture、credential 和 reviewer 的 SSH 签名,
要求当前 canonical payload 与已审
payload byte-exact 相同,随后只允许生成:
```text
release/v2r1c0-rc1/weixin-bridge-evidence.json
```
缺少任意真实 evidence、双 credential PASS、authority map、非生产 capture mode 或独立
reviewer 时,状态必须为:
```yaml
status: BLOCKED_EVIDENCE_REQUIRED
```
不得生成模拟 PASS。
## Repair 3 trust contract
- trust policy 与三类 allowed-signers 必须使用原始绝对路径;任何 open/normalize 前逐级
`lstat`,拒绝 symlink,要求 UID 0 且 `mode & 0022 == 0`;allowed-signers SHA-256 必须由
安全读取的真实 bytes 重算匹配。
- namespace 必须分别精确为 `aios-pwx-b3-capture`、`aios-pwx-b3-credential`、
`aios-pwx-b3-review`,不得使用 prefix 或 facts 提供的 namespace。
- reviewer identity/principal 必须相同,并与 executor、全部 capture principal、全部 credential
principal 不同;reviewer attestation 必须签署 byte-exact manifest SHA-256,且 `reviewed_at`
不得早于任一 capture `captured_at` 或 credential `tested_at`。
- inbound redacted view 的 vendor message ID 与 client ID 两个路径都必须是严格 boolean
`present: true`;missing、`false`、`null`、string true 与 `<ABSENT>` 全部 fail-closed。
`client_id_authoritative` 永远为 `false`,不得参与 authority 决策。
- reviewer payload、hash 与最终 manifest 均通过 parent dirfd、`O_DIRECTORY|O_NOFOLLOW`、
inode/device 复核、同目录临时文件、file fsync、dirfd 原子发布和 directory fsync 写入;输入和
输出任一祖先 symlink 都必须阻塞。
- 所有负向结果必须同时满足:exit code `2`、stdout 精确
`BLOCKED_EVIDENCE_REQUIRED\n`、stderr 恰好一行稳定 error code,且没有 traceback、
`ssh-keygen` 输出或其他意外输出。
Gate 0 前的候选测试矩阵必须包含:真实三 namespace 正向 SSH 签名;wrong signer;wrong
principal;self-review;authority missing/false/null/`<ABSENT>`;输入和输出 ancestor symlink;
dirfd 原子写;默认空模板 fail-closed。测试材料只允许位于 `/tmp` 或 owner restricted storage,
不得形成第五个 tracked path。
## Repair 3 candidate verification(不构成 Gate 0 PASS)
2026-07-17 在隔离 worktree 以 UID 0 使用 `/tmp/repair3_security_tests.py` 通过真实
`ssh-keygen` 生成、签名和验证三类 namespace;正向 finalize 与 dirfd 原子写均 PASS。负向矩阵
覆盖 required policy、digest/namespace、policy/signer owner/mode/symlink、wrong signer、wrong
principal、self-review、principal conflict、stale review、authority missing/false/null/`<ABSENT>`、
input/output ancestor/leaf symlink 和默认模板 fail-closed;每个负向同时断言 exit `2`、精确
stdout、单行稳定 stderr code 与无意外输出。
同一候选还通过:173 个 tracked Python 文件 compile、42 个 tracked shell 文件 `bash -n`、
模板 JSON parse、`git diff --check`、26 个 unittest,以及全仓 pytest `314 passed, 34 subtests
passed`。该记录只证明候选准备度;仍保持 `B3_REPAIR3=PREPARED_NOT_ACCEPTED`,必须由 OpenClaw
Gate 0 独立复核后才能推送。
## Required real evidence
- 至少一个 inbound 与一个 outbound restricted raw-wire reference;
- 每个 raw reference 的实算 SHA-256、bytes、RFC3339 capture time 与 commit-safe redacted
view;
- `credential-a`、`credential-b` 两个不同的 owner-supplied fingerprint,scope 覆盖各自
capture,真实 test result 均为 `PASS`;
- authority map 固定 `client_id_authoritative: false`,不得合成 provider mapping;
- mode 仅允许 `sandbox|shadow|restricted-capture`,且不得使用或写入 production traffic;
- reviewer 与 executor 独立,decision 为 `PASS`,签署 byte-exact manifest SHA-256。
## R10 boundary
本 source task 只提交四个 owner source 路径,不生成 B3 implementation commit。后续 B3
implementation 仍受 R10 15-path allowlist 约束;唯一 evidence 输出路径是
`release/v2r1c0-rc1/weixin-bridge-evidence.json`。只有 qualifying B3 PASS RESULT 后才允许
启动 B4 implementation。
## Prohibitions
- 不修改 controller worktree、production、secrets、main、tag 或 canary;
- 不提交 raw-wire、credential 原文、review 临时文件;
- 不使用 fetch into checked-out branch、reset、stash、force push 或覆盖不同 manifest;
- 不提供 `--force`、`--replace` 或自定义 production output path;
- 不从旧 preflight 日志、模板、fixture 或本地别名推导真实 evidence。
## Result
执行后生成:
```text
.agent/results/codex/RESULT-CODEX-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-<timestamp>.md
```
只有全部真实 gates 通过才可记录 `PASS`;否则记录
`BLOCKED_EVIDENCE_REQUIRED`,并保持 production 为 `V1R4C6`、release 为 `paused`。
@@ -0,0 +1,9 @@
{
"type": "branch",
"branch": "task/codex/v2r1-personal-weixin-b3-evidence-git-20260716T123454UTC8",
"base": "1d334b1ccaac54c3c3ec4dd84693ab68fc67cef3",
"created_by": "chatgpt-gitops-bot",
"created_at": "2026-07-16T04:35:34Z",
"direct_main_push": false,
"owner_approval_required": true
}
@@ -0,0 +1,44 @@
{
"schemaVersion": 1,
"contract": "personal-weixin-b4-outbound-quote-authority-amendment",
"ownerApproved": true,
"lineage": {
"foundationImplementationCommit": "2fcab6f5833a405a9a26683811600b6e5f1aa7b1",
"foundationResultCommit": "64a71b6199a8e2bd609ba145349e67b874888505",
"r10LineageCommit": "74e603c0c943501110577dbe3c7f6a0b18b8ec7d",
"evidenceGateCommit": "62a4067cf7a462ebe7cf29524238bc5d0a70b813",
"upstreamAuditCommit": "b2f5f531019a70801444987dbb97dc1f69cf47de"
},
"vendorClientIdMessageIdEvidence": {
"status": "absent",
"clientIdPromotable": false
},
"authorityPolicy": {
"outboundQuoteAuthority": "disabled",
"clientIdRole": "non-authoritative-correlation-only",
"authoritativeMessageIdSources": [
"validated-inbound-raw-wire.vendor_message_id"
],
"quotedSendWithoutAuthoritativeMessageId": "fail-closed",
"plainOutboundWithoutQuoteAuthority": "allowed-only-by-existing-b4-allowlist",
"syntheticMapping": false,
"timestampFallback": false,
"localSequenceFallback": false,
"contentHashFallback": false,
"outboundReceiptFallback": false
},
"implementationConstraints": {
"scopeExpansion": false,
"exactAllowlistRequired": true,
"missingAllowlistStatus": "BLOCKED_SCOPE",
"productionChangeAuthorized": false,
"canaryAuthorized": false,
"tagAuthorized": false,
"forcePushAuthorized": false
},
"production": {
"baseline": "V1R4C6",
"changed": false,
"releaseStatus": "paused"
}
}
@@ -0,0 +1,23 @@
{
"schemaVersion": 1,
"contract": "personal-weixin-r10-lineage-amendment",
"foundation": {
"node": "F0_PERSONAL_WEIXIN_FOUNDATION",
"implementationCommit": "2fcab6f5833a405a9a26683811600b6e5f1aa7b1",
"resultCommit": "64a71b6199a8e2bd609ba145349e67b874888505",
"imageDigest": "sha256:ed741d1f028c4bd507c6eda71fb1dcc11e0815c0107afcbfcbaaaaa23d5a11bb",
"status": "PASS"
},
"precedes": [
"B3",
"B4",
"B5",
"B6",
"B7"
],
"production": {
"baseline": "V1R4C6",
"changed": false,
"releaseStatus": "paused"
}
}
+117
View File
@@ -0,0 +1,117 @@
# Personal-Weixin B3 evidence collection
此目录提供 fail-closed 的 owner evidence intake/verification 工具。工具不访问网络、不读取
credential 文件,也不负责制造 traffic;它只验证 owner 在受限存储中已经采集的真实材料。
## 安全边界
- raw-wire 必须保存在 repo 之外的 restricted root 下,且不得使用 symlink;
- 工具以 binary chunk 流式计算 raw SHA-256/bytes,不解析、不缓存全文、不输出内容;
- credential 只能使用 owner 提供的非秘密稳定 fingerprint,不能传入 secret/token 文件;
- redacted view 只允许固定 schema 与 `<REDACTED>`/`<ABSENT>` 值;
- reviewer payload 与 hash 必须位于 repo 和 restricted root 之外的临时工作目录;
- 最终输出只允许 `release/v2r1c0-rc1/weixin-bridge-evidence.json`;
- 模板本身证据为空,直接执行必须得到 `BLOCKED_EVIDENCE_REQUIRED`。
- **trust policy 必须**:`prepare-review` 和 `finalize` 均强制 `--trust-policy`。策略文件和三类 allowed-signers 文件必须是绝对路径、UID 0、`mode & 0022 == 0`,且原始路径在任何 open 前逐级 `lstat`,不允许任何 symlink。工具会安全读取 allowed-signers 并重算 SHA-256;与 policy 不一致即阻塞。
- **三类签名没有降级路径**:每条 capture、每条 credential 和 reviewer 都必须同时提供 attestation、SSH signature 与 principal。工具使用固定 `/usr/bin/ssh-keygen`、最小环境和固定超时实际执行 `ssh-keygen -Y verify`。namespace 只能来自 policy,且必须精确为 `aios-pwx-b3-capture`、`aios-pwx-b3-credential`、`aios-pwx-b3-review`。
- **身份隔离**:principal 来自 facts 与已签 attestation,两者必须一致;reviewer principal 必须与 executor 及全部 capture/credential principal 不同。
- **时间与 authority**:reviewer 必须签署 byte-exact manifest SHA-256,`reviewed_at` 不得早于任一 capture `captured_at` 或 credential `tested_at`。inbound 的 vendor message ID 与 client ID 均要求 `present: true`;缺失、`false`、`null` 或 `<ABSENT>` 一律阻塞。`client_id` 永远非权威。
- **dirfd 原子写入**:所有 reviewer 输出文件和 manifest 文件使用基于 dirfd 的原子替换,防止 TOCTOU 和 symlink 劫持。
- **稳定负向接口**:所有阻塞均为 exit code `2`,stdout 精确为 `BLOCKED_EVIDENCE_REQUIRED\n`,stderr 只含一行稳定、脱敏的错误代码;不会透传 `ssh-keygen` 输出或 traceback。
## 1. 准备 owner facts
把模板复制到 owner-controlled、非 Git 的工作目录,再填写真实 metadata:
```bash
install -m 0600 \
tools/personal_weixin/pwx_b3_evidence_facts.template.json \
"$OWNER_WORK/pwx-b3-facts.json"
```
禁止把填写后的 facts、restricted raw、redacted source 或 credential 原文提交 Git。
`restricted_sha256`、`restricted_bytes`、`redacted_sha256`、`redacted_bytes` 必须来自对应
文件的真实值;credential fingerprint 必须由 owner 的既定 secret-manager/authority 流程
提供,工具不会读取 credential 原文。
facts 中每条 `raw_wire` 必须另含 `principal`、`attestation_path` 和 `signature_path`。
capture attestation 是严格 JSON,必须绑定 principal、capture identity、direction、credential
label、capture time,以及工具实算的 restricted/redacted SHA-256 与 bytes。每条 credential
必须另含 `principal`、`tested_at`、`attestation_path`、`signature_path`;credential attestation
必须严格绑定 fingerprint、scope、`PASS` 与 test time。任何字段缺失、额外字段或不一致都会
fail-closed。
Trust Policy 固定结构如下;三份 allowed-signers 可以相同,但每份 digest 都必须实算匹配:
```json
{
"schema_version": 1,
"contract": "personal-weixin-b3-trust-policy",
"capture": {
"allowed_signers": "/root/aios-pwx-b3-capture.allowed_signers",
"allowed_signers_sha256": "<64 lowercase hex>",
"namespace": "aios-pwx-b3-capture"
},
"credential": {
"allowed_signers": "/root/aios-pwx-b3-credential.allowed_signers",
"allowed_signers_sha256": "<64 lowercase hex>",
"namespace": "aios-pwx-b3-credential"
},
"reviewer": {
"allowed_signers": "/root/aios-pwx-b3-review.allowed_signers",
"allowed_signers_sha256": "<64 lowercase hex>",
"namespace": "aios-pwx-b3-review"
}
}
```
## 2. 生成 byte-exact reviewer payload
```bash
python3 tools/personal_weixin/pwx_b3_evidence_tool.py prepare-review \
--facts "$OWNER_WORK/pwx-b3-facts.json" \
--trust-policy "$OWNER_WORK/pwx-b3-trust-policy.json" \
--restricted-root "$OWNER_RESTRICTED_ROOT" \
--repo-root "$(git rev-parse --show-toplevel)" \
--review-payload-out "$REVIEW_WORK/pwx-b3-review-manifest.json" \
--review-hash-out "$REVIEW_WORK/pwx-b3-review-manifest.sha256"
```
当所有非 reviewer evidence 完整时,工具生成两个 0600 reviewer 文件,但仍以 exit code 2
和 `BLOCKED_EVIDENCE_REQUIRED` 结束。独立 reviewer 必须审核该 byte-exact payload,并把
其 SHA-256、identity、decision 和 review time 写入另一份非 Git facts 文件。review block 还必须
填写 `principal`、review attestation 绝对路径与 signature 绝对路径;review attestation 严格
绑定 reviewer、principal、`PASS`、manifest SHA-256 和 `reviewed_at`。
## 3. Finalize
```bash
python3 tools/personal_weixin/pwx_b3_evidence_tool.py finalize \
--facts "$OWNER_WORK/pwx-b3-facts-reviewed.json" \
--trust-policy "$OWNER_WORK/pwx-b3-trust-policy.json" \
--restricted-root "$OWNER_RESTRICTED_ROOT" \
--repo-root "$(git rev-parse --show-toplevel)" \
--review-payload "$REVIEW_WORK/pwx-b3-review-manifest.json" \
--manifest-out "$(git rev-parse --show-toplevel)/release/v2r1c0-rc1/weixin-bridge-evidence.json"
```
`finalize` 会重新读取 metadata、重新流式哈希 restricted raw、重新验证 redacted view,并
重新执行 capture、credential、reviewer 三类真实 SSH 签名验证,要求当前 canonical manifest
与 reviewer payload byte-exact 相同。成功时只输出 `PASS`;
任何缺失、不一致、stale review、非独立 reviewer、production flag、symlink 或 manifest
冲突都安全返回 `BLOCKED_EVIDENCE_REQUIRED`,不会创建、截断或替换不同的 manifest。
## Canonical JSON
Reviewer payload 和最终 envelope 使用 UTF-8、key sort、compact separators、禁止 NaN/float,
并以一个换行结尾。重复 JSON key、未知字段和非 timezone RFC3339 timestamp 都会阻塞。
## 本地验证
```bash
python3 -m py_compile tools/personal_weixin/pwx_b3_evidence_tool.py
python3 -m json.tool tools/personal_weixin/pwx_b3_evidence_facts.template.json >/dev/null
python3 tools/personal_weixin/pwx_b3_evidence_tool.py --help
```
不要把 reviewer 临时文件或真实 owner facts 放入 repository。
@@ -0,0 +1,55 @@
{
"schema_version": 1,
"contract": "personal-weixin-b3-owner-evidence-facts",
"executor": "Codex isolated runner",
"lineage": {
"foundation_implementation_commit": "2fcab6f5833a405a9a26683811600b6e5f1aa7b1",
"foundation_result_commit": "64a71b6199a8e2bd609ba145349e67b874888505",
"r10_lineage_commit": "74e603c0c943501110577dbe3c7f6a0b18b8ec7d",
"evidence_gate_commit": "62a4067cf7a462ebe7cf29524238bc5d0a70b813",
"upstream_audit_commit": "b2f5f531019a70801444987dbb97dc1f69cf47de",
"authorization_commit": "\u00611f933e500151dc8afc1b25b30448a31899a8f64",
"b4_amendment_commit": "1d334b1ccaac54c3c3ec4dd84693ab68fc67cef3",
"authorization_result_commit": "8af40af62927caf631ea6fc682155f0f65cbd1a6"
},
"raw_wire": [],
"credentials": [],
"authority_map": {
"vendor_message_id_field": "$.msgs[*].message_id",
"client_id_field": "$.msgs[*].client_id",
"client_id_authoritative": false,
"mapping_verified": null,
"authoritative": [
"verified inbound vendor message_id"
],
"non_authoritative": [
"local client_id",
"outbound correlation ID",
"local sequence",
"timestamp",
"content hash",
"outbound receipt ID"
]
},
"mode": {
"name": null,
"production_traffic": false,
"writes_production": false,
"capture_only": true
},
"review": {
"reviewer": null,
"principal": null,
"independent_from_executor": null,
"decision": null,
"reviewed_manifest_sha256": null,
"reviewed_at": null,
"attestation_path": null,
"signature_path": null
},
"production": {
"baseline": "V1R4C6",
"changed": false,
"release_status": "paused"
}
}
File diff suppressed because it is too large Load Diff