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

11 KiB

id, status
id status
dcy-0004 confirmed

requester-versioned·runtime-locked image publication

Problem

현재 .github/workflows/publish-image.yml은 main과 v* push 모두에서 GHCR publication을 실행한다. 이 때문에 문서·governance-only main commit도 새 registry artifact를 만들며, publication을 요청자가 선택한 release version과 분리해서 통제할 수 없다.

repository verification은 uv sync --extra dev --locked를 사용하지만 현재 Dockerfile은 pyproject.toml만 복사한 뒤 pip install .을 실행한다. 따라서 CI 검증 환경과 built image의 runtime dependency graph가 동일한 repository-owned uv.lock resolution을 사용한다는 보장이 없다.

이 Discovery는 기존의 single build, built-image smoke, image ID, archive SHA-256, canary scan, OCI source revision, rebuild 없는 publish와 multi-tag same-digest 계약을 유지하면서 publication authority를 strict requester-selected version tag로 제한하고 runtime dependency identity를 lockfile에 결속한다.

Evidence

  • GitHub issue #57 https://github.com/fourblocks2020/trex-core/issues/57은 requester-versioned·runtime-locked publication 변경과 완료 조건을 기록한 원본 제안이다.
  • 요청자는 모든 OQ에서 정확히 하나의 선택지를 선택한 뒤 이슈 본문 갱신과 Discovery 승인을 명시적으로 지시했다.
  • 승인 결정에 따라 vX.Y.Z Git tag는 container publication version authority이며 pyproject.toml의 [project].version과 독립적이다. 두 값을 일치시키는 검증이나 package version 변경은 요구하지 않는다.
  • 승인 결정에 따라 별도 비게시 CI를 추가하지 않는다. full Ruff와 full pytest는 strict version-tag publication gate에서 실행하고, 일반 main/branch push에는 이 Discovery가 별도 CI workflow를 추가하지 않는다.
  • 조사 기준 source revision은 1a2b50072238ea72186d99b3ec951fc9511100aa이며 조사 시 main과 origin/main은 동기화되어 있고 worktree는 clean이었다.
  • .github/workflows/publish-image.yml은 현재 main과 v* push를 모두 trigger로 사용하고, exact github.sha checkout 후 uv sync --extra dev --locked, full Ruff, full pytest, single Docker build, built-image smoke, image ID 기록, archive export·canary scan·SHA-256 기록과 immutable artifact handoff를 수행한다. 별도 publish job만 packages: write를 가지며 tested artifact를 재빌드 없이 게시한다.
  • Dockerfile은 현재 pyproject.toml과 trex_core/만 copy한 뒤 pip install --no-cache-dir .을 실행하므로 uv.lock을 runtime dependency installation input으로 사용하지 않는다.
  • scripts/image_release.py::release_tags()는 현재 refs/heads/main을 허용하고 v로 시작하는 넓은 tag 형식을 허용한다. publish helper는 archive checksum, tested/loaded image ID, OCI revision, registry credential 경계, 두 tag의 same-digest와 성공 evidence 생성을 검증하지만 strict vX.Y.Z event만 허용하지는 않는다.
  • tests/release/test_image_contracts.py는 현재 main/v* trigger와 Dockerfile의 기존 COPY allowlist를 고정하고 있어 승인된 trigger·runtime lock 계약에 맞춰 변경해야 한다.
  • docs/operations.md는 source-derived tag를 stable selector로, registry digest를 immutable deployment/rollback identity로 설명하고 runtime config·secret 외부 주입 및 reset 분리 경계를 보존한다. version tag 생성·push가 별도 사용자 승인 외부 쓰기라는 절차는 아직 설명하지 않는다.
  • 기존 active AC 중 AC-0004는 main 또는 v* event의 verification-gated publication, AC-0006은 source tag·release tag·digest 추적성, AC-0008은 Docker COPY allowlist와 secret/config 비포함을 소유한다. AC-0005의 tested-artifact identity와 AC-0007의 built-container smoke는 이번 변경에서도 의미를 유지한다.
  • 비교 기준 trex-mega-swing-v2 revision 88e90caea7e4ab740ed785fc1f57aed8b6f2da5f의 workflow는 strict vX.Y.Z tag-only trigger, event/ref/commit fail-closed validation, exact tagged commit checkout, locked verify, single build와 tested-artifact publication을 사용한다. workflow run 31468042611은 v0.1.0 tag에서 성공했다.
  • 기준 revision에서 proofline validate는 exit 0, uv run ruff check .은 All checks passed!, uv run pytest -q는 1040 passed, 51 skipped를 반환했다. skip은 환경 의존 integration 경계이며 현재 repository baseline이 승인된 변경을 이미 구현했다는 의미는 아니다.

