75 KiB
title, source_type, status, branch, parent_branch, related_projects, governing_docs, tags, created, updated, target_merge, status_label, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, contract_packet_sha256
| title | source_type | status | branch | parent_branch | related_projects | governing_docs | tags | created | updated | target_merge | status_label | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | contract_packet_sha256 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-build-release-supply-chain-contract | branch-note | raw | feature-build-release-supply-chain-contract |
|
|
|
2026-05-22 | 2026-06-23 | review | BR-CA-SKELETON-OPERATIONAL-CONTRACT-029 | project-work-item | ca-skeleton-operational-contract | WI-CA-SKELETON-OPERATIONAL-CONTRACT-029 |
|
1 | 2307d3faa4febc43cbbe5f18fae9ae683e96a7b2b9f0fbe86065acf1a767a65b |
branch: feature-build-release-supply-chain-contract
Layer:
raw/branch-notes/— artifact, dependency, image, vulnerability, rollback 기준을 정의합니다.
부모 (필수)
- Parent project (canonical SSOT): raw/project-notes/ca-skeleton-operational-contract
ca-skeleton 은 별도 root branch 없이 project-note 가 SSOT 역할. 본 feature branch 는 project-note 의 운영 계약 중 해당 영역 (§<관련 섹션>) 의 결정/근거/금지 사항을 정제한다.
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: Gradle release·SBOM·signature artifact가 생성된다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1 |
build tool은 Gradle Groovy DSL이다 | Work Item 완료 조건에 적용 | raw/project-notes/ca-skeleton-operational-contract |
브랜치 지역 결정
기존 branch-local 결정은 아래
## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|
선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|
목표
운영 가능한 skeleton은 실행되는 코드만이 아니라 배포 가능한 artifact를 안정적으로 만들어야 합니다. dependency drift, 취약 이미지, rollback 불가 artifact는 도메인과 무관하게 실무 장애가 됩니다.
- 이슈:
- PR:
범위
포함 범위
- dependency version locking.
- artifact versioning.
- container image base 기준.
- non-root runtime 기준.
- SBOM 생성 기준.
- vulnerability severity별 release block 기준.
- rollback 기준.
제외 범위
- 특정 registry 운영.
- 조직별 release approval workflow.
- cloud provider 배포 스크립트.
근거 (필수, 최소 1개+)
본 branch의 결정 근거. 상세 비교는 §외부 근거 / 대안 조사 (있다면) 참조.
| Source | 정당화하는 결정 |
|---|---|
| raw/official-docs/supply-chain-cosign-keyless-sigstore | Sigstore Cosign keyless + Fulcio + Rekor (ca-tmpl baseline |
| raw/official-docs/supply-chain-slsa-provenance-framework | SLSA v1 |
| raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking | Gradle dependency-locking vs Maven Enforcer |
| raw/official-docs/cosign-keyless-identity-verification-policy | 참조 |
| raw/official-docs/slsa-v1-provenance-schema | 참조 |
| raw/official-docs/vuln-severity-cvss-v31-spec-first-official | D2 — high/critical release-blocking 기준: CVSS v3.1 §5 severity bands (C1), optional 선언 (C2), Base Score intrinsic/worst-case 정의 (C3) |
| raw/official-docs/semver-2-0-0-spec-semver-official | D9 — artifact version = SemVer + git sha suffix (1.2.3+a1b2c3d): build metadata(+ suffix)는 precedence에서 무시됨 (SEMVER-C3, SEMVER-C4) |
| raw/official-docs/trivy-severity-exit-code-gating | D2 — severity→release-block 정책의 집행(enforcement) 메커니즘: Trivy --exit-code 1 --severity HIGH,CRITICAL 기본 패턴의 공식 출처 (TRIVY-EG-C1~C3) |
| raw/official-docs/renovate-gradle-manager-official | D3 — Renovate Gradle 지원 범위(파일 패턴, --write-locks lockfile 갱신, Version Catalog), self-hosted allowedUnsafeExecutions: ["gradleWrapper"] supply-chain 보안 제약 (RENOV-GRAD-C1~C4) |
| raw/official-docs/gradle-reproducible-archives-working-with-files | D10 — preserveFileTimestamps=false / reproducibleFileOrder=true 의 Gradle 공식 API 명세 + tasks.withType<AbstractArchiveTask>().configureEach {} 전역 적용 패턴 (GRADLE-RA-C1~C3) |
| raw/official-docs/dependabot-supported-ecosystems-official | D3 — Dependabot Gradle ecosystem 공식 지원 범위: version updates ✓ / security updates ✓(단 dependency submission API 수동 업로드 한정) / Private registries ✓ / Vendoring ✗; 파일 파싱 방식(Gradle 미실행) 공식 확인 (DBOT-ECO-C1~C5) |
| raw/official-docs/calver-spec-calver-official | D9 negative-evidence — CalVer when-to-use 기준(대규모/상시변동 scope, 시간민감)이 library/skeleton에 미해당함을 원문 부재로 뒷받침 (CALVER-C2, C3, C5) |
| raw/official-docs/reproducible-builds-org-jvm-guide | D10 — reproducible builds 공식 정의(cross-ecosystem) + JVM nondeterminism 원인(timestamps/file ordering/locale/umask) + Gradle isPreserveFileTimestamps=false + isReproducibleFileOrder=true 두 설정이 두 주요 원인 제거 근거 (RB-JVM-C1~C6) |
외부 근거 / 대안 조사 (2026-05-22 — Group G-E: Build / Release / Supply Chain)
본 branch의 Cosign keyless + SLSA provenance + Gradle dependency-locking + SemVer+sha + reproducibility 결정에 대한 외부 source.
- 채택 결정 (Cosign keyless + SLSA + Gradle lock):
- raw/official-docs/supply-chain-cosign-keyless-sigstore — Sigstore Cosign keyless + Fulcio + Rekor (ca-tmpl baseline)
- raw/official-docs/supply-chain-slsa-provenance-framework — SLSA v1.0 build levels + in-toto attestation
- raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking — Gradle dependency-locking vs Maven Enforcer
- 검토한 대안:
- 대안 1: GPG signing (legacy) — Cosign 이전 표준
- 대안 2: Notary v1 (Docker Content Trust) — Cosign으로 대체된 deprecated 경로
- 대안 3: in-toto attestations — SLSA에 통합되어 별도 도구로는 미채택
- 대안 4: JFrog Artifactory provenance — vendor 통합 솔루션
- 비교 핵심: Cosign keyless가 GPG signing 대비 키 관리 부담 제거(Fulcio가 ephemeral cert 발급, Rekor가 transparency log). SLSA Build L3 도달은 hermetic build 필요. Maven에는 1급 lockfile 부재(Enforcer는 부분 대응) — Gradle 선택 근거. 보강 후보: Cosign signature 누락만 차단으로 부족 —
--certificate-identity+--certificate-oidc-issueridentity 매칭 정책 추가 필요. SLSA v1.0 spec 실제 필드명(buildDefinition.externalParameters등)과 ca-tmpl 약식 매핑 정정 필요. - 후속 보강 (2026-05-22): Cosign signature 존재 검증만으로는 불충분. identity 매칭 정책 추가 필요. raw/official-docs/cosign-keyless-identity-verification-policy 참조.
- 후속 보강 (2026-05-22): SLSA v1.0 spec 실제 필드명과 약식 매핑 정정 필요. raw/official-docs/slsa-v1-provenance-schema 참조.
- 자동조사 라운드 (2026-06-15 —
/branch-spec): UNSUPPORTED 였던 D2(vuln severity)·D3(dependency bot)·D9(SemVer)·D10(reproducibility) 에 공식 source 8건 아카이브. D9·D10 은 본 branch 소유 영역(artifact versioning·reproducibility) → official-standard/vendor-doc 로 승급. D2·D3 은 정책 single-owner 가 raw/branch-notes/feature-dependency-vulnerability-management-contract 이므로 본 branch 는 consume 관계 — §Audit & FindingsOWNER_RECONCILE참조.
TODO
TODO drained 2026-05-22 — dependency lock/update, artifact version naming, container base/non-root runtime, SBOM 생성, vulnerability severity 차단, rollback artifact 보관 정책 모두 "결정 사항" / "Supply Chain Defaults" / "테스트 계약"에 반영됨. 잔존 TODO 없음.
진행 중 메모
- 2026-06-15
/branch-spec자동조사: 근거 없던 결정 5개(D2/D3/D9/D10/D11) 중 D2/D3/D9/D10 을 공식 source 로 보강(§Sources 하단 8행). D11(rollback 10/90 retention)은 외부 표준 부재 →UNSUPPORTED_DECISION유지. - D2/D3 은 evidence 가 붙었으나 정책 owner 는 별도 branch — 자동 rewrite 하지 않고 §Audit & Findings 에 정합 권고로만 기록(사용자 결정 영역).
/sync가 Single-Owner 정합 수행 예정. - 2026-06-20~21 Phase C2 구현 완료. Gradle strict lock, 재현 가능한 archive, traceable version, digest-first image release, SBOM, Cosign keyless, SLSA provenance, High/Critical 차단, rollback retention audit를 코드와 계약 테스트로 배선했다.
- GitHub-hosted OIDC/Rekor/GHCR와 실제 release 생성은 로컬에서 재현할 수 없어
needs-confirmation; 구현·로컬 검증과 운영 검증 경계를 아래 §구현 결과에 분리했다.
구현 결과
아래 §구현 가이드의 2026-06-15
planned표시는 구현 전 설계 스냅샷이다. 현재 상태 SSOT는 이 절이며, 실제 코드·테스트가 존재하는 항목만actually-implemented또는locally-verified로 분류한다.
| Decision | 구현 상태 | 구현 증거 | 검증 등급 |
|---|---|---|---|
| D1 · D9 | src/build.gradle, src/Dockerfile, release manifest에 <SemVer>+<12-char sha>와 source revision 고정 |
JAR manifest와 OCI label inspect | locally-verified |
| D4 · D6 · D12 | digest 대상 Cosign keyless image signature와 SPDX SBOM attestation 생성, exact workflow identity + GitHub issuer 검증 | .github/workflows/build-release-supply-chain.yml, .github/supply-chain-policy.json |
actually-implemented; live OIDC/Rekor는 needs-confirmation |
| D7 · D13 | official SLSA generator provenance와 exact @refs/tags/v2.1.0 builder ID, v1 predicate field 검증 |
release workflow provenance/verify jobs |
actually-implemented; live attestation은 needs-confirmation |
| D8 | 모든 Gradle project에 LockMode.STRICT, 기본 gradle.lockfile, lock 생성/검증 task 적용 |
10개 module lockfile, positive/negative strict-lock 실행 | locally-verified |
| D10 | archive timestamp/order/mode 정규화, Temurin 21.0.11+10 pin, Docker base digest pin | 두 clean build의 JAR SHA-256 일치, zip metadata, Docker build/inspect | locally-verified |
| D2 consume | Trivy image scan HIGH,CRITICAL --exit-code 1을 promotion 전 배치 |
release workflow build job |
actually-implemented; live scan은 needs-confirmation |
| D3 consume | Renovate-compatible Gradle 기본 lockfile 경로와 갱신 절차 명시 | renovate.json, PR template, README |
actually-implemented; Renovate dry-run은 needs-confirmation |
| D5 consume | digest-pinned Temurin JRE runtime + USER app |
Docker build 및 image config inspect | locally-verified |
| D11 | 최근 10개 OR 90일 이내 release의 manifest/SBOM/GHCR digest 일치 daily audit | retention workflow/script/positive-negative behavior tests | locally-verified (fixture); live registry/release는 needs-confirmation |
| D14 | jq 1.8.1을 job-local 경로에 checksum 검증 후 설치하고 모든 jq 소비 job이 같은 installer를 호출 | installer behavior test, workflow YAML parse, 6개 job-level 정적 계약 | locally-verified; Gitea/act CI 재실행은 needs-confirmation |
변경 파일
- Build:
src/build.gradle,.tool-versions,src/*/gradle.lockfile,src/Dockerfile,docker-compose.local.yml. - Release policy/workflows:
.github/supply-chain-policy.json,.github/workflows/build-release-supply-chain.yml,.github/workflows/supply-chain-retention-audit.yml. - Contract/scripts:
.github/scripts/verify-supply-chain-contract.sh,create-release-manifest.sh,verify-reproducible-build.sh,audit-rollback-retention.sh,test-supply-chain-scripts.sh. - Gate/docs:
.github/ci-gate-matrix.yml,.github/workflows/ci-quality-gates.yml,.github/pull_request_template.md,README.md,src/README.md. - 2026-06-23 CI portability repair:
.github/scripts/install-jq.sh,.github/scripts/verify-supply-chain-contract.sh,.github/workflows/{ci-quality-gates,build-release-supply-chain,supply-chain-retention-audit,dependency-vulnerability}.yml. - 2026-06-23 Bean conflict & cycle resolution & test repair:
src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/CaSkeletonApplication.java에서 컴포넌트 스캔 범위를 프로덕션 패키지로 명시화하여sample-portfolio의domainContextPropagator빈과의 BeanDefinitionOverrideException 충돌을 해결.src/adapter-persistence-postgresql/src/main/java/dev/caskeleton/adapter/persistence/postgresql/PostgreSqlPersistenceConfig.java에서postgreSqlFlywayLocationCustomizer()빈을 static @Bean으로 변경하여 Flyway ↔ EntityManagerFactory 간 초기화 순환 참조 제거. 또한PiiTokenBodyForbiddenContractTest.java에서 공유 JVM 테스트 환경에 따른 로깅 레벨 오염으로 로그 미캡쳐 현상이 나타나던 것을 테스트 실행 중 로깅 레벨을 INFO로 보장하는 코드로 격리.OutboxEventEntity.java에서@Lob대신@JdbcTypeCode(SqlTypes.LONGVARCHAR)를 사용하여 PostgreSQLoid캐스팅 경고/오류 및 DDL 불일치를 해결.sample-portfolio모듈의application.yml에서 기본 데이터소스 폴백 정보 수정 및out-of-order: true활성화로 단독 실행 기동 문제 해결. 추가로app-bootstrap모듈의 런타임 기동 마이그레이션(Flyway)을 웹 서버 기동 시 함께 실행할지(In-App) 혹은 별도 원샷 컨테이너/Job으로 격리할지 선택할 수 있도록ca-skeleton.runtime.migration-on-startup(환경 변수:APP_MIGRATION_ON_STARTUP, 기본값true) 설정을 도입하고MigrationStartupRunner,RuntimeSafetySettings,docs/registries/env-keys.yaml을 연동 갱신하여 런타임 운영 유연성을 확보하고MigrationStartupRunnerTest에 우회(bypass) 검증 시나리오를 추가하여 빌드 검증을 완료함. - 2026-06-23 Local environment configuration alignment:
docker-compose.local.yml에서 애플리케이션의 등록된 환경 변수(APP_DATASOURCE_*)와 일치하도록 명칭을 수정(기존SPRING_DATASOURCE_*제거)하고, 템플릿의 로컬 개발 DB 기본 자격 증명(ca_skeleton)이 fallback 디폴트로 자동 바인딩되도록 개선하여 별도 환경변수 입력이나 보간 오류 없이 로컬 스택이 구동 가능하도록 정합성을 확보함.
검증 증거
cd src && ./gradlew resolveAndLockAll --write-locks --no-daemon→ 성공, 10개 module lockfile 생성.cd src && ./gradlew check verifyPublicPathSnapshot --no-daemon→ 최종 변경 후 성공, 108 tasks(89 executed / 19 up-to-date), public path snapshot unchanged.cd src && ./gradlew verifyDependencyLocks ...→ 정상 lock 성공. 격리 사본에서 transitivespring-coreentry 제거 후 동일 task → 기대한 non-zero와not part of the dependency lock state확인.bash .github/scripts/verify-reproducible-build.sh→ 성공, 두 clean build 모두af5e00540adad76313d778680d2ef20dca241671e08107c0144d3961d721f77d.docker build ... -t ca-tmpl:supply-chain-test src→ 최종 strict-lock preflight 포함 성공.USER=app, OCI version/revision/source label 확인.bash -n .github/scripts/*.sh, 공급망 정적 계약, behavior test, gate matrix 검사,yqworkflow parse,jqpolicy parse,git diff --check→ 성공.- Actionlint pinned container는 2026-06-20 실행에 성공했으나, 2026-06-21 최종 재실행은 private workspace 내용을 third-party image에 노출하는 정책으로 거부됐다. 저장소 mount와 stdin 전달 모두 중단하고
yq+ 정적 계약으로 대체했다. 상세: raw/errors/sandbox-build-verification-boundaries-2026-06-21. - 2026-06-23
verify-supply-chain-contract.shRED → installer/6개 job 배선/inline download 금지 15건 실패 확인 후 GREEN.install-jq.sh가 jq 1.8.1 AMD64 공식 asset을 내려받아 SHA-256 검증 후 실행했고, 설치된 바이너리로test-supply-chain-scripts.sh양/음수 경로가 성공했다. ./gradlew verifyCleanArchitectureDependencies,:app-bootstrap:test --tests '*CleanArchitectureTest',test,check verifyPublicPathSnapshot모두 성공. 최종check는 108 tasks(7 executed / 101 up-to-date), public path snapshot unchanged.- 실패 로그와 동일한
node:20-bullseyecontainer 재검증은 private workspace mount 위험으로 실행 승인이 거부되어 중단했다. 실제 Gitea/act 재실행은needs-confirmation. 상세: raw/errors/gitea-act-missing-jq-job-bootstrap-2026-06-23. - 2026-06-23 컴포넌트 스캔 제한, 순환 참조 해결, 로깅 레벨 복구 적용 상태에서 전체 빌드/테스트 및 로컬 기동 검증:
cd src && ./gradlew test빌드가 성공(BUILD SUCCESSFUL)함을 확인하고, 로컬 PostgreSQL 컨테이너(ca-pg)를 기동하여./gradlew :app-bootstrap:bootRun을 실행함으로써 Flyway 마이그레이션 적용 및Started CaSkeletonApplication기동 성공을 로그로 검증함.
결정 사항
- 2026-05-22: release 가능한 artifact는 source revision과 version을 추적 가능해야 함.
- 2026-05-22: high/critical vulnerability는 기본 release-blocking으로 둠.
- 2026-05-22: dependency upgrade bot은 Renovate 기본, Dependabot은 조직 표준일 때 허용.
- 2026-05-22: SBOM만으로는 충분하지 않음. image digest는 필수, Cosign signature와 SLSA provenance는 release-blocking 의무. signature 없이 deploy는 forbidden.
- 2026-05-22: container base image default는 container-runtime branch의 Temurin JRE slim 결정을 소비.
- 2026-05-22: Cosign keyless signing (sigstore Fulcio) 의무화. release artifact에 signature 누락 시 deploy block.
- 2026-05-22: SLSA provenance attestation 의무화 (
build.config.source,build.invocation,materials포함). build provenance 검증 실패 시 deploy block. - 2026-05-22: dependency lock = Gradle dependency-locking 강제 (
gradle/locks/*.lockfile). lock drift 시 build fail. - 2026-05-22: artifact version = SemVer + git sha suffix (예: 1.2.3+a1b2c3d). CalVer은 forbidden.
- 2026-05-22: build reproducibility =
archives.preserveFileTimestamps=false,archives.reproducibleFileOrder=true, JDK version pin via.tool-versions또는gradle/wrapper/. timestamp/locale entropy 제거. - 2026-05-22: rollback artifact 보관 = 최근 10개 release + 90일 (whichever longer).
- 2026-05-22: Cosign verify는
--certificate-identity=<expected>+--certificate-oidc-issuer=<expected>필수. signature 존재만 검증하면 fail. - 2026-05-22: provenance 생성 시 SLSA v1.0 공식 필드명(
buildDefinition.externalParameters,runDetails.builder.id등) 사용. 약식 명명 forbidden. - 2026-06-23: 각 CI job은 격리된 실행 환경이므로 jq 소비 job마다 공통 installer를 호출한다. installer는 jq 1.8.1과 AMD64/ARM64 checksum을 고정하고
RUNNER_TEMP/GITHUB_PATH만 사용한다. apt 설치·workflow별 curl 복제·runner image 사전 설치는 각각 root/배포판 결합, 정책 중복, 숨은 runner 결합 때문에 채택하지 않았다. 근거 raw claim 부재로 D14는UNSUPPORTED_DECISION이다.
Work Item Contract
각 TODO는 아래 판정 단위로 재작성되어야 canonical 승급 가능합니다. TODO가 단순히 기준 작성으로 남아 있으면 이 branch는 완료로 보지 않습니다.
| field | required | rule |
|---|---|---|
| Decision | yes | 구현자가 선택해야 하는 기본값 |
| Allowed | yes | 허용되는 예외와 조건 |
| Forbidden | yes | 절대 금지되는 구현/문서 상태 |
| Required registry update | conditional | error/env/header/log/metric/capability 변경 시 필수 |
| Required contract test | yes | 계약 위반 시 실패해야 하는 테스트 |
| Failure condition | yes | review/build에서 실패로 판정할 상태 |
| Canonical extraction target | yes | wiki/projects 승급 위치 |
Supply Chain Defaults
| item | default | failure condition |
|---|---|---|
| dependency bot | Renovate | no upgrade policy |
| SBOM | generated per release | release without SBOM |
| image identity | immutable digest | tag-only promotion |
| signature | Cosign release-blocking 의무. signature 없이 deploy는 forbidden. | no signed artifact plan |
| provenance | SLSA provenance release-blocking 의무. signature 없이 deploy는 forbidden. | source revision not traceable |
| vuln block | high/critical block | critical vuln warning-only |
결정-근거 매핑
각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시.
Decision ID는 이 branch-note 안에서 안정적으로 유지.
| Decision ID | Decision | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|
| D1 | release 가능한 artifact 는 source revision 과 version 을 추적 가능해야 함 | raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C4 (provenance = where/when/how verifiable info), raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C5 (builder.id + resolvedDependencies) |
official-standard (SLSA v1.0) |
provenance 존재만으로 forge 방지 보장 안 됨 (SLSA-FW-C1 L1 한계) |
| D2 | high/critical vulnerability 는 기본 release-blocking | raw/official-docs/vuln-severity-cvss-v31-spec-first-official.md#C1 (CVSS v3.1 §5 severity bands: High 7.0–8.9 / Critical 9.0–10.0), #C2 (qualitative ratings are optional — 조직이 이를 정책으로 강제 가능), #C3 (Base Score = intrinsic/worst-case, Temporal/Environmental 보완적); 집행 메커니즘 raw/official-docs/trivy-severity-exit-code-gating.md#TRIVY-EG-C2 |
official-standard (FIRST.org CVSS v3.1) — 단 정책 owner 는 raw/branch-notes/feature-dependency-vulnerability-management-contract; 본 branch 는 consume |
severity 정책의 single owner = vuln-management branch (§Audit OWNER_RECONCILE). severity 임계값(≥7.0 / ≥9.0)이 "최적"이라는 것은 명세가 증명하지 않음 — 조직 정책 선택 |
| D3 | dependency upgrade bot = Renovate 기본, Dependabot 은 조직 표준일 때 허용 | raw/official-docs/renovate-gradle-manager-official.md#RENOV-GRAD-C1 (Gradle 파일 패턴 공식 지원), #RENOV-GRAD-C2 (lockfile 유지 via --write-locks), #RENOV-GRAD-C3 (self-hosted allowedUnsafeExecutions: ["gradleWrapper"] 필수); raw/official-docs/dependabot-supported-ecosystems-official.md#DBOT-ECO-C1~C5 (Dependabot Gradle 지원 범위) |
official-vendor-doc (Renovate + GitHub Dependabot) — 단 update-automation 정책 owner 는 raw/branch-notes/feature-dependency-vulnerability-management-contract; 본 branch 는 consume |
"Renovate 기본 vs Dependabot 조건부" 우선순위 결정 자체는 owner branch 소유. lockfile 경로 정합 필요 (§Audit LOCKFILE_PATH_DRIFT) |
| D4 | SBOM + image digest 필수, Cosign signature + SLSA provenance release-blocking, signature 없이 deploy 는 forbidden | raw/official-docs/supply-chain-cosign-keyless-sigstore.md#COSIGN-C1, raw/official-docs/supply-chain-cosign-keyless-sigstore.md#COSIGN-C4, raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C4 |
official-vendor-doc (Cosign) + official-standard (SLSA) |
"signature 누락 시 deploy block" 의 admission controller 구현 (Kyverno/OPA Gatekeeper/sigstore-policy-controller) 별도 — 본 branch 범위 밖(§엣지·실패·의존) |
| D5 | container base image default 는 container-runtime branch 의 Temurin JRE slim 결정 소비 | (cross-branch reference) raw/official-docs/container-distroless-google-github.md#CDG-C1, raw/official-docs/container-alpine-java-musl-tradeoffs.md#CAJM-C4 (대안 trade-off — container-runtime branch 가 SSOT) |
cross-branch-reference |
raw/branch-notes/feature-container-runtime-contract D3 (base image = Temurin JRE slim) 와 동기화 (§Audit D5_CROSSREF_PRECISION) |
| D6 | Cosign keyless signing (sigstore Fulcio) 의무화, signature 누락 시 deploy block | raw/official-docs/supply-chain-cosign-keyless-sigstore.md#COSIGN-C1 (keyless = identity 결합), raw/official-docs/supply-chain-cosign-keyless-sigstore.md#COSIGN-C2 (Fulcio OIDC 검증 + cert 발급), raw/official-docs/supply-chain-cosign-keyless-sigstore.md#COSIGN-C3 (10분 short-lived cert) |
official-vendor-doc |
GPG 대비 운영 부담 감소 직접 진술 (COSIGN-C7) 은 needs-confirmation — verbatim 미확보 |
| D7 | SLSA provenance attestation 의무화 (build.config.source, build.invocation, materials), 검증 실패 시 deploy block |
raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C4, raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C5, raw/official-docs/supply-chain-slsa-provenance-framework.md#SLSA-FW-C6 (in-toto Statement) |
official-standard (SLSA v1.0 + in-toto) |
ca-tmpl 약식 필드명은 spec 실제 필드명과 불일치 — SLSA-SCH-* claim 으로 보강 (D13 참조) |
| D8 | dependency lock = Gradle dependency-locking (gradle/locks/*.lockfile), lock drift 시 build fail |
raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking.md#SC-DL-C1~SC-DL-C9 (Gradle dependency-locking vs Maven Enforcer 비교) |
official-vendor-doc |
Maven Enforcer 의 1급 lockfile 부재는 SC-DL claim 으로 직접 지지. 선언 경로 gradle/locks/*.lockfile vs Renovate 인식 기본 경로 drift (§Audit LOCKFILE_PATH_DRIFT) |
| D9 | artifact version = SemVer + git sha suffix (1.2.3+a1b2c3d), CalVer forbidden | raw/official-docs/semver-2-0-0-spec-semver-official.md#SEMVER-C3 (build metadata + suffix는 precedence에서 무시됨), #SEMVER-C4 (Build metadata does not figure into precedence), #SEMVER-C5 (1.2.3+sha vs 1.2.3-sha 의미 구분), #SEMVER-C1 (MAJOR.MINOR.PATCH 증가 의미론); negative-evidence raw/official-docs/calver-spec-calver-official.md#CALVER-C2/C3/C5 |
official-standard (SemVer 2.0.0 spec) |
CalVer forbidden 은 spec 이 직접 금지하는 것이 아님 — 팀 컨벤션; 일부 레지스트리/도구가 + 문자를 tag 에 허용하지 않을 수 있음 (도구 호환성 별도 검증 필요) |
| D10 | build reproducibility = preserveFileTimestamps=false, reproducibleFileOrder=true, JDK pin |
raw/official-docs/gradle-reproducible-archives-working-with-files.md#GRADLE-RA-C1 (preserveFileTimestamps=false → 기계/JVM/OS 간 타임스탬프 통일), #GRADLE-RA-C2 (reproducibleFileOrder=true → 파일시스템 순서 독립 → byte-for-byte 재현 기여), #GRADLE-RA-C3 (tasks.withType().configureEach {} 전역 적용 패턴); 보조: raw/official-docs/reproducible-builds-org-jvm-guide.md#RB-JVM-C1~RB-JVM-C6 (cross-ecosystem 정의 + JVM nondeterminism 원인 목록) |
official-vendor-doc (Gradle DSL reference) + official-reference (reproducible-builds.org) |
JDK pin (.tool-versions/Gradle Toolchains) 은 본 raw source 범위 밖 — UNSUPPORTED_IMPL(§구현 가이드). 두 property 조합만으로 완전한 reproducibility 보장 아님 (C2: "helps") |
| D11 | rollback artifact 보관 = 최근 10개 release + 90일 (whichever longer) | UNSUPPORTED_DECISION (외부 source 없음 — 조직 retention 정책; 2026-06-15 자동조사에서도 10/90 정량값을 정의하는 외부 표준 미발견) | team-policy |
10/90 정량값 외부 표준 부재 — owner=조직 release 정책. trade-off: 보수적 보관(스토리지 비용 ↔ rollback 가용성). 재평가 트리거: 스토리지 비용 임계 초과 또는 rollback 빈도 변화. 자동 강제 = Claims To Verify(registry retention IaC) |
| D12 | Cosign verify 는 --certificate-identity + --certificate-oidc-issuer 필수, signature 존재만 검증하면 fail |
raw/official-docs/cosign-keyless-identity-verification-policy.md#CSIGN-KL-C1~CSIGN-KL-C4 (identity 매칭 정책) |
official-vendor-doc |
admission controller 통합 시 policy DSL 별도 |
| D13 | provenance 생성 시 SLSA v1.0 공식 필드명 사용 (buildDefinition.externalParameters, runDetails.builder.id 등), 약식 명명 forbidden |
raw/official-docs/slsa-v1-provenance-schema.md#SLSA-SCH-C1~SLSA-SCH-C8 (SLSA v1.0 spec 필드명) |
official-standard |
D7 의 ca-tmpl 약식 필드명이 본 결정과 충돌 — wiki/projects 추출 시 spec 필드명 채택 |
| D14 | jq 1.8.1을 checksum 검증해 job-local 설치하고 jq 소비 job 6개가 공통 installer를 호출 | UNSUPPORTED_DECISION — CI 장애 로그와 jq 1.8.1 GitHub release asset metadata를 구현 증거로 사용했으나 raw source Claim ID는 만들지 않음 |
local-incident + vendor-release-metadata |
실제 Gitea/act runner 재실행 전까지 needs-confirmation; GitHub release host egress가 차단된 runner는 내부 mirror 설계가 별도 필요 |
구현 가이드
결정 이 "무엇" 이면 본 §는 "어디에 어떻게" 의 사전 명세. 다음 구현자가 되묻지 않고 코드를 작성할 수준이 목표.
코드 ground truth (2026-06-15 확인): ca-tmpl
src/Dockerfile= 빈 파일,gradle/locks/부재,.github/workflows/부재, cosign/slsa config 부재 → 본 § 의 모든 detail 은planned. 어떤 항목도actually-implemented아님.3-rule: 각 sub-section 은 Decision ID + Supporting Claim ID 를 Trace. 근거 raw 가 원칙만 권고하고 detail 을 권고 안 하면
UNSUPPORTED_IMPL_DECISION라벨 + trade-off 한 줄. branch 결정 범위 밖 cell 은OUT_OF_BRANCH_SCOPE로 정제(별도 owner 이관).
1. Dependency version locking + reproducible build (Trace: D8 · SC-DL-C1C9 / D10 · GRADLE-RA-C1C3 · RB-JVM-C3/C4/C6)
Trace: D8(Gradle dependency-locking), D10(reproducible archives). 모두
planned(코드 부재).
- UNSUPPORTED_IMPL_DECISION: (a) lockfile 경로 — D8 의
gradle/locks/*.lockfile은 Gradle 기본(gradle.lockfile/*.versions.lock, RENOV-GRAD-C1)과 불일치 → §AuditLOCKFILE_PATH_DRIFT. trade-off: Gradle 기본 경로 채택 = Renovate 호환 우선. (b)dirPermissions/filePermissions의 정확한 unix 값(755/644)은 RB-JVM-C4 가 원칙만 권고 — 팀 선택. (c) JDK pin 메커니즘(Gradle Toolchains vs.tool-versions/gradle/wrapper/)은 D10 raw 가 명시 안 함 — trade-off: Toolchains = 빌드 자체 강제,.tool-versions= 로컬 개발 동기화.
| 위치 / 설정 | 값 (planned) | 상태 | Trace |
|---|---|---|---|
build.gradle.kts dependencyLocking |
dependencyLocking { lockAllConfigurations(); lockMode = LockMode.STRICT } |
planned |
D8 / SC-DL |
| lockfile 경로 | Gradle 기본 gradle.lockfile(루트/서브프로젝트) — D8 의 gradle/locks/*.lockfile 와 정합 필요 |
planned + DRIFT |
D8 / RENOV-GRAD-C1 |
| reproducible archives | tasks.withType<AbstractArchiveTask>().configureEach { isPreserveFileTimestamps = false; isReproducibleFileOrder = true } |
planned |
D10 / GRADLE-RA-C3 |
| umask 정규화 | dirPermissions { unix("755") }; filePermissions { unix("644") } |
planned (값=UNSUPPORTED_IMPL) |
D10 / RB-JVM-C4 |
| JDK pin | java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } + 로컬 .tool-versions |
planned (메커니즘=UNSUPPORTED_IMPL) |
D10 |
| locale entropy | CI JVM args -Dfile.encoding=UTF-8 (Java 17 이하) |
planned |
D10 / RB-JVM-C6 |
2. Artifact versioning (Trace: D9 · SEMVER-C1/C3/C4/C5)
Trace: D9. SemVer 2.0.0
MAJOR.MINOR.PATCH+ git short-sha build metadata.
- UNSUPPORTED_IMPL_DECISION: version bump 자동화 메커니즘(conventional-commits + semantic-release / GitVersion / 수동 tag)은 D9 raw 가 권고 안 함 — trade-off: 자동화 없으면 MAJOR/MINOR/PATCH 의미론이 팀 규율에 의존. (b)
+문자 registry 호환 — OCI tag 규칙이+를 거부하면 image-tag 층에서 치환(_등) 필요(UNSUPPORTED_IMPL, D9 Open Risk).
| 항목 | 명세 (planned) | 근거 |
|---|---|---|
| version 포맷 | <MAJOR>.<MINOR>.<PATCH>+<short-sha> (예: 1.2.3+a1b2c3d) |
SEMVER-C1 |
+ 의미 |
build metadata — precedence 에서 무시. 1.2.3+x 와 1.2.3+y 동일 precedence |
SEMVER-C3/C4 |
| 금지 | 1.2.3-<sha> 형식(= pre-release, precedence 낮춤) 사용 금지; CalVer 금지 |
SEMVER-C5 / CALVER |
3. Artifact signing + provenance (Trace: D4 · COSIGN-C1/C4 · SLSA-FW-C4 / D6 · COSIGN-C1C3 / D7 · SLSA-FW-C4C6 / D12 · CSIGN-KL-C1C4 / D13 · SLSA-SCH-C1C8)
Trace: D4/D6/D7/D12/D13. Cosign keyless 서명 + SLSA v1.0 provenance attestation. 모두
planned.
- OUT_OF_BRANCH_SCOPE: deploy-time admission 강제(Kyverno / sigstore-policy-controller / OPA Gatekeeper)는 k8s admission/deploy 계약 — 본 branch 는 서명된 artifact + verify 정책 만 생성, 클러스터 게이트 는 별도 owner. §엣지·실패·의존 + Claims To Verify 참조.
| 항목 | 명세 (planned) | 근거 |
|---|---|---|
| sign | cosign sign --yes <image>@<digest> (keyless, Fulcio OIDC, 10분 cert) |
D6 / COSIGN-C1~C3 |
| verify | cosign verify --certificate-identity=<expected> --certificate-oidc-issuer=<expected> <image> — identity flag 필수, 존재만 검증하면 fail |
D12 / CSIGN-KL-C1~C4 |
| provenance | in-toto Statement, SLSA v1.0 필드명 buildDefinition.externalParameters / runDetails.builder.id 사용; 약식(build.config.source) 금지 |
D7·D13 / SLSA-SCH |
4. Vulnerability severity gating — consume (Trace: D2 → owner raw/branch-notes/feature-dependency-vulnerability-management-contract)
Trace: D2. severity 차단 정책 의 single owner 는 vuln-management branch(§Audit
OWNER_RECONCILE). 본 branch 는 release artifact 단계에서 그 정책을 consume — 새 결정을 만들지 않는다.
- OUT_OF_BRANCH_SCOPE: scanner tool 선택·CVSS 표준·차단 임계값·suppression governance 는 vuln-management owner. CI gate wiring 은 [raw/branch-notes/feature-ci-quality-gates-contract], image scan wiring 은 raw/branch-notes/feature-container-runtime-contract.
| 항목 | 본 branch 의 consume 지점 (planned) | 근거 |
|---|---|---|
| release-block 신호 | "high/critical → release fail" 을 owner 의 CVSS bands(High 7.0–8.9 / Critical 9.0–10.0)에 결합 | D2 / CVSS C1 |
| 집행 vehicle | Trivy --severity HIGH,CRITICAL --exit-code 1 (scanner wiring 은 ci-gates/container-runtime 소유) |
TRIVY-EG-C2 |
| 예외 경로 | .trivyignore.yaml exp: allowlist — governance 는 owner 소유 |
TRIVY-EG-C4 |
5. Dependency update bot — consume (Trace: D3 → owner raw/branch-notes/feature-dependency-vulnerability-management-contract)
Trace: D3. update-automation 정책(Renovate primary / Dependabot 조건부) owner 는 vuln-management. 본 branch 의 직접 관심사는 단 하나 — lockfile(D8)이 선택된 bot 과 호환되어야 함.
- DRIFT: D8 의 lockfile 경로 vs Renovate 인식 경로 → §Audit
LOCKFILE_PATH_DRIFT. bot CHOICE 자체는 owner 결정.
| 항목 | 본 branch 의 consume 지점 (planned) | 근거 |
|---|---|---|
| Renovate lockfile 갱신 | config:recommended + self-hosted 시 allowedUnsafeExecutions: ["gradleWrapper"] (lockfile --write-locks) |
RENOV-GRAD-C2/C3 |
| 경로 정합 | D8 lockfile 경로를 Renovate fileMatch/Gradle 기본과 일치 |
RENOV-GRAD-C1 |
6. Rollback artifact retention (Trace: D11 · UNSUPPORTED_DECISION)
Trace: D11. 최근 10개 release + 90일(whichever longer).
- UNSUPPORTED_IMPL_DECISION: 10/90 정량값 + registry retention 강제 메커니즘(registry retention IaC / 정기 audit cron)은 외부 표준 부재 — 조직 정책. trade-off: 보수적 보관(스토리지 비용 ↔ rollback 가용성). 자동 강제 검증은 Claims To Verify.
엣지·실패·의존
R4 캡처용. 정상 경로 외 구현 중 부딪힐 실패/엣지/다른 계약 의존을 미리 열거.
- 실패·엣지 경로:
- lock drift: 선언 dependency ≠ lockfile → build fail (D8). 엣지: transitive-only version 변경도 fail 해야 함(Claims To Verify).
- reproducibility 부분 보장: 동일 commit 이라도 JDK vendor/version 또는 build cache 차이로 hash 불일치 가능 — GRADLE-RA-C2 는 "helps"(보장 아님). 테스트 계약의 "2회 build hash 일치" 는 동일 toolchain 전제.
- unfixed CVE: 상위 fix 없는 HIGH CVE → release 무기한 차단;
.trivyignore.yaml exp:예외로 완화(D2 consume). 엣지: 만료된 예외는 다시 fail 로 표면화. - SemVer
+sharegistry 거부: OCI/registry tag 규칙이+거부 시 image-tag 층 치환 필요(D9 엣지). - signature 강제 누수: cosign 서명은 생성되나 admission controller 미배포 → unsigned image 가 deploy 통과 가능(D4/D6 의 "forbidden" 이 강제 안 됨). 엣지: admission gate 배포 전까지 유효.
- Renovate lockfile 경로 mismatch: D8 경로와 Renovate 인식 경로 불일치 시 bot 이 lock 갱신을 조용히 실패(§Audit
LOCKFILE_PATH_DRIFT).
- 다른 계약 의존:
- raw/branch-notes/feature-dependency-vulnerability-management-contract — vuln severity 정책(D2) + dependency update automation(D3)의 single owner. 본 branch 는 release-gating 에서 consume. owner 가 임계값/bot 을 바꾸면 본 branch 의 release-block 신호 + lockfile 호환 가정이 영향.
- raw/branch-notes/feature-container-runtime-contract D3 — base image(Temurin JRE slim) + non-root USER. 본 branch D5 가 consume. base image 변경 시 image digest/scan surface 영향.
- raw/branch-notes/feature-ci-quality-gates-contract — CI gate wiring(release-blocking vs warning-only)의 owner. 본 branch 의 release-blocking 신호를 파이프라인 단계에서 집행. 단 scanner tool 확정은 그 branch 의 D5(
UNSUPPORTED_DECISION+ OWNER_AMBIGUITY)가 아니라 raw/branch-notes/feature-dependency-vulnerability-management-contract D1(Trivy 확정 owner)이 소유한다. - raw/branch-notes/feature-developer-experience-contract — DX 진입점(
./gradlew bootstrap,.tool-versions, Testcontainers, link-rot)의 owner. 본 branch D10 의 JDK pin 은 그 branch 의.tool-versions(D6) 핀과 정합 필요. - k8s admission controller (deploy/security 계약, owner 미식별) — 본 branch 의 "signature 없이 deploy forbidden"(D4/D6)은 그 gate 가 존재해야 강제 가능.
테스트 계약
- artifact에 version/source revision 식별자가 없으면 실패.
- container가 root user로만 실행 가능하면 실패.
- release artifact 재생성 없이 rollback할 수 없으면 실패.
- dependency upgrade policy가 없으면 실패.
- SBOM은 있으나 image digest/source revision 추적이 없으면 실패.
- signature 없는 artifact 발견 시 release fail.
- reproducibility 검증: 동일 commit 2회 build → artifact hash 불일치 시 fail.
검증해야 할 주장
공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다. 구현 전/중/후에 실제로 검증해야 하는 주장을 분리.
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| GitHub Actions hosted runner 기반 build 가 SLSA Build L2 도달 | SLSA-FW-C2 는 hosted dedicated infrastructure + signed provenance 요구, hosted runner 가 자동 L2 라는 뜻은 아님 |
slsa-github-generator action 으로 provenance 생성 + slsa-verifier 로 --builder-id / --source-uri 검사 통과 verify |
actually-implemented; live run needs-confirmation |
Cosign --certificate-identity + --certificate-oidc-issuer 매칭이 admission 단계에서 강제 |
Cosign verify CLI 자체는 검증만, deploy gate 통합은 별도 | sigstore-policy-controller 또는 Kyverno policy 작성 → mismatched identity 의 image deploy 실패 verify | documented-only; deploy admission은 OUT_OF_BRANCH_SCOPE |
| Gradle dependency-locking 이 transitive dependency 모두를 lock | Gradle 공식 lockfile 의 transitive 포함 여부 확인 필요 | lockfile transitive entry 확인; 의도적으로 spring-core entry 제거 후 strict verification non-zero 확인 |
locally-verified |
| 동일 commit 2회 build → artifact hash 일치 (reproducibility) | timestamp/locale entropy 외에 build 환경 차이 (JDK build, dependency cache) 가능 | 두 clean local build SHA-256 비교; 후속 CI runner와 local 교차 비교 | 동일 환경 locally-verified; 교차 환경 needs-confirmation |
| Renovate 가 Gradle 기본 lockfile 경로를 인식·갱신 | Renovate 실행 환경과 wrapper 허용 정책에 따라 lock 갱신 실패 가능 | gradle.lockfile + renovate.json 배선 후 Renovate dry-run → lock 갱신 PR 생성 여부 verify |
경로 actually-implemented; dry-run needs-confirmation |
| Rekor transparency log entry 가 signing 후 검증 측에서 접근 가능 | Rekor public instance (rekor.sigstore.dev) 가용성 SLA 부재 | sign 후 cosign verify --rekor-url=... 로 transparency log entry 검증 |
actually-implemented; live run needs-confirmation |
| SBOM 생성 도구가 모든 dependency 를 누락 없이 캡처 | SBOM 도구의 false negative 가능 | SBOM 출력 vs gradle dependencies diff verify; 의도적 dependency 추가 후 SBOM 갱신 verify |
생성 gate actually-implemented; 완전성 needs-confirmation |
| signature 없는 artifact 가 deploy pipeline 의 어느 단계에서도 통과 못 함 | admission controller 미배포 시 검증 누수 가능 | 의도적으로 unsigned image 를 push → deploy gate 에서 block 되는지 verify (다중 환경: dev/staging/prod) | release promotion actually-implemented; deploy admission OUT_OF_BRANCH_SCOPE |
| rollback artifact 10개/90일 retention 정책이 자동 강제 | registry retention policy 가 수동 설정 시 drift 가능 | scheduled audit + fixture에서 protected manifest/SBOM/GHCR digest 누락·불일치가 실패하는지 검증 | fixture locally-verified; live audit needs-confirmation |
Gitea/act의 node:20-bullseye job에서 공통 jq installer 이후 공급망 behavior test가 통과 |
동일 컨테이너 검증은 private workspace mount 위험으로 승인 거부됨 | 변경 commit으로 ci-quality-gates/gate-matrix-lint 재실행 후 install-jq: jq-1.8.1 및 test-supply-chain-scripts: OK 로그 확인 |
installer/behavior local locally-verified; Gitea CI needs-confirmation |
관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
/coverage가 채우는 생성물 — 손으로 유지하지 않는다. governing 문서(wiki/projects/ca-tmpl/devops-ci-supply-chain-dx)가 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지의 결과. 2026-06-15coverage-auditor판정: Covered (Blocking 0 / Should-fix 3 → Coverage 섹션 정규화로 해소 / Advisory 1). 상태:covered-here(이 브랜치 결정) /delegated(다른 owner 브랜치) /missing(아무도 안 맡음 → Blocking).
| 관심사 | 상태 | owner | 심각도 | 근거 |
|---|---|---|---|---|
| Cosign keyless signing (Fulcio + Rekor) 의무화 | covered-here | — | — | D6 (COSIGN-C1~C3) |
Cosign verify identity 정책 (--certificate-identity + --certificate-oidc-issuer) |
covered-here | — | — | D12 (CSIGN-KL-C1~C4) |
| SLSA provenance attestation + SLSA v1.0 공식 필드명 강제 | covered-here | — | — | D7 (SLSA-FW-C4 |
| Gradle dependency-locking (lockMode=STRICT) | covered-here | — | — | D8 (SC-DL-C1~C9) |
| SemVer + git sha suffix 버전 정책 (CalVer 금지) | covered-here | — | — | D9 (SEMVER-C1/C3/C4/C5 + CALVER negative-evidence) |
| Build reproducibility (preserveFileTimestamps/reproducibleFileOrder/JDK pin) | covered-here | — | — | D10 (GRADLE-RA-C1 |
| SBOM 생성 (release per) + image digest 필수 | covered-here | — | — | D4 (COSIGN-C4 + SLSA-FW-C4) + §Supply Chain Defaults |
| Rollback artifact 보관 (최근 10개 / 90일) | covered-here | — | — | D11 (UNSUPPORTED_DECISION, team-policy) |
| Container base image (Temurin JRE slim) + non-root runtime | delegated | raw/branch-notes/feature-container-runtime-contract D3 | OK | D5 consume; §엣지·실패·의존 cross-link |
| Vulnerability severity 정책 (high/critical release-blocking, CVSS v3.1) | delegated | raw/branch-notes/feature-dependency-vulnerability-management-contract | OK | D2 consume; §Audit OWNER_RECONCILE |
| Dependency update automation (Renovate primary, Dependabot 조건부) | delegated | raw/branch-notes/feature-dependency-vulnerability-management-contract | OK | D3 consume; §Audit OWNER_RECONCILE |
| GitHub Actions gate model + Trivy scan wiring | delegated | raw/branch-notes/feature-ci-quality-gates-contract | OK | §구현 가이드 4 OUT_OF_BRANCH_SCOPE; §엣지·실패·의존 cross-link |
| OpenAPI snapshot diff / flaky quarantine | delegated | raw/branch-notes/feature-ci-quality-gates-contract | OK | governing doc CI 슬라이스 — 본 branch 범위 밖 |
DX 진입점 (./gradlew bootstrap, .tool-versions, Testcontainers, link-rot) |
delegated | raw/branch-notes/feature-developer-experience-contract | ⚪ Advisory | governing doc DX 슬라이스 — 본 branch 범위 밖; D10 JDK pin 은 dx .tool-versions(D6)와 정합 |
Audit & Findings
2026-06-15
/branch-spec자동조사 라운드에서 발견한 정합 항목. 자동 rewrite 하지 않고 권고만 기록(사용자 결정 영역)./sync가 Single-Owner 정합을 수행.
OWNER_RECONCILE(Single-Owner, 권고): D2(vuln severity 정책) + D3(dependency update automation 정책)의 정책 single owner 는 raw/branch-notes/feature-dependency-vulnerability-management-contract (그 branch §Audit 가 본 branch 의 D2/D3UNSUPPORTED_DECISION스텁을 승계해 owner 선언). 2026-06-15 자동조사가 본 branch D2/D3 에 CVSS/Trivy/Renovate/Dependabot 공식 source 8건 중 일부를 아카이브했고 이 source 들은 owner 정책도 뒷받침한다. 권고:/sync로 본 branch 의 D2/D3 를 owner 의 Reference-Only 포인터로 정합(RESTATED_FOREIGN_DECISION 방지). 본 branch 의 D2/D3 는 consume 관계(§구현 가이드 4·5)로 유지.CVSS_CLAIM_ANCHOR_FIX(정정 완료): D2 의 CVSS 참조 anchor 를#CVSS-SRS-C1/2/3→#C1/C2/C3로 정정. 재사용된 기존 파일raw/official-docs/vuln-severity-cvss-v31-spec-first-official.md의 실제 claim ID 는C1~C5.LOCKFILE_PATH_DRIFT(권고): D8 은gradle/locks/*.lockfile경로를 선언하나, Gradle 기본/Renovate 인식 경로는 루트gradle.lockfile+*.versions.lock(RENOV-GRAD-C1). 정합 안 하면 Renovate(D3 owner 영역)가 lock 갱신 실패. 권고: D8 경로를 Gradle 기본으로 정합하거나 RenovatefileMatchoverride. 실측 = Claims To Verify.D5_CROSSREF_PRECISION(권고): D5 Open Risk 의 cross-branch 동기화 대상은 raw/branch-notes/feature-container-runtime-contract 의 D3(base image = Temurin JRE slim)로 좁히는 것이 정확(기존 "D2~D4" 는 광범위). 비차단 — 사용자 결정 영역, 권고만.
완료 후 wiki 추출 대상
wiki/projects/ca-skeleton-operational-contract.md의 build/release/supply-chain canonical section.- 정합 governing canonical: wiki/projects/ca-tmpl/devops-ci-supply-chain-dx (Supply chain §).
마주친 문제
- Gradle
dependenciesreport는 strict lock 누락을FAILED로 표시해도 exit 0으로 끝나 Docker preflight가 fail-open이었다.- 원인: dependency report가 진단 task이고 unresolved configuration을 build failure로 전파하지 않음.
- 해결: 실제 모든 resolvable configuration을 resolve하는
verifyDependencyLockstask를 추가하고 Docker preflight에 연결. transitive lock entry 제거 negative test로 exit 1 확인.
- sandbox/외부 도구 경계로 Gradle과 Actionlint 재검증이 한때 차단됐다.
- Gradle은 사용자 승인 escalated 실행으로 해결했고, Actionlint는 third-party image에 workspace data를 전달하지 않고
yq+ 정적 계약으로 대체했다. - 별도 에러 노트: raw/errors/sandbox-build-verification-boundaries-2026-06-21.
- Gradle은 사용자 승인 escalated 실행으로 해결했고, Actionlint는 third-party image에 workspace data를 전달하지 않고
- Gitea/act의
gate-matrix-lint가 정적 계약 통과 뒤jq: command not found(exit 127)로 실패했다.- 원인:
ubuntu-latest가node:20-bullseye로 매핑됐지만 jq 소비 job이 runner 기본 도구를 암묵적으로 가정했다. - 해결: checksum 검증 공통 installer를 추가하고 직접·간접 jq 소비 job 6곳에 연결했다.
- 별도 에러 노트: raw/errors/gitea-act-missing-jq-job-bootstrap-2026-06-23.
- 원인:
묶음
- raw/official-docs/calver-spec-calver-official
- raw/official-docs/ci-github-actions-vs-gitlab-comparison
- raw/official-docs/cosign-keyless-identity-verification-policy
- raw/official-docs/dependabot-supported-ecosystems-official
- raw/official-docs/dx-devcontainer-spring-boot
- raw/official-docs/dx-mise-asdf-tool-versioning
- raw/official-docs/gradle-reproducible-archives-working-with-files
- raw/official-docs/renovate-gradle-manager-official
- raw/official-docs/reproducible-builds-org-jvm-guide
- raw/official-docs/scorecard-cis-benchmarks-slsa
- raw/official-docs/semver-2-0-0-spec-semver-official
- raw/official-docs/slsa-v1-provenance-schema
- raw/official-docs/supply-chain-cosign-keyless-sigstore
- raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking
- raw/official-docs/supply-chain-slsa-provenance-framework
- raw/official-docs/trivy-severity-exit-code-gating
- raw/official-docs/vuln-severity-cvss-v31-spec-first-official
- raw/errors/gitea-act-missing-jq-job-bootstrap-2026-06-23
- raw/errors/sandbox-build-verification-boundaries-2026-06-21
본 feature branch 는 leaf — 자식 자료 없음. Phase C2 실 코드 작성 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.
근거 자료
- raw/official-docs/supply-chain-cosign-keyless-sigstore
- raw/official-docs/supply-chain-slsa-provenance-framework
- raw/official-docs/supply-chain-gradle-vs-maven-dependency-locking
- raw/official-docs/cosign-keyless-identity-verification-policy
- raw/official-docs/slsa-v1-provenance-schema
- raw/official-docs/vuln-severity-cvss-v31-spec-first-official
- raw/official-docs/semver-2-0-0-spec-semver-official
- raw/official-docs/trivy-severity-exit-code-gating
- raw/official-docs/renovate-gradle-manager-official
- raw/official-docs/gradle-reproducible-archives-working-with-files
- raw/official-docs/dependabot-supported-ecosystems-official
- raw/official-docs/calver-spec-calver-official
- raw/official-docs/reproducible-builds-org-jvm-guide
오류 기록 (본 feature 작업 중 발생)
- raw/errors/sandbox-build-verification-boundaries-2026-06-21 — sandbox/cache/network 및 third-party container data-exposure 경계에서 verification을 안전하게 축소한 기록.
- raw/errors/gitea-act-missing-jq-job-bootstrap-2026-06-23 — minimal Gitea/act job image의 ambient jq 가정을 공통 checksum installer로 제거한 기록.
- raw/errors/logback-shared-jvm-test-leak-pii-contract-2026-06-23 — 공유 JVM 테스트 환경에서 로깅 레벨 오염으로 인해 순수 JUnit 로깅 테스트가 실패하는 현상을 로깅 레벨 격리로 해결한 기록.
- raw/errors/spring-componentcan-multimodule-overlap-collision-2026-06-23 — 멀티모듈 환경에서 최상위 패키지 기준의 컴포넌트 스캔 시 테스트 모듈 내 중복 빈 정의가 끌려 올라와 BeanDefinitionOverrideException 충돌을 야기하던 현상을 프로덕션 패키지 명시 스캔으로 변경하여 해결한 기록.
- raw/errors/spring-jpa-flyway-circular-dependency-2026-06-23 — Flyway ↔ EntityManagerFactory 간 초기화 순환 참조 문제를 static @Bean 정의 방식으로 해결한 기록.
- raw/errors/spring-jpa-postgres-lob-oid-cast-2026-06-23 — PostgreSQL text 컬럼에 대해
@Lob이oid타입 DDL 변경을 발생시켜 발생하는 캐스팅 오류를@JdbcTypeCode(SqlTypes.LONGVARCHAR)매핑 방식을 통해 해결한 기록. - raw/errors/sample-portfolio-flyway-out-of-order-2026-06-23 — 단독 실행이 가능한
sample-portfolio모듈 기동 시, 기 적용된 상위 버전에 의해 발생하는 Flyway의V2out-of-order 미적용 validation 오류를 설정 조정을 통해 해결한 기록.
면접 준비 (이 작업에서 나올 수 있는 면접 질문)
- raw/interviews/digest-first-supply-chain-release-gates — Java/Gradle 릴리스에서 digest·SBOM·Cosign·SLSA를 promotion gate로 묶는 설계 질문.
job-posting tie-ins (이 작업에서 파생된 글감)
- raw/blog-topics/digest-first-java-release-pipeline-2026-06-21 — mutable tag가 아닌 digest를 검증·승격·rollback SSOT로 삼는 구현 글감.
관련 일일 노트
- 없음 — 2026-06-23 CI 보완 작업에 대응하는 daily note는 작성되지 않음.
완료 후 정리
머지/종료 시점에 채움.
- PR 링크:
- 리뷰 메모: self-review에서 release publication 순서, retention API fail-open, manifest↔GHCR digest 일치, exact SLSA builder ID, Trivy 무권한 설치, Gradle diagnostic task fail-open을 보강. 2026-06-23에는 jq job 격리와 checksum bootstrap 계약을 추가했다.
- 머지 결과 / 배포 환경: 미머지. local build/test/contract/Docker 검증까지 완료; GitHub OIDC·Rekor·GHCR live release는 미실행.
- wiki 추출 대상 (verified만,
wiki/projects/로만 추출):actually-implemented항목: Gradle strict locks, SemVer+sha, digest-first release DAG, SPDX SBOM, Cosign identity, SLSA v1 exact builder, High/Critical gate, rollback audit, jq job-local bootstrap wiring.locally-verified항목: 전체 Gradle check, positive/negative lock drift, 두 clean build hash, Docker non-root/OCI labels, manifest/retention behavior tests, jq 1.8.1 checksum install과 공급망 behavior test.prod-verified항목: 없음.
- 추출하지 않을 항목 (planned / documented-only / abandoned): live OIDC/Rekor/GHCR release 결과와 deploy-time admission 강제는 검증 전 canonical 사실로 추출하지 않음.