Files
trex-core/.proofline/lines/line-0010/dcy-0010.md
T

13 KiB

id, status
id status
dcy-0010 confirmed

운영 provenance 검증 계약과 audit checkout 증거 무결성

Problem

PR #93은 audit checkout의 clean/detached/expected revision, runtime file hash, image digest 형식과 PRE/POST 상태 capture를 검사하는 release_provenance_gate.py를 추가했다. 현재 gate는 개별 record를 생성하지만, 실행 환경이 관측한 target·image identity를 명시적인 expected/observed 구조로 보존하지 않고 같은 operation의 PRE/POST record가 한 쌍인지 검증하거나 최종 manifest로 묶지 않는다. Dirty checkout 격리는 파일을 checkout 밖에 복사하지만 각 파일의 hash·type·복사 성공 여부를 manifest에 남기지 않아 보존본이 원본과 같은 bytes인지 사후 검증하기 어렵다.

실제 Docker Compose/container 또는 host process 선택, runtime inspect, stop/start/recreate/deploy 실행, 전역 operation lock, audit checkout 교체와 maintenance window 승인은 배포 환경을 소유한 운영 계층의 책임이다. trex-core가 특정 runtime을 선택하거나 lifecycle command를 실행하면 application repository가 production orchestration과 권한 경계를 소유하게 된다. 이 저장소가 제공해야 하는 것은 운영 계층이 수집한 evidence를 엄격한 schema로 검증하고, 실패를 machine-readable non-zero 결과로 반환하며, 개별 PRE/POST record와 dirty isolation manifest의 무결성을 증명할 수 있게 하는 source-owned verification contract다.

기대 상태는 trex-core provenance gate가 운영 계층이 제공한 observed target/image evidence와 audit checkout evidence를 명시적으로 구분해 기록하고, 누락·형식 오류·checkout mismatch·capture 실패를 fail-closed하는 것이다. 별도 pair validator는 명시적으로 전달된 PRE/POST record 두 개의 operation identity와 gate 성공 여부를 검증하고 immutable manifest를 생성해야 한다. Dirty isolation은 source를 삭제하거나 정리하지 않으면서 regular file과 symlink의 보존 결과를 hash/type 기준으로 검증 가능하게 남겨야 한다.

