docs(proofline): capture issue 57 specification
This commit is contained in:
@@ -3,14 +3,14 @@ id: "ac-0004"
|
||||
status: active
|
||||
---
|
||||
|
||||
# 검증 성공 이미지에 한정된 GHCR 게시
|
||||
# strict version-tag 검증 성공 이미지에 한정된 GHCR 게시
|
||||
|
||||
## Criterion
|
||||
|
||||
`main` 또는 `v*` tag push의 정확한 source commit에 대해 repository가 정의한 검증 gate, image build, built-container smoke와 tested-image artifact 생성·전달·checksum·load 검증이 모두 성공한 경우에만 GitHub Actions가 registry login/push 단계에 진입해야 한다. 이 push 전 gate 중 하나라도 실패하면 registry write 없이 fail-closed 해야 한다. push 이후에만 반환되는 digest가 누락되거나 형식이 잘못되면 job은 nonzero로 종료하고 성공 output·summary를 남기지 않아야 하며, 이미 발생한 registry write를 발생하지 않은 것으로 보고해서는 안 된다.
|
||||
GitHub Actions publication workflow는 strict `vX.Y.Z` tag push만 후보로 받아야 한다. 각 숫자 구성요소는 `0` 또는 leading zero 없는 non-negative decimal integer여야 하며 branch, non-push event, malformed tag, prerelease/build suffix를 거부해야 한다. workflow는 event·ref·40자리 lowercase `${GITHUB_SHA}`를 검증하고 exact source checkout 뒤 실제 `HEAD` 일치를 재검증한 다음, pinned `uv`와 repository `uv.lock`을 사용하는 full Ruff·full pytest, single image build, built-container smoke, tested image ID, archive checksum, canary scan과 immutable artifact handoff가 모두 성공한 경우에만 publish job이 registry credential과 `packages: write`를 사용해야 한다. 이 push 전 gate 중 하나라도 실패하면 registry login/push 없이 fail-closed 해야 한다. push 이후 digest 누락·형식 오류 또는 tag 간 digest 불일치는 nonzero로 종료하고 성공 output·summary를 남기지 않아야 하며, 이미 발생한 registry write를 발생하지 않은 것으로 보고해서는 안 된다. 일반 `main`/branch push는 이 workflow에서 verification이나 publication을 실행하지 않으며 별도 비게시 CI workflow는 이 criterion의 요구사항이 아니다.
|
||||
|
||||
## Verification
|
||||
|
||||
- 성공 조건: synthetic workflow fixture에서 모든 push 전 gate가 성공한 경우에만 publish job의 login/push가 실행 가능하고, push가 반환한 유효한 digest가 확인된 경우에만 성공 output과 summary가 생성된다.
|
||||
- 실패·경계 조건: repository 검증, build, smoke, artifact 생성·upload·download, checksum 비교 또는 load 실패는 login/push 전 nonzero로 종료된다. push 후 digest 누락·형식 오류는 job nonzero와 성공 output·summary 부재로 이어진다.
|
||||
- 검사 방법: workflow parser 기반 구조 테스트와 publication helper의 recording-runner 단위 테스트로 push 전/후 실패 시점을 분리해 검증하고, `publish.needs` 및 `packages: write`의 publish-job 한정을 정적 검사한다. 실제 최초 GHCR 실행은 별도 승인된 `main` 반영 이후 integration/release evidence로 확인한다.
|
||||
- 성공 조건: synthetic strict tag-push fixture에서 exact checkout 재검증, full repository verification, single build, smoke, tested-artifact 생성·전달·checksum·load 검증을 모두 통과해야 publish job의 login/push가 실행 가능하고, 두 push가 같은 유효 digest를 반환한 뒤에만 성공 evidence가 생성된다.
|
||||
- 실패·경계 조건: non-push, branch, malformed/leading-zero/prerelease/build tag, invalid source commit, checkout `HEAD` mismatch, repository 검증·build·smoke·artifact·checksum·load 실패는 registry credential/write 전에 nonzero로 종료된다. post-push digest 오류·불일치는 nonzero와 성공 evidence 부재로 이어진다.
|
||||
- 검사 방법: `tests/release/test_image_contracts.py`, `tests/release/test_image_release.py`의 workflow parser·recording-runner tests로 trigger, guard 순서, exact checkout, `publish.needs`, publish-job-only `packages: write`, registry write 전후 실패 경계를 검증하고 전체 Ruff·pytest를 실행한다. 실제 tag push·GHCR write는 별도 승인된 publication evidence로 확인한다.
|
||||
|
||||
@@ -3,14 +3,14 @@ id: "ac-0006"
|
||||
status: active
|
||||
---
|
||||
|
||||
# stable SHA tag와 immutable digest 추적성
|
||||
# requester version tag·source tag와 immutable digest 추적성
|
||||
|
||||
## Criterion
|
||||
|
||||
모든 성공 게시 이미지는 전체 40자리 lowercase hexadecimal source commit에서 결정적으로 파생된 앞 12자리 lowercase SHA tag와 전체 commit 값을 담은 `org.opencontainers.image.revision` label을 가져야 한다. SHA tag는 source를 찾기 위한 stable selector이며 배포·rollback의 불변 정본은 registry가 반환한 `sha256` digest다. `v*` tag event에서는 같은 loaded image에 해당 Git tag를 추가하지만 이동 가능한 `latest` tag는 게시하지 않아야 하며, workflow output 또는 summary는 GHCR image reference, 64-hex digest와 전체 source commit을 함께 기록해야 한다.
|
||||
모든 성공 게시 이미지는 전체 40자리 lowercase hexadecimal source commit에서 결정적으로 파생된 앞 12자리 lowercase SHA tag, requester가 선택한 strict `vX.Y.Z` version tag와 전체 commit 값을 담은 `org.opencontainers.image.revision` label을 가져야 한다. version tag는 container publication authority이며 `pyproject.toml` package version과 독립적으로 취급한다. source tag와 version tag는 별도 build 없이 동일하게 검증·load된 image에 부여하고 registry가 반환한 동일 `sha256` digest를 가리켜야 한다. 이동 가능한 `latest` tag는 게시하지 않아야 하며, 성공 output·summary는 immutable GHCR image reference, 64-hex digest, 전체 source commit과 selected version tag를 함께 기록해야 한다. source tag는 source를 찾기 위한 stable selector이고 배포·rollback의 불변 정본은 registry digest다. 이미 게시된 source tag, version tag와 digest는 이 publication flow가 삭제·이동·재지정하지 않아야 한다. operator documentation은 Git version tag가 container publication authority이고 package metadata version과 독립임을 설명하며, version 선택과 tag 생성·push가 구현·검증과 분리된 requester-approved external write임을 명시해야 한다.
|
||||
|
||||
## Verification
|
||||
|
||||
- 성공 조건: `main` event는 source commit 앞 12자리 SHA tag를, `v*` event는 같은 loaded image의 SHA tag와 release tag를 생성한다. OCI revision과 summary/output의 image reference·`sha256` digest·전체 source commit이 해당 실행 입력 및 push 결과와 일치한다.
|
||||
- 실패·경계 조건: source commit 형식 오류, SHA tag 파생 불일치, 빈/형식 오류 digest, source commit 불일치, release tag용 별도 build, `latest` tag 생성 또는 OCI revision 누락은 성공 output·summary를 만들 수 없다. digest 오류가 push 이후 발견되면 job은 nonzero로 종료한다.
|
||||
- 검사 방법: synthetic `main`/`v*` event와 유효·무효 commit/digest를 publication helper에 입력하는 단위 테스트, Docker image label inspection, workflow의 tag/summary 정적 검사 및 `latest` 생성 금지 회귀 검사를 실행한다.
|
||||
- 성공 조건: strict `vX.Y.Z` tag event는 같은 loaded image에 `:<source-commit-first-12>`와 `:vX.Y.Z`를 만들고 두 push가 동일한 digest를 반환한다. OCI revision과 output·summary의 immutable image reference, digest, source commit, version tag가 event와 push 결과에 정확히 일치하며 package version 값은 tag 생성·검증에 사용되지 않는다. 운영 문서는 version authority·package version 독립성·별도 승인 tag push 경계를 모두 설명하고 기존 published identity를 보존한다.
|
||||
- 실패·경계 조건: source commit 또는 version tag 형식 오류, SHA tag 파생 불일치, version/package version 일치 강제, tag별 별도 build, `latest` 생성, OCI revision 불일치, digest 누락·형식 오류·tag 간 불일치가 있으면 성공 evidence를 생성할 수 없다. 기존 published tag·digest의 삭제·이동·재지정 또는 operator documentation의 version authority·별도 승인 경계 누락도 FAIL이다. push 이후 오류는 job nonzero로 유지한다.
|
||||
- 검사 방법: `scripts/image_release.py`의 trigger/tag/publish helper 단위 테스트와 workflow contract test로 deterministic tag, same-loaded-image, no rebuild, same digest, no-`latest`와 output·summary exactness를 검증하고 Docker image label을 inspect한다. `docs/operations.md` contract test로 Git tag authority, package version 독립성과 requester-approved tag creation/push 경계를 검사하고, workflow·helper가 기존 published registry identity를 삭제·이동·재지정하는 command를 포함하지 않는지 정적 검사한다. 실제 registry의 두 tag·digest와 기존 identity 보존은 별도 승인된 publication run에서 immutable evidence로 확인한다.
|
||||
|
||||
@@ -3,14 +3,14 @@ id: "ac-0008"
|
||||
status: active
|
||||
---
|
||||
|
||||
# 운영 설정과 자격증명의 이미지 비포함
|
||||
# locked runtime build input과 운영 설정·자격증명의 이미지 비포함
|
||||
|
||||
## Criterion
|
||||
|
||||
`trex-core` Dockerfile은 package 설치에 필요한 `pyproject.toml`과 `trex_core/`만 application source로 copy하고 repository 전체를 copy하지 않아야 한다. `.dockerignore`는 최소한 `.git`, `.env`, `.env.*`, `config/`와 `.proofline/`을 build context에서 제외해야 한다. image filesystem·history·inspect metadata와 export archive에는 운영 per-instance TOML, `.env`, credential, token, private key, 실제 connection string 또는 synthetic canary marker가 없어야 한다. daemon의 필수 config와 secret은 runtime에 read-only mount, secret 또는 environment로만 주입하고, 문서는 digest pin과 이전 digest rollback을 안내하며 `trex-core-reset`을 자동 rollback 절차에 포함하지 않아야 한다.
|
||||
`trex-core` Dockerfile은 runtime dependency 설치에 필요한 pinned `uv` tool, `pyproject.toml`, repository-owned `uv.lock`과 allowlisted `trex_core/` package source만 application build input으로 copy하고 repository 전체를 copy하지 않아야 한다. runtime environment는 lockfile을 실제 소비하는 `uv sync --locked --no-dev --no-editable` 또는 의미상 동등한 명령으로 생성해야 한다. `.dockerignore`는 최소한 `.git`, `.env`, `.env.*`, `config/`와 `.proofline/`을 build context에서 제외해야 한다. image filesystem·history·inspect metadata와 export archive에는 운영 per-instance TOML, `.env`, credential, token, private key, 실제 connection string 또는 synthetic canary marker가 없어야 한다. 필수 config와 secret은 runtime에 read-only mount, secret 또는 environment로만 주입하고, 문서는 digest pin과 이전 digest rollback을 안내하며 `trex-core-reset`을 자동 rollback 절차에 포함하지 않아야 한다.
|
||||
|
||||
## Verification
|
||||
|
||||
- 성공 조건: 임시 build context의 제외 대상 `.env.ci-canary`에 고정 marker `TREX_SECRET_CANARY_DO_NOT_SHIP`을 둔 상태로 이미지를 빌드해도 marker가 image filesystem, `docker history --no-trunc`, `docker image inspect` 결과와 exported image archive 어디에서도 발견되지 않는다. Dockerfile에는 `COPY .`가 없고 runtime 문서는 외부 주입과 digest rollback 경계를 설명한다.
|
||||
- 실패·경계 조건: 필수 ignore path 누락, repository 전체 copy, synthetic canary 또는 금지 파일·값이 검사 surface에 존재하면 FAIL이다. helper의 locally captured stdout/stderr에 canary가 노출되거나 rollback 안내가 DB reset·자동 data mutation을 실행하도록 제시해도 FAIL이다.
|
||||
- 검사 방법: Dockerfile·`.dockerignore` contract test, synthetic canary가 있는 임시 context의 실제 image build, filesystem/history/inspect/export archive scan, helper의 local output 검사와 runtime documentation contract test를 실행한다. 실제 credential이나 실제 운영 connection string은 fixture·명령·evidence에 사용하지 않는다.
|
||||
- 성공 조건: Dockerfile의 copy/install allowlist에 pinned `uv`, `pyproject.toml`, `uv.lock`, package source만 존재하고 locked runtime sync가 성공한다. 제외 대상 `.env.ci-canary`에 고정 marker `TREX_SECRET_CANARY_DO_NOT_SHIP`을 둔 build에서도 marker가 filesystem, `docker history --no-trunc`, `docker image inspect`와 exported archive 어디에도 없으며 runtime 문서는 외부 주입과 digest rollback 경계를 설명한다.
|
||||
- 실패·경계 조건: missing/mismatched lockfile, unlocked `pip install .` 등 lock 우회, 필수 ignore 누락, broad `COPY .`, synthetic canary 또는 금지 파일·값의 검사 surface 노출은 FAIL이다. helper stdout/stderr에 canary가 노출되거나 rollback 안내가 DB reset·자동 data mutation을 포함해도 FAIL이다.
|
||||
- 검사 방법: `tests/release/test_image_contracts.py`의 Dockerfile·`.dockerignore`·documentation contract tests, 의도적 `pyproject.toml`/`uv.lock` mismatch build, synthetic canary가 있는 실제 image build, filesystem/history/inspect/export archive scan과 helper local-output 검사를 실행한다. 실제 credential이나 운영 connection string은 fixture·명령·evidence에 사용하지 않는다.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
id: "ac-0014"
|
||||
status: active
|
||||
---
|
||||
|
||||
# repository-owned lockfile 기반 runtime dependency identity
|
||||
|
||||
## Criterion
|
||||
|
||||
repository verification environment와 published container의 runtime environment는 같은 revision의 repository-owned `uv.lock` dependency resolution을 사용해야 한다. version-tag verification은 pinned `uv`로 `uv sync --extra dev --locked`를 수행해야 하고, Docker runtime stage는 같은 `pyproject.toml`과 `uv.lock`을 입력으로 `uv sync --locked --no-dev --no-editable` 또는 의미상 동등한 runtime-only locked installation을 수행해야 한다. lockfile이 없거나 project metadata와 불일치하거나 install command가 lock resolution을 우회하면 image build와 publication은 fail-closed 해야 한다. Git publication tag와 Python package metadata version의 독립성은 이 lock identity를 변경하지 않는다.
|
||||
|
||||
## Verification
|
||||
|
||||
- 성공 조건: 동일 source revision의 `pyproject.toml`과 `uv.lock`으로 dev verification sync와 runtime-only image sync가 모두 성공하며 built image에서 `trex_core` import, `trex-core-daemon`, `trex-core`, `trex-core-reset` CLI와 canonical SQL migration inventory가 network 없이 동작한다.
|
||||
- 실패·경계 조건: missing lockfile, project metadata/lock mismatch, `--locked` 누락, runtime dependency를 새로 resolve하는 install, dev dependency의 runtime 포함 또는 editable install은 build/publication 전에 FAIL이다. tag version과 package version 불일치 자체는 실패 조건이 아니다.
|
||||
- 검사 방법: workflow·Dockerfile contract tests로 pinned `uv`와 두 locked sync command를 검사하고, 정상 lockfile의 실제 Docker build·built-container smoke와 의도적으로 불일치시킨 `pyproject.toml`/`uv.lock` build failure를 실행한다. release 집중 테스트와 full repository regression을 함께 실행한다.
|
||||
Reference in New Issue
Block a user