fix(ops): address provenance gate review findings

Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-09-13 16:12:55 +09:00
committed by Hermes Agent
co-authored by genichin
parent 8d9d627b1c
commit 619feff5f4
3 changed files with 18 additions and 5 deletions
+1
View File
@@ -65,6 +65,7 @@ python scripts/release_provenance_gate.py \
- `--image-digest`와 `--runtime-file` 검증 결과(sha256 + revision 일치 여부)가 JSON record에 저장된다.
- actor/timestamp/instance/command-class/reason이 JSON record에 함께 저장되어 stop/start/recreate 감사 추적이 가능하다.
- PRE/POST 모두 실행해 재기동 전후의 `pending_slots`, `reconciliation_slots`, `queue_consumers`, broker-side-effect 로그(`order_submit/fill/reject/cancel`)를 자동 캡처한다.
- broker-side-effect 로그 입력은 기본 `/tmp/trex-core.log`를 사용하며, 로그 파일 위치가 다르면 `--broker-log-path <path>`로 명시한다.
- 이 스크립트는 read-only capture 전용이다. 주문 제출·취소, DB 복구, 자동 sync/verify live 실행을 암묵적으로 수행하지 않는다.
재기동 후에는 동일 명령(예: `--command-class "manual-start"`)으로 POST record를 추가 저장한다.
+14 -3
View File
@@ -72,7 +72,16 @@ def main(argv: list[str] | None = None) -> int:
output_dir.mkdir(parents=True, exist_ok=True)
output_path = _record_path(output_dir, instance=args.instance, command_class=args.command_class)
if report["checkout"]["dirty_paths"] and not args.allow_dirty:
dirty_checkout = bool(report["checkout"]["dirty_paths"])
runtime_ok = all(
item.get("matches_expected_revision", False) for item in report["runtime_file_verification"]
)
oci_ok = bool(report["artifact_identity"]["oci_revision_matches_head"])
allow_dirty_passed = bool(args.allow_dirty and dirty_checkout and runtime_ok and oci_ok)
report["gate"]["allow_dirty"] = bool(args.allow_dirty)
report["gate"]["allow_dirty_passed"] = allow_dirty_passed
if dirty_checkout and not args.allow_dirty:
report["dirty_checkout_isolation"] = isolate_dirty_checkout_files(
checkout_dir=args.checkout_dir,
isolate_dir=args.isolate_dir,
@@ -80,9 +89,11 @@ def main(argv: list[str] | None = None) -> int:
output_path.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
print(str(output_path))
if report["checkout"]["dirty_paths"] and not args.allow_dirty:
if dirty_checkout and not args.allow_dirty:
return 2
return 0 if report["gate"]["passed"] else 1
if report["gate"]["passed"] or allow_dirty_passed:
return 0
return 1
if __name__ == "__main__":
+3 -2
View File
@@ -98,9 +98,10 @@ def _sha256_bytes(payload: bytes) -> str:
def _resolve_under(root: Path, relpath: str) -> Path | None:
candidate = (root / relpath).resolve()
resolved_root = root.resolve()
candidate = (resolved_root / relpath).resolve()
try:
candidate.relative_to(root)
candidate.relative_to(resolved_root)
return candidate
except ValueError:
return None