v2 evidence: bind release evidence with ts/nonce, pin actual-only quota, ledger onboarding checklist, ledger failure outbox, read-only gate verifier (no live wiring)

- cloud/evidence_binding.py: bind/validate/nonce single-use store;
  release endpoint consumes nonce on first validated submission,
  replay -> 409 evidence_replayed, stale/future -> 409
  evidence_stale, partial -> 400, absent -> old path + label.
  Binding blocks exact replay and stale evidence, NOT restamping
  (unsigned evidence cannot prove content freshness).
- cloud/quota.py docstring: actual-only is the v2 integration
  position (already converged in v1 base via fef09ae, NOT in
  main); original PR semantics (#86 all-rows vs #90 actual-only)
  still pending coordinator confirmation at merge time.
- cloud/ledger_onboarding.py: DDL checklist referencing
  PG_DDL/PG_MARKER_DDL constants, read-only verify_ledger_ready
  and ledger_setup_report; default stays OFF, PG DDL stays an
  operator action (never claimed as executed).
- cloud/ledger_outbox.py + worker hook: ledger write failures
  go to a JSONL outbox in addition to the log and can be
  replayed; task outcome still unaffected (rule 7 kept),
  audit fail-closed untouched -- asymmetry documented, not
  silently changed.
- cloud/gate_verification.py: read-only verifier over an
  injected reader (match/mismatch/skipped); live wiring in
  merge/release is NOT possible on the current contract (no
  repo/ref in body or task row, no guaranteed trusted token),
  proven in the module header; no fake verification claimed.
- cloud/tests/test_v2_evidence.py: 18 new tests, all passing.

(cherry picked from commit bd85e33cd5e846fa6ee5d7e2440182dbd9c758b0)
This commit is contained in:
host committed 2026-11-04 21:03:32 +00:00
1 parent f16941347f
commit 27c2acd5d0
9 files changed
+1263 -2

No files matched your search

+16
View File
@@ -7809,6 +7809,22 @@ class Worker:
except Exception as exc:
log_event(self.logger, "worker_attempt_ledger_failed",
message="attempt ledger write failed: %s" % exc)
# 集成 v2(cloud/ledger_outbox):写失败除日志外再
# 进 outbox,运维事后可重放补写——任务状态与返回值
# 仍不受影响(规则 7 原样保留,台账不改 fail-closed,
# 审计 fail-closed 也不动;不对称的剩余部分见
# ledger_outbox 模块头的边界说明)。outbox 追加本身
# 也是 best-effort,失败只吞掉,不抛、不挡任务。
try:
from cloud.ledger_outbox import append_failure \
as _ledger_outbox_append
from cloud.ledger_outbox import outbox_path_for \
as _ledger_outbox_path
_ledger_outbox_append(
_ledger_outbox_path(self.db_path),
task_id, outcome, exc)
except Exception:
pass
return None
def run_one(self, task=None):