Evidence

  • GitHub Issue #87은 running artifact와 audit checkout의 provenance 불일치, PRE/POST 증거 연결, dirty checkout 무손실 보존 문제를 추적한다. Issue 본문의 lifecycle wrapper·runtime inspect·global lock 항목은 현재 책임 재검토 결과 운영 계층 소유로 분리해야 한다.
  • PR #93은 main에 병합되었고 조사 기준 revision은 cd2342f2c69267c471b5e81658c58332e00857de다. 관련 변경은 f3a6b2c, 8d9d627, 619feff, 8378e03, 7dc2f65에 걸쳐 있다.
  • scripts/release_provenance_gate.py는 command class와 read-only capture command 형태를 제한하고 dirty checkout에서 state capture를 실행하지 않은 채 exit 2로 차단한다. 하지만 --expected-oci-revision과 --image-digest는 caller가 제공한 평면 문자열이며 target identity, evidence source와 expected/observed 구분을 기록하지 않는다.
  • trex_core/adapters/persistence/ops_checks.py의 collect_release_provenance()는 audit checkout HEAD와 caller가 제공한 revision을 비교하고 image digest의 sha256:<64 hex> 형식을 검사한다. Runtime 파일은 working-tree bytes와 지정 revision의 Git blob hash를 비교한다.
  • scripts/release_provenance_gate.py는 PRE와 POST record를 각각 exclusive-create하고 read-only mode로 전환하지만, 동일 operation ID·instance·target identity를 검증하는 pair validator와 pair manifest는 없다.
  • isolate_dirty_checkout_files()의 현재 manifest.json은 dirty_paths와 copied_paths만 기록한다. 각 source/copied path의 file type, SHA-256, size와 복사 일치 여부는 기록하지 않는다. 따라서 path-only manifest가 현재 baseline이며 hash manifest는 이번 Line의 신규 범위다.
  • docs/operations.md의 현재 실행 절차는 host trex-core-daemon과 pkill을 설명하지만 Issue #87은 container identity를 예로 든다. 저장소에는 production Compose/service definition이나 canonical lifecycle executor가 없으므로 이 Line에서 특정 runtime을 선택하거나 lifecycle command를 추가할 직접 근거가 없다.
  • 현재 main에서 tests/adapters/persistence/test_ops_checks.py와 tests/scripts/test_release_provenance_gate.py를 실행한 결과 19 passed, 3 skipped다. 이는 기존 개별 gate baseline을 확인하지만 observed evidence schema, pair integrity와 hash isolation manifest를 검증하지 않는다.
  • Duplicate sweep 결과 Issue #87 관련 open PR과 release provenance·lifecycle wrapper open PR은 없고 PR #93만 merged 상태다.
  • 현재 active ProofLine AC 전체와 .proofline/lines/**를 release_provenance, audit checkout, 재기동, lifecycle wrapper로 검색한 결과 이 검증 계약을 소유하는 AC는 없다. Image publication을 소유하는 req-0002·req-0004는 production restart와 deployment를 비범위로 두므로 update/satisfy 대상이 아니다.

Scope

  • 이 Line은 기존 PR #93 gate를 기반으로 version-independent 동작을 소유하는 신규 AC 세 건을 create한다. 기존 active AC의 update, retire, satisfy, release evidence 대상은 없다.

신규 AC-A: observed provenance evidence와 개별 gate

  • 운영 계층이 수집해 전달하는 evidence는 최소 target_id, target_kind, image_id, image_digest, oci_revision, observed_at을 가진 versioned JSON object다. target_kind는 extensibility를 위한 식별값이며 trex-core가 Docker·Compose·host runtime을 선택하거나 inspect하지 않는다.
  • Gate는 evidence source를 operator_observed로 명시하고, caller가 제공한 observed 값과 gate가 직접 확인한 checkout HEAD/detached/dirty 상태 및 runtime-file Git blob 비교를 별도 field로 기록한다. Caller evidence를 gate 직접 관측값으로 표시하지 않는다.
  • target_id와 target_kind는 non-empty string, oci_revision은 40-hex commit, image_id와 image_digest는 sha256:<64 hex>, observed_at은 timezone을 가진 UTC timestamp여야 한다. 누락·중복 key, 잘못된 type/형식, secret-like key/value, checkout revision mismatch, dirty/attached checkout, runtime-file mismatch와 필수 state capture 실패는 record에 원인을 남기고 non-zero로 종료한다.
  • 정상 검증은 gate record에 schema_version, evidence의 expected/observed provenance, checkout/runtime/capture 결과와 gate.passed=true를 남긴다. 실패 record도 exclusive-create read-only로 남기되 lifecycle 허용을 주장하지 않는다.
  • Verification은 정상 evidence, 각 필수 field 누락·잘못된 type/형식, unknown key, secret-like 값, revision mismatch, dirty/attached checkout, runtime-file mismatch와 capture 실패를 독립적으로 포함한다.

신규 AC-B: PRE/POST pair validator와 immutable manifest

  • Pair validator는 filesystem scan으로 record를 추정하지 않고 운영 계층이 명시적으로 전달한 정확한 PRE path와 POST path만 읽는다.
  • PRE는 phase=pre, POST는 phase=post이며 두 record는 동일한 schema_version, operation_id, instance, target_kind, target_id를 가져야 한다. 각 command class는 기존 allowlist에 속해야 하지만 실제 PRE→POST lifecycle transition policy와 image 변경 허용 여부는 운영 계층이 소유한다.
  • 두 record 모두 gate.passed=true이고 필수 checkout/runtime/state capture evidence가 완전해야 한다. PRE/POST의 image identity는 각각 manifest에 보존하되 deploy 여부를 모르는 core validator가 임의로 동일성을 강제하지 않는다.
  • Pair 검증 성공 시 두 input record의 canonical path, SHA-256, phase, command class, observed image identity와 검증 시각을 포함한 versioned manifest를 checkout 밖에 exclusive-create하고 read-only mode로 전환한다. 동일 output path 재사용은 overwrite하지 않고 실패한다.
  • PRE 없는 POST, phase 역전, identity mismatch, failed gate, 변조된/비정상 record, 필수 evidence 누락에서는 manifest를 생성하지 않고 non-zero로 종료한다.
  • Verification은 성공 pair, PRE 없는 POST, phase mismatch, operation/instance/target mismatch, failed gate, input record byte 변경, output collision을 독립적으로 포함한다.

신규 AC-C: dirty isolation 무결성과 비밀 안전성

  • Dirty checkout이면 기존과 같이 state capture 전에 fail-closed하고 tracked modified file, untracked regular file과 symlink를 checkout 밖의 operation-specific isolation directory에 복사한다. Source를 삭제·reset·checkout하지 않는다.
  • Isolation manifest는 각 dirty path에 대해 relative path, source type, source SHA-256 또는 symlink target SHA-256, size, copied relative path, copied type/hash/size와 matches를 기록한다. Directory·unsupported special file·checkout escape·symlink escape는 성공으로 추정하지 않고 오류 상태를 기록하며 gate를 실패시킨다.
  • Manifest 자체는 versioned JSON이며 exclusive-create 후 read-only mode로 전환한다. Secret-like file content는 manifest에 넣지 않고 hash·size·type만 저장한다.
  • Verification은 modified/untracked regular file, symlink, empty file, nested path, checkout escape, unsupported type, copy/hash mismatch와 output collision을 포함하고 source bytes가 변경·삭제되지 않았음을 확인한다.

Source 및 문서 변경 경계

  • 예상 source/test owners는 scripts/release_provenance_gate.py, 신규 pair verification CLI, trex_core/adapters/persistence/ops_checks.py, provenance 관련 tests와 docs/operations.md다.
  • Public trading/domain API, daemon composition root, persistence schema와 runtime service lifecycle에는 변경이 없다.
  • docs/operations.md는 trex-core gate가 lifecycle을 실행하거나 runtime truth를 직접 관측하지 않는다는 경계를 명시하고, 운영 계층이 exact observed evidence를 제공하고 non-zero 결과를 lifecycle 차단 조건으로 사용해야 한다고 설명한다.
  • Production runtime validation은 운영 계층 구현과 별도 사용자 승인을 받은 maintenance window가 있어야 하며 이번 source delivery의 완료 증거가 아니다.

Out of Scope

  • Docker Compose/container 또는 host process 중 canonical production runtime 선택
  • Runtime/container/process inspect, 실제 stop/start/recreate/deploy/recovery command 실행
  • Lifecycle wrapper, global operation lock, stale-lock 해제와 maintenance window orchestration
  • Audit checkout의 branch/worktree 생성·교체·reset, dirty source 삭제 또는 recovery branch commit
  • Trading/domain contract, 주문 lifecycle, database schema 또는 migration 변경
  • 자동 주문 제출·취소, 자동 DB recovery, 자동 sync --live 또는 verify --live
  • 여러 instance의 일괄·병렬 재기동 또는 실패 뒤 다음 instance 자동 진행
  • Production credential·raw broker payload를 evidence에 저장하거나 Issue/PR에 게시
  • 사용자 승인 없는 production 변경, 배포 완료 또는 runtime 검증 완료 주장
  • Container registry publication, image signing, SBOM, package visibility 또는 release workflow 변경

Risks and Unknowns

Risks

  • 운영 계층이 잘못된 observed evidence를 제공하면 trex-core는 실제 runtime을 독립적으로 재관측하지 않으므로 그 진실성을 증명할 수 없다. Record는 evidence source를 명시하고 운영 계층은 runtime-specific inspect와 lifecycle 차단을 별도 계약으로 구현해야 한다.
  • Deploy operation은 PRE와 POST image identity가 달라질 수 있으므로 core pair validator가 동일 image를 강제하면 정상 deploy를 막는다. Core는 두 identity와 record hash를 보존하고 transition policy는 운영 계층에 맡긴다.
  • Hash manifest는 dirty bytes의 보존 동일성을 증명하지만 그 내용의 안전성이나 배포 적합성을 승인하지 않는다. Recovery와 clean checkout 준비는 운영자가 별도로 수행한다.
  • 기존 record consumer가 새 versioned schema를 전제로 하지 않을 수 있다. CLI와 parser는 기존 record를 pair success로 암묵 승격하지 않고 unsupported schema로 fail-closed해야 한다.

Assumptions

  • 운영 계층은 실제 runtime-specific inspect로 evidence JSON을 생성하고 gate의 non-zero 종료를 lifecycle 차단 신호로 사용한다.
  • target_id는 운영 계층이 한 operation의 PRE/POST에 안정적으로 유지하는 logical target identity이며 runtime-specific 의미는 core가 해석하지 않는다.
  • Existing trex-core slots ... --json, rabbitmqctl list_consumers와 broker log capture는 PR #93의 approved read-only capture boundary를 유지한다.
  • Issue #87 구현 지시는 source/test/docs/PR delivery를 승인하지만 production restart와 checkout mutation 승인을 포함하지 않는다.