Scope

  • AC admission은 기존 동작의 권한·식별자·build input을 변경하는 update와 새로운 runtime lock 동작을 정의하는 create다.
    • update: AC-0004의 publication event를 일반 main/v*에서 strict version-tag-only로 변경하고 malformed/non-version event가 registry credential·write 전에 실패하도록 한다.
    • update: AC-0006에 strict requester-selected vX.Y.Z version tag, source-derived tag와 version tag의 same-digest, version을 포함한 publication evidence를 반영한다.
    • update: AC-0008의 좁은 Docker build input allowlist에 repository-owned uv.lock과 locked installation에 필요한 도구만 추가하면서 기존 config·credential·canary 비포함 경계를 보존한다.
    • create: repository verification과 runtime image가 동일한 repository-owned lock resolution을 사용하고 lock mismatch 또는 unlocked runtime install을 거부하는 독립적인 장기 AC를 추가한다.
    • AC-0005의 tested-artifact identity와 AC-0007의 built-container package·entrypoint smoke는 변경 없이 유지한다.
  • GHCR publication workflow의 유일한 trigger는 requester가 exact source commit에 생성·push한 strict vX.Y.Z tag다. 각 숫자 구성요소는 0 또는 leading zero가 없는 non-negative decimal integer여야 하며 prerelease/build suffix, malformed tag, branch ref와 non-push event는 허용하지 않는다.
  • workflow는 event·ref·40자리 lowercase source commit을 registry credential 사용 전에 fail-closed로 검증하고, exact tagged commit을 checkout했음을 다시 확인한다.
  • version tag는 container publication identity이며 pyproject.toml의 [project].version과 독립적으로 취급한다. package version 일치 검사, 자동 version 증분과 package metadata 변경을 수행하지 않는다.
  • 일반 main과 branch push는 registry login, docker push, packages: write 또는 image publication을 수행하지 않는다. 요청자 결정에 따라 이번 Scope는 일반 main/branch push를 위한 별도 비게시 CI workflow를 추가하지 않는다.
  • 허용된 version-tag event는 exact source checkout 후 pinned uv와 repository-owned uv.lock으로 full Ruff와 full pytest를 실행하고, 성공한 경우에만 이미지를 한 번 빌드한다.
  • Docker build는 pyproject.toml, uv.lock과 allowlisted package source로 runtime environment를 uv sync --locked --no-dev --no-editable 또는 의미상 동등한 locked 방식으로 설치한다. lock mismatch, missing lockfile 또는 lock을 우회한 runtime dependency install은 build/publication 전에 실패한다.
  • 동일한 tested image에 :<source-commit-first-12>와 :vX.Y.Z를 부여하고 두 tag가 동일한 registry digest를 가리키는지 확인한다. immutable deployment·rollback identity는 @sha256:<digest>다.
  • 기존 scripts/image_release.py의 archive checksum, tested/loaded image ID, OCI revision, canary surface scan, no-rebuild publication, registry credential 경계와 multi-tag same-digest 검증을 유지한다.
  • latest를 생성하지 않으며 성공 evidence에는 source revision, immutable image reference, digest와 selected version tag를 함께 기록한다.
  • workflow contract와 helper tests는 일반 branch/main non-publication, strict event validation, exact checkout, lock mismatch, locked runtime build, same-digest tags, no-latest, no-rebuild 및 기존 failure boundaries를 검증한다.
  • operator documentation은 version 선택과 Git tag 생성·push가 구현과 분리된 사용자 승인 외부 쓰기이고, tag push가 verify/publication을 시작한다는 점을 설명한다.

Out of Scope

  • 이 Discovery 또는 후속 구현 중 concrete version 선택, version tag 생성·push, 최초·후속 GHCR package write, production deployment 또는 운영 서버 pull/restart
  • 일반 main/branch push를 위한 별도 lint/test CI workflow 신설 또는 기존 publication workflow 외 CI 정책 변경
  • pyproject.toml package version 변경, version tag와 package version의 일치 강제 또는 자동 version 증분
  • 기존 published tag·digest 삭제, 이동 또는 registry retention 변경
  • live credential, 실제 account·database·RabbitMQ·Redis·KIS·portfolio-hub 연결, database migration/reset 또는 운영 데이터 변경
  • image signing, SBOM, provenance attestation, multi-architecture build와 moving latest
  • 다른 TREX repository의 workflow, image 또는 release policy 변경

Risks and Unknowns

Risks

  • trigger 변경 후 일반 main push는 새 runtime image뿐 아니라 현재 publication workflow가 제공하던 full Ruff/pytest도 실행하지 않는다. 이는 요청자가 선택한 정책이며, branch protection 또는 지속적 검증이 필요해지면 registry 권한이 없는 별도 CI 변경으로 다룬다.
  • version tag와 package version을 독립적으로 두면 image :vX.Y.Z와 installed Python package metadata version이 다를 수 있다. container publication version authority는 Git tag임을 문서화하고, package version synchronization이 필요해지면 별도 변경으로 다룬다.
  • GitHub trigger glob만으로는 malformed v*.*.*를 모두 배제할 수 없다. workflow 내부 helper가 strict ref/event/commit을 registry credential 전에 재검증해야 한다.
  • Docker build가 lockfile을 copy만 하고 실제 runtime install에 소비하지 않으면 CI lock PASS만으로 runtime reproducibility를 주장할 수 없다. build contract와 tests가 locked runtime command 및 mismatch failure를 직접 검증한다.
  • version tag와 source-derived tag를 별도 build에서 만들면 같은 release identity가 서로 다른 image를 가리킬 수 있다. 단일 tested artifact를 재빌드 없이 두 tag로 push하고 registry digest equality를 확인한다.
  • 기존 commit-derived selector와 immutable digest는 보존해야 하며 migration 과정에서 과거 tag를 삭제하거나 이동하지 않는다.
  • tag 생성·push는 즉시 publication workflow와 registry write를 유발할 수 있다. operator 문서가 이를 별도 사용자 승인 외부 쓰기로 명시하고 구현·테스트 중 실제 tag push를 금지한다.

Approval State

  • Discovery status: confirmed
  • 승인 근거: 요청자가 이슈의 모든 OQ에서 하나의 선택지를 명시적으로 선택한 뒤 이슈 본문 업데이트와 승인을 지시했다.
  • 채택 결정: version tag와 package version은 독립적으로 취급하며, 일반 main/branch push용 별도 비게시 CI는 추가하지 않는다.
  • 추가로 필요한 제품 결정: 없음
  • 이 승인은 Discovery 범위 확인이며 Requirement/AC 승인, 구현, tag 생성·push, GHCR publication, delivery, release 또는 deployment 완료를 의미하지 않는다.