45 KiB
title, source_type, status, branch, parent_branch, related_projects, governing_docs, tags, created, 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 | target_merge | status_label | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | contract_packet_sha256 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-contract-registry-governance | branch-note | raw | feature-contract-registry-governance |
|
|
|
2026-05-22 | in-progress | BR-CA-SKELETON-OPERATIONAL-CONTRACT-041 | project-work-item | ca-skeleton-operational-contract | WI-CA-SKELETON-OPERATIONAL-CONTRACT-041 |
|
1 | 583c60a41462cd57c1c9bf3c27759eaa9ea2597db7633e5507c9577c6467d81e |
branch: feature-contract-registry-governance
Layer:
raw/branch-notes/— error/env/header/log/metric/capability 같은 contract 문자열과 enum을 registry로 관리합니다.
부모 (필수)
- Parent project (canonical SSOT): raw/project-notes/ca-skeleton-operational-contract
ca-skeleton 은 별도 root branch 없이 project-note 가 SSOT 역할. 본 feature branch 는 project-note 의 운영 계약 중 해당 영역 (§21 Contract Registry) 의 결정/근거/금지 사항을 정제한다. governing_docs 로 §21 을 가리킨다.
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: registry single-owner·schema·OpenAPI drift gate가 통과한다
상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-ERROR-ENVELOPE-001@1 |
foundation이 envelope schema와 error.category enum의 단일 owner다 | Work Item 완료 조건에 적용 | raw/project-notes/ca-skeleton-operational-contract |
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-OPENAPI-001@1 |
verification suite가 OpenAPI drift의 release-blocking 판정권을 소유한다 | 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 |
|---|
목표
100점 skeleton에서 가장 위험한 것은 ad hoc 문자열입니다. error code, env key, header, log field, metric name, capability가 파일마다 흩어지면 운영 계약이 깨집니다. 이 branch는 모든 contract token을 registry 기반으로 관리합니다.
- 이슈:
- PR:
범위
포함 범위
- error registry.
- response/meta registry.
- header registry.
- env registry.
- log/metric/trace registry.
- capability registry.
- registry 변경 절차.
제외 범위
- registry UI.
- external config server 구현.
- runtime dynamic registry.
근거 (필수, 최소 1개+)
본 branch의 결정 근거. 상세 비교는 §외부 근거 / 대안 조사 (있다면) 참조.
| Source | 정당화하는 결정 |
|---|---|
| raw/official-docs/archunit-annotation-as-registry-evaluation | — |
| raw/official-docs/registry-adr-official | Nygard/MADR; ca-tmpl branch note가 Status·Context·Decision·Consequences 모두 포함하므로 별도 ADR 불요 |
| raw/official-docs/governance-archunit-official | annotation 기반 registry; ca-tmpl은 ArchUnit을 verifier로만 사용 |
| raw/official-docs/opentelemetry-versioning-stability-spec | D5: OTel semantic conventions는 experimental→stable 전환·rename이 발생하며 모든 변경은 Schema File에 기술해야 함 — 외부 표준 매핑 row 필요성의 공식 근거 |
| raw/official-docs/opentelemetry-http-semconv-migration-guide | D5: HTTP 메트릭 이름(http.server.duration → http.server.request.duration)과 단위(ms → s)가 실제로 rename된 직접 증거 — mapping/version row 없이는 old vs new token 구분 불가 (OTEL-HM-C2, OTEL-HM-C4) |
| raw/official-docs/trace-context-w3c-recommendation | D5: W3C Trace Context Recommendation 이 tracestate 를 통해 내부 shorter identifier 와 표준 trace-id 를 병행 전파할 것을 권고 (W3C-TC-C4) — traceparent/tracestate registry mapping row 유지의 공식 spec 근거 |
| raw/official-docs/rfc9457-problem-details-http-apis | D5: RFC 9457 이 RFC 7807 을 obsolete 하고 error envelope 외부 표준이 버전 관리됨을 IETF 공식 증명 (RFC9457-C1, RFC9457-C5) — skeleton error registry 에 RFC version mapping row 필요성의 직접 근거 |
외부 근거 / 대안 조사 (2026-05-22 — Group G-G: Contract Registry Governance)
본 branch의 markdown SSOT + YAML/generated constants + 공통 schema + 7 registry families (as-built, §Audit F2/F3 정합) 결정에 대한 외부 source.
- 채택 결정 (markdown raw SSOT + YAML implementation):
- (ca-tmpl branch note의 "결정 사항" 라인이 사실상 mini-ADR로 작동)
- 검토한 대안:
- 대안 1: ADR (Architectural Decision Record) 별도 파일 — raw/official-docs/registry-adr-official (Nygard/MADR; ca-tmpl branch note가 Status·Context·Decision·Consequences 모두 포함하므로 별도 ADR 불요)
- 대안 2: ArchUnit annotations as registry — raw/official-docs/governance-archunit-official (annotation 기반 registry; ca-tmpl은 ArchUnit을 verifier로만 사용)
- 대안 3: Code-only enums — DI 통합 강점이나 markdown SSOT 부재
- 대안 4: Protobuf·Smithy as registry — API contract 도구, ca-tmpl scope 외
- 비교 핵심: ca-tmpl branch note의 "결정 사항" 라인이 mini-ADR로 동작 (Status=
status_label, Context=목표/WHY, Decision=결정 사항, Consequences=테스트 계약) — 별도 ADR 파일 도입 불요. ArchUnit은 verifier로만 사용, registry 자체는 markdown SSOT + YAML/generated constants.
후속 보강 (2026-05-22): ArchUnit annotation-as-registry 대안 평가 완료. markdown SSOT 채택 유지. raw/official-docs/archunit-annotation-as-registry-evaluation 참조.
후속 보강 (2026-06-15, D5 외부표준 mapping): 외부 platform 표준 채택 시 mapping row 유지(D5) 의 대안 3종 — (1) per-token mapping row, (2) 외부 이름 직접 채택 무 mapping, (3) spec URL 만 참조 — 을 공식 표준으로 조사. OTel semconv 의 실제 rename(http.server.duration→http.server.request.duration) 과 RFC 7807→9457 obsolete 가 "외부 표준은 버전이 바뀐다" 를 실증하므로, 혼재 표준(W3C+OTel+RFC) 환경에서는 (1) per-token mapping row 채택. 단 W3C Recommendation 처럼 이름이 고정된 표준의 헤더는 (2) 직접 채택 + 최소 external_standard/spec_url column 으로 충분. 근거: W3C-TC-C4(권고 "encouraged"), OTEL-VS-C4(rename 시 Schema File MUST), OTEL-HM-C2(실 rename), RFC9457-C1(obsolete).
TODO
TODO drained 2026-05-22 — 결정은 아래 "결정 사항" / "구현 가이드" (Registry Storage Contract / Registry Tables / 변경 절차) 참조. 잔존 TODO 없음.
진행 중 메모
- 2026-06-15 (
/branch-spec): ca-tmpl ground truth(/home/donghyeon/workspace/ca-tmpl/docs/registries/*.yaml7개 + 8 sibling owner branch 실재) 대조 완료. 확인된 핵심 구조:- 본 branch 는 7 registry 의 schema owner — 모든 yaml header 가
# Schema owner: feature-contract-registry-governance명시. column 구조·저장 형식·변경 절차의 SSOT. - registry row 값(어떤 code/key/name 이 존재하는가)은 각 sibling
owner_branch소유(delegated, 8개). - category enum 값은 본 branch 가 아니라 foundation 소유(
# Category enum owner: feature-operational-error-observability-foundation). 본 branch 는categorycolumn 이 있어야 한다는 schema 만 소유. - D5(외부표준 mapping) 공식 근거 4종 확보 → UNSUPPORTED 해소.
- D3/D4/Registry Tables 의 path·schema·family 수가 as-built 와 달라 §Audit & Findings(F1~F3)로 정합.
- 본 branch 는 7 registry 의 schema owner — 모든 yaml header 가
- 2026-06-20 (Phase C2 구현 착수 — schema-owner gate): 본 branch 의 schema governance 를 기계 강제하는 cross-registry 테스트
ContractRegistrySchemaGovernanceTest(ca-tmpl/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/contract/) 추가. per-registry value drift guard(ErrorCodeRegistryMappingTest/SecretsClassificationRegistryTest/RepositoryAccessCapabilityRegistryTest/MetricsAlertingContractTest— row owner 소유)와 분리되는 schema 층 게이트로, 다음 6가지를 검증: ① 7 family(error-codes/env-keys/secrets-classification/headers/mdc-keys/metrics/capabilities) 존재(Audit F3) ② 각 파일# Schema owner: feature-contract-registry-governance헤더(§3) ③ 모든 row 의 identity(code/key/name)+owner_branch(§1/§2) ④ full row 의compatibility_impact(legal enum none/additive/behavior-change/breaking)+required_test(D2) ⑤ reference row(secrets public-config 5개) 면제 + reference target 보유.docs/gitignore 이므로 registry 부재 시 SKIP, 존재 시 위반은 hard FAIL(기존 drift 테스트 패턴 동일). evidence:locally-verified—./gradlew :app-bootstrap:test --tests '*ContractRegistrySchemaGovernanceTest'6 tests green(skipped=0); 음성 변이 검사(illegalcompatibility_impact주입 시 FAIL, restore 후 green)로 게이트 실효성 확인. ArchUnit 정적 token 탐지(§Claims To Verify 3행)는 여전히planned— 본 게이트는 artifact schema 정합만 강제하며 그 PoC 를 대체하지 않음. 상세 함정: raw/errors/contract-registry-reference-row-universal-column-false-fail-2026-06-20.
결정 사항
- 2026-05-22: 새 error/env/header/log/metric/capability는 registry 없이 추가하지 않음.
- 2026-05-22: registry 항목은 최소 하나 이상의 contract test와 연결.
- 2026-05-22: registry 저장 형식은 markdown table을 raw SSOT로 두고, 구현 단계에서
src/main/resources/contract-registry/*.yml또는 generated constants로 변환 가능하게 함. - 2026-05-22: registry row의 공통 필수 column은
name,owner_branch,owner_layer,default,allowed_values,compatibility_impact,required_test로 둠. - 2026-05-22: 외부 platform 표준을 쓰는 경우에도 skeleton registry에는 mapping row를 남김.
- 2026-05-22: registry 본문(implementation artifact)은
ca-tmpl/docs/registries/하위에 yaml로 작성 (Phase B). raw SSOT는 본 branch note의 표 schema + 각 owner branch의 결정 사항. yaml은 표 schema를 따르는 row table. - 2026-05-22: registry SSOT은 markdown 유지. ArchUnit annotation은 verification verifier 역할만 (registry 아님). 근거: framework-neutral + git diff review + 외부 도구 호환. 상세 평가는 raw/official-docs/archunit-annotation-as-registry-evaluation.
- 2026-06-15 (as-built 정합, Audit F1): registry implementation artifact 의 실제 위치는
ca-tmpl/docs/registries/*.yaml7개 파일(D6 와 일치). 위 2026-05-22 D3/Registry Storage Contract 의src/main/resources/contract-registry/*.yml경로는 미구현 stale — 코드에 존재하지 않음(find src -path '*resources/contract-registry*'결과 0). generated Java constants 는 Phase C2 downstream(yaml→constants) 이며 SSOT 아님. yaml header# SSOT: wiki/projects/ca-tmpl/registries/*.yaml는 추출 후 canonical 위치(현재 미존재). - 2026-06-15 (as-built 정합, Audit F3): registry 는 6개가 아니라 7개 family — Error Codes / Env Keys / Secrets Classification / HTTP Headers / MDC·Log Keys / Metrics / Repository Access Capabilities (governing §21 SSOT yaml 표). 이전 "Log/Metric/Trace" 단일 family 는
mdc-keys.yaml+metrics.yaml2개로 분리, Secrets Classification 추가. 이전 "Response" family 는 별도 registry 가 아니라 foundation 소유 envelope schema 이므로 7 registry 에서 제외. - 2026-06-15 (as-built 정합, Audit F2): 초기 제안한 uniform 7-column schema 는 as-built 에서 채택되지 않음. 모든 7 registry 에 공통(universal) 인 column 은
owner_branch·compatibility_impact·required_test3개뿐 + family 별 identity column(code/name/key) + family-specific column.owner_layer는 error-codes 에만,default/allowed_values는 env-keys 에만 존재. D4 UNSUPPORTED → as-built 로 해소. - 2026-06-15 (D5 근거 확보): 외부 platform 표준 mapping row(D5) 에 W3C Trace Context / OTel versioning-stability / OTel HTTP migration / RFC 9457 공식 표준 근거 확보. D5 UNSUPPORTED →
official-standard. 상세 §외부 근거 후속 보강.
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 승급 위치 |
판정 기준
| 구분 | 기준 |
|---|---|
| Decision | contract token은 registry로 관리 |
| Allowed | 외부 platform 표준 사용 시 mapping table 제공 |
| Forbidden | raw string/enum을 branch별로 ad hoc 추가 |
| Required metadata | name, owner, default, allowed values, profile, test link, compatibility impact |
| Failure condition | registry에 없는 error/env/header/log/metric/capability가 구현에 등장하면 실패 |
결정-근거 매핑
각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시.
Decision ID는 본 branch-note 안에서 안정적으로 유지 (D1~D7). Registry Storage Contract 및 7개 Registry Family table(§구현 가이드)의 책임도 본 표의 row 로 매핑.
선택 조건열: "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 분기 없으면 N/A.
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | 새 error/env/header/log/metric/capability 는 registry 없이 추가하지 않음 | N/A — skeleton-wide 불변 규칙 | raw/official-docs/registry-adr-official.md#REG-ADR-C1, raw/official-docs/registry-adr-official.md#REG-ADR-C2, raw/official-docs/governance-archunit-official.md#AU-OFF-C1, raw/official-docs/governance-archunit-official.md#AU-OFF-C2; + as-built enforcement: 7/7 registry row 가 required_test 필수(grep 확인) → "registry 없이 추가 금지" 는 required_test + contract test 로 강제(§구현 가이드 §4 + §테스트 계약), 정적 탐지(ArchUnit custom rule)는 §Claims To Verify PoC |
official-reference + official-vendor-doc + as-built |
REG-ADR-C1/C2 는 "AD/ADR 정의" 까지만 — "모든 contract token 을 registry 로 관리한다" 의 직접 출처 아님. AU-OFF Claim 은 ArchUnit verifier 능력만 — registry SSOT 강제 아님. enforcement 메커니즘은 required_test(as-built) 로 닫히되, "registry 부재 token 의 정적 차단" 은 ArchUnit PoC(미검증, Claims To Verify) |
| D2 | registry 항목은 최소 1개 이상의 contract test 와 연결 | N/A — 모든 row 의 required_test 필수 |
raw/official-docs/governance-archunit-official.md#AU-OFF-C1, raw/official-docs/governance-archunit-official.md#AU-OFF-C2, raw/official-docs/archunit-conditional-on-property-3-layer-pattern.md#AUCP-C1, raw/official-docs/archunit-conditional-on-property-3-layer-pattern.md#AUCP-C5, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C5 |
official-vendor-doc + engineering-blog |
AAR-C5 (fitness function 정의) 는 verifier 측면만 — "test connection" 의 의무화 자체는 ca-tmpl 운영 결정 |
| D3 | registry 저장 형식 = markdown table raw SSOT + YAML implementation artifact (실 위치는 D6: ca-tmpl/docs/registries/*.yaml); generated Java constants 는 Phase C2 downstream |
markdown 으로 git diff review·외부 도구 호환이 필요할 때 이 결정 / 런타임 DI 통합이 1순위면 대안 3(code-only enum) | raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C1, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C2 |
official-vendor-doc |
AAR-C1/C2 는 annotation registry 의 한계 (Does not prove: domain contract registry 용도) — markdown SSOT 채택 의 직접 권장 아님, 대안 비교의 부정 근거로만 작동. ⚠️ 이전 Decision 텍스트의 src/main/resources/contract-registry/*.yml 경로는 미구현 stale 였음 → D6/§Audit F1 로 정합 |
| D4 | registry row 공통 필수 column = universal 3 (owner_branch, compatibility_impact, required_test) + family identity column (error=code, 그 외=name, mdc=key) + family-specific column. (초기 제안 uniform 7-column 은 as-built 미채택 — §Audit F2) |
현재 7 family 는 universal-3 + family-specific 로 분기 없음. 신규 family 추가 시 어떤 column 을 universal 로 승격할지는 본 결정 범위 밖 — Claims To Verify 2행(walkthrough)으로 위임(의도된 deferral) | ground truth ca-tmpl/docs/registries/*.yaml (7 file 모두 # Schema owner: feature-contract-registry-governance; universal 3-column 은 grep 으로 7/7 확인, owner_layer=error only, default/allowed_values=env only) |
as-built (ca-tmpl/docs/registries/*.yaml) |
family-specific column 의 universal 승격 기준 부재 — 신규 registry 추가 시 어떤 column 을 공통으로 둘지 규칙 없음. 초기 7-column 제안이 미채택된 이력은 §Audit F2 보존 |
| D5 | 외부 platform 표준 (예: OpenTelemetry semantic conventions, RFC 7807→9457, W3C Trace Context) 을 쓰는 경우에도 skeleton registry 에 mapping row 를 남김 | 혼재 표준(W3C+OTel+RFC) 또는 experimental/rename 이력 있는 표준이면 per-token mapping row(대안1) / W3C Recommendation 처럼 이름 고정 표준 헤더는 직접 채택 + 최소 external_standard·spec_url column(대안2) / spec URL 만 참조(대안3)는 per-token 추적 불가로 기각 |
raw/official-docs/opentelemetry-versioning-stability-spec.md#OTEL-VS-C1, raw/official-docs/opentelemetry-versioning-stability-spec.md#OTEL-VS-C4, raw/official-docs/opentelemetry-versioning-stability-spec.md#OTEL-VS-C5, raw/official-docs/opentelemetry-http-semconv-migration-guide.md#OTEL-HM-C1, raw/official-docs/opentelemetry-http-semconv-migration-guide.md#OTEL-HM-C2, raw/official-docs/opentelemetry-http-semconv-migration-guide.md#OTEL-HM-C4, raw/official-docs/trace-context-w3c-recommendation.md#W3C-TC-C1, raw/official-docs/trace-context-w3c-recommendation.md#W3C-TC-C3, raw/official-docs/trace-context-w3c-recommendation.md#W3C-TC-C4, raw/official-docs/trace-context-w3c-recommendation.md#W3C-TC-C5, raw/official-docs/rfc9457-problem-details-http-apis.md#RFC9457-C1, raw/official-docs/rfc9457-problem-details-http-apis.md#RFC9457-C5 |
official-standard |
OTEL-VS-C1: experimental 단계에서 breaking change MAY occur → registry row 없이 hardcode 금지. OTEL-VS-C4: 모든 rename·breaking change는 Schema File에 MUST 기술 → mapping row가 변경 추적 지점이 됨. OTEL-HM-C2: http.server.duration → http.server.request.duration rename 직접 증거. W3C-TC-C1: traceparent/tracestate 가 W3C Recommendation 규범 표준 — registry "외부 표준" 표기 근거. W3C-TC-C4: 내부 shorter identifier 와 표준 trace-id 를 tracestate 로 병행 전파 권고("encouraged") — 내부 token ↔ 외부 표준 token mapping row 유지의 직접 spec 근거. RFC9457-C1: "This document obsoletes RFC 7807" — IETF 공식 폐지로 error envelope 외부 표준의 버전 관리가 실제 발생함을 직접 증명. RFC9457-C5: registry 신설 + multiple problems 처리 + non-resolvable type URI guidance 의 3변경 — RFC 7807 vs 9457 token 구분을 위한 skeleton registry 의 version mapping row 필요성의 직접 근거. |
| D6 | registry 본문 implementation artifact = ca-tmpl/docs/registries/ 하위 yaml (Phase B), raw SSOT 는 본 branch note 표 schema |
N/A — Phase B 운영 결정 | raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C1, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C2 |
official-vendor-doc + as-built (7 yaml 파일 실재) |
yaml 저장 형식의 공식 권장 부재 — Phase B 운영 결정. AAR-C2 의 meta-annotation 패턴은 ArchUnit 설정 중복 제거용일 뿐 registry storage 권장 아님 |
| D7 | registry SSOT 은 markdown 유지, ArchUnit annotation 은 verifier 역할만 (registry 아님) — framework-neutral + git diff review + 외부 도구 호환 | annotation 으로 schema(column) 표현 불가 → markdown SSOT 유지 / verifier 가 필요할 때만 ArchUnit annotation 부착 | raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C1, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C2, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C3, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C4, raw/official-docs/archunit-annotation-as-registry-evaluation.md#AAR-C5, raw/official-docs/governance-archunit-official.md#AU-OFF-C1, raw/official-docs/governance-archunit-official.md#AU-OFF-C2, raw/official-docs/governance-archunit-official.md#AU-OFF-C3 |
official-vendor-doc + engineering-blog |
AAR-C5 는 engineering-blog (서적 출처). "framework-neutral + 외부 도구 호환" 의 정량 비교 부재 — annotation registry 대비 markdown 의 우위는 본 raw 자료의 "Does not prove" 영역 (annotation 으로 schema 표현 불가) 에서 도출 |
구현 가이드
결정 (Decisions) 이 "무엇" 이라면, 본 §는 "어디에 어떻게" 의 사전 명세. as-built ground truth(
ca-tmpl/docs/registries/*.yaml7개 + 8 sibling owner branch)에 정합. 코드로 확인되지 않은 항목은planned/UNSUPPORTED_IMPL_DECISION로 표기.
1. Registry 저장 & 경로 (as-built — Registry Storage Contract)
Trace: D3 + D6 — Supporting: AAR-C1/C2 + ground truth
ca-tmpl/docs/registries/*.yaml.
- UNSUPPORTED_IMPL_DECISION: markdown raw SSOT(표) → yaml 변환 스크립트의 구체적 구현(언어/diff 알고리즘)은 근거 raw 없음 — Phase B 도구 결정. trade-off: 수기 동기화 vs 생성 스크립트, 현재 수기. (검증은 §Claims To Verify "markdown↔yaml row 누락" 행.)
- UNSUPPORTED_IMPL_DECISION: generated Java constants 의 패키지/클래스 명칭 — 근거 없음, Phase C2 downstream. trade-off: 코드 단계 결정.
| item | as-built decision | note |
|---|---|---|
| raw SSOT | 본 branch note 표 schema + 각 owner branch 결정 사항 + project note §21 | governing §21 (raw/project-notes/ca-skeleton-operational-contract) |
| implementation artifact | ca-tmpl/docs/registries/*.yaml — 7 files (error-codes / env-keys / secrets-classification / headers / mdc-keys / metrics / capabilities) |
PATH 정정(Audit F1): 이전 src/main/resources/contract-registry/*.yml 은 미구현 stale. generated constants 는 Phase C2 downstream, SSOT 아님 |
| canonical 추출 경로 (예정) | wiki/projects/ca-tmpl/registries/*.yaml |
각 yaml header # SSOT: 가 가리키는 추출 후 위치 — 추출 전이라 현재 미존재 (Phase C2) |
| row identity | family 별: error=code, mdc=key, 그 외(env/secrets/headers/metrics/capability)=name |
as-built grep |
| required owner | owner_branch 필수(7/7). owner_layer 는 error-codes 만 보유 |
as-built |
| compatibility impact | none / additive / behavior-change / breaking 중 하나 (7/7 공통) |
as-built |
| required test | required_test 필수(7/7) — architecture/contract/OpenAPI/log/metric/env smoke 중 하나 이상 |
D2 |
registry 구현 산출물이 raw SSOT와 다르면 verification suite가 실패해야 합니다.
2. Registry families & 공통 schema (as-built 7개 — Registry Tables)
Trace: D4 + governing §21 — Supporting: ground truth 7 yaml header(
# Schema owner: feature-contract-registry-governance).
- as-built reconciliation (Audit F2/F3): 초기 6-family + uniform 7-column 안은 미채택. universal column 은
owner_branch·compatibility_impact·required_test3개 + identity + family-specific.
Universal columns (7 registry 전부 보유): owner_branch, compatibility_impact, required_test, + family identity. 그 외는 family-specific.
| registry | yaml 파일 | row owner_branch | identity | family-specific 주요 column |
|---|---|---|---|---|
| Error Codes | error-codes.yaml |
feature-operational-error-observability-foundation (category enum SSOT) |
code |
category, http_status, retryable, retry_after_seconds, owner_layer, client_safe_message, log_level, runbook_link |
| Env Keys | env-keys.yaml |
feature-env-driven-runtime-configuration |
name |
type, default, allowed_values, classification, required, reload_policy, validation |
| Secrets Classification | secrets-classification.yaml |
feature-secrets-config-source-contract |
name |
classification, source, rotation_policy, prod_default, dev_sentinel_prefix, masking_rule |
| HTTP Headers | headers.yaml |
feature-api-contract-baseline (cross-owner: idempotency·tracing·tenant·compat·security) |
name |
direction, type, required, generated_if_missing, mdc_key, envelope_meta_field, case_style |
| MDC / Log Keys | mdc-keys.yaml |
feature-operational-error-observability-foundation |
key |
type, source, required_in, http_header_mapping, envelope_field, propagation, cardinality_safe_for_metric, case_style |
| Metrics | metrics.yaml |
feature-metrics-alerting-contract |
name |
type, unit, tags(+cardinality_limit/allowed_values), percentiles, alert_severity_thresholds, log_field_mapping |
| Repository Access Capabilities | capabilities.yaml |
feature-repository-access-permission-contract |
name |
scope, enforcement, annotation, semantics, bound_to_capability, threshold |
"Response" 재분류 (Audit F3, OUT_OF_BRANCH_SCOPE): 이전 Registry Tables 의 "Response" family 는 별도 registry yaml 이 아님. response/error envelope schema 는 raw/branch-notes/feature-operational-error-observability-foundation 가 owner (project §21 "Response Envelope 요약", §3 envelope). registry 메커니즘이 아니라 envelope schema 이므로 7 registry 에서 제외 — 본 branch 결정 범위 밖, foundation 소유.
3. Schema-owner vs row-owner 분리 (본 branch 의 핵심 역할)
Trace: D1 + D4 — Supporting: ground truth(7 yaml header
# Schema owner: feature-contract-registry-governance; error-codes.yaml# Category enum owner: ...).
- 본 branch = schema owner: 모든 registry 의 column 구조 + 저장 형식(D3/D6) + 변경 절차(§4)의 SSOT. 어떤 column 이 있어야 하는가를 정함.
- 각 registry row owner = sibling
owner_branch(8개, §2 표). 어떤 row(code/key/name) 값이 존재하는가는 sibling 결정. 본 branch 는 row 값을 정의하지 않음. - category enum 값 = foundation 소유(error-codes.yaml). 본 branch 는
categorycolumn 존재만 강제, enum 값(VALIDATION/AUTH/AUTHZ/…10개)은 foundation. → §엣지·실패·의존 cross-contract 의존.
4. Registry 변경 절차 (change procedure)
Trace: D1(registry 없이 추가 금지) + D2(test 연결) + D7(markdown SSOT) — Supporting: AU-OFF-C1/C2. project §21 "Registry 변경 절차" 와 정합.
- UNSUPPORTED_IMPL_DECISION: step 6 의 TODO-drain mismatch 검사 주체/시점 — 현재 수동 review (자동 lint 미구현). trade-off: 수동 review(즉시·누락 위험) vs lint 자동화(구현 비용). 향후
wiki_structure_lint.py확장 대상.
- registry row를 먼저 추가.
- 관련 branch note의 Decision/Failure condition을 수정.
- contract test 또는 architecture test mapping을 추가.
.env.example, OpenAPI snapshot, log assertion, metric assertion 중 영향받는 산출물을 갱신.- backward compatibility 또는 migration 영향이 있으면 canonical 승급 전 기록 (
compatibility_impactcolumn 갱신). - TODO drain. 이 branch의 결정이 표(Decisionized Work Items 또는 동등 표)로 반영되면 동일 branch 내 잔존 TODO 항목은 (a) 해당 표 row로 link 또는 (b) 삭제. "기준 작성" TODO를 표와 분리해 두는 패턴은 forbidden. branch note의 TODO 블록과 Decisionized 표의 row 수가 mismatch면 review에서 fail(수동 check, 향후 lint 자동화 대상).
엣지·실패·의존
R4 캡처용. 본 branch 는 schema/governance 층이므로 "다른 계약 의존" 이 핵심.
- 다른 계약 의존 (cross-contract):
- category enum 값은 raw/branch-notes/feature-operational-error-observability-foundation 의 결정(category enum owner)에 의존 — 본 branch 는
categorycolumn schema 만 소유. foundation 이 enum 을 바꾸면 error-codes.yaml 의category값 전체가 영향(본 branch 의 schema 는 불변). - 각 registry row 는 8개 sibling
owner_branch가 소유(delegated, §구현 가이드 §2). 본 branch 가 universal column schema 를 바꾸면 7 registry 전부가 동시 영향 → 항상breaking후보. 부분 적용 시 일부 registry 가 구 schema 로 남아 verification 실패. - response/error envelope schema 는 foundation 소유(registry 아님, Audit F3). 본 branch 가 정의하지 않음.
- headers ↔ mdc-keys ↔ metrics ↔ envelope cross-link: 동일 식별자가 layer 별로 다른 표기(
X-Request-Idkebab /request_idsnake /meta.requestIdcamel)를 가짐 — 표기 매핑 SSOT 는 foundation(mdc-keys snake authoritative). schema 가 이 매핑 column(mdc_key/envelope_meta_field/http_header_mapping)을 보유해야 함. - headers.yaml cross-owner: HTTP Headers registry row 는 단일 owner 가 아니라 복수 — idempotency=raw/branch-notes/feature-rate-limit-idempotency-contract (
Idempotency-Key/Retry-After), tracing=traceparent/tracestate(W3C-TC-C4), tenant/compat/security=각 owner branch. governing §21 도 "(cross-owner)" 로 인정. schema column(direction/mdc_key/case_style) 변경 시 이들 owner row 가 동시 영향. row 값 위임은 §Coverage(api-contract-baseline primary).
- category enum 값은 raw/branch-notes/feature-operational-error-observability-foundation 의 결정(category enum owner)에 의존 — 본 branch 는
- 실패·엣지 경로:
- markdown SSOT ↔ yaml drift: 변환/동기화 도구 부재(현재 수기). row 누락 시 verification suite fail 해야 함 → §Claims To Verify.
- yaml header SSOT 경로 불일치: yaml header
# SSOT: wiki/projects/ca-tmpl/registries/*.yaml가 실제 파일 위치(docs/registries/)와 다름 — 추출 전 canonical placeholder. 추출 시점까지 "현재 위치 ≠ header 표기" 를 인지해야 함(헷갈림 방지). - stale enum 주석 (OUT_OF_BRANCH_SCOPE):
error-codes.yamlL580 주석에 deprecatedPERSISTENCE문자열 잔존(actual enum 은 10-value,PERSISTENCE없음). 이는 category enum 영역(foundation 소유)이며 본 branch schema 범위 밖 → foundation 에 정합 권고만(자동 rewrite 금지). - 외부 표준 rename 전환기 (dual-emit): OTel
OTEL_SEMCONV_STABILITY_OPT_IN=http/dup(OTEL-HM-C5) 처럼 old + new token 이 동시 활성인 기간 — D5 mapping row 가 old/new 를 구분하려면 version 구분 column 필요. mapping row 의 구체 column schema 는 D4 family-specific(미표준화) 영역. - 신규 registry family 추가 시: universal-3 로 표현 불가한 family-specific column 발생 가능 — schema 확장 결정 필요(어떤 column 을 universal 로 승격할지 기준 부재, D4 Open Risk).
Audit & Findings (2026-06-15 — ca-tmpl ground truth 대조)
/branch-spec가 ca-tmpldocs/registries/*.yaml+ project §21 + 8 sibling branch 와 대조해 발견한 drift. 사용자 작성 결정을 덮어쓰지 않고 append-only 정합(결정 사항 2026-06-15 라인) + 본 § 기록. 원 결정 이력은 §결정 사항 2026-05-22 라인에 보존.
| ID | 유형 | 발견 | 정합 조치 |
|---|---|---|---|
| F1 | PATH_DRIFT |
Registry Storage Contract/D3 의 src/main/resources/contract-registry/*.yml 경로가 코드에 미구현(0 hits). 실제 yaml 은 ca-tmpl/docs/registries/*.yaml(D6 와 일치) |
구현 가이드 §1 을 docs/registries 로 정합, D3 Decision 텍스트 정정, 결정 사항 2026-06-15(F1) 추가. 원 D3 라인은 §결정 사항 2026-05-22 에 보존 |
| F2 | SCHEMA_DRIFT |
D4 의 uniform 7-column(name/owner_branch/owner_layer/default/allowed_values/compatibility_impact/required_test)이 as-built 미채택. universal 은 3개(owner_branch/compatibility_impact/required_test)뿐, owner_layer=error only, default/allowed_values=env only |
D4 Decision 을 as-built(universal 3 + identity + family-specific)로 갱신, 초기 제안 미채택 이력 명시. 결정 사항 2026-06-15(F2) 추가 |
| F3 | FAMILY_COUNT_DRIFT |
Registry Tables 가 6 family(+phantom "Response"). as-built/governing §21 은 7 family — "Log/Metric/Trace"→mdc-keys+metrics 분리, Secrets Classification 추가, "Response"=foundation envelope(registry 아님) | 구현 가이드 §2 를 as-built 7 family 로 갱신, "Response" 재분류(OUT_OF_BRANCH_SCOPE). 결정 사항 2026-06-15(F3) 추가 |
| F4 | STALE_COMMENT (OUT_OF_BRANCH_SCOPE) |
error-codes.yaml L580 주석에 deprecated PERSISTENCE 잔존 |
category enum = foundation 소유 → 본 branch schema 영역 밖. foundation 에 정합 권고만(자동 수정 안 함). §엣지·실패·의존 기록 |
테스트 계약
- error code가 registry 없이 사용되면 실패.
- env key가 registry와
.env.example에 없으면 실패. - log/metric field가 registry naming과 다르면 실패.
- registry 변경 없이 response/header/capability 상수가 추가되면 실패.
검증해야 할 주장
공식 문서나 사례는 근거지만, 내 프로젝트의 실 동작을 자동으로 보장하지 않음.
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| markdown table SSOT 가 yaml/generated constants 로 변환되어도 row 누락 없이 일관 유지된다 | D3 — markdown ↔ yaml 변환의 공식 도구/스크립트 부재(현재 수기). AAR-C1/C2 는 annotation 한계만 보임 | Phase B 진입 시 markdown → yaml 변환 스크립트 작성 + diff 로 row count 일치 검증 + drift 시 CI fail rule 추가 |
planned |
universal-3 column (owner_branch/compatibility_impact/required_test) + family-specific column 모델이 7 registry 전부에 충분하다 |
D4 — as-built 로 7 family 가 family-specific column 을 실제로 사용함은 확인(F2). 다만 신규 registry 추가 시 universal-3 만으로 부족할 가능성 + 어떤 column 을 universal 로 승격할지 기준 부재 | 신규 registry 후보(예: rate-limit policy / feature-flag) 에 universal-3 적용 walkthrough → 부족 시 universal 승격 기준 결정 | planned |
| ArchUnit 만으로 "registry 에 없는 contract token 의 사용" 을 정적으로 탐지 가능 | AU-OFF-C2 + AAR-C4 의 fitness function 능력 한계 — registry 와 코드의 cross-reference 검사가 ArchUnit DSL 로 가능한지 PoC 필요 | sample error code (registry 부재) 를 코드에 추가 → ArchUnit noClasses().that()...should().notHaveCode().that().isNotIn(REGISTRY) 식 custom rule PoC → 탐지 성공 여부 |
planned |
.env.example, OpenAPI snapshot, log assertion, metric assertion 이 registry 변경 시 자동으로 drift 탐지 |
D1, D7 — 4종 산출물 ↔ registry 의 cross-check 도구 부재 | env: dotenv-linter / OpenAPI: openapi-diff / log: logback test appender / metric: micrometer test registry 각각의 CI step PoC | planned |
| ADR 별도 파일 없이 branch-note 의 "결정 사항" 라인이 mini-ADR 로 작동 (Status/Context/Decision/Consequences 매핑) | REG-ADR-C2 "ADR captures a single AD" — 1-decision-1-file 모델과 branch-note 의 "결정 사항 누적" 모델의 trade-off 검증 필요 | branch-note 의 한 결정 라인을 MADR 포맷으로 변환 시도 → 4 section 모두 채워지는지 + 별도 파일 가치 평가 | needs-confirmation |
| 외부 platform 표준 (OpenTelemetry / RFC 7807→9457 / W3C) 사용 시 mapping row 가 가독성 손실 없이 표현 | D5 — OTel versioning spec 은 breaking change MAY occur + MUST describe in Schema File 확인 (OTEL-VS-C1/C4/C5). RFC9457-C1/C5 로 RFC 7807→9457 obsolete 사실 확인, W3C-TC-C4 로 tracestate 병행 권고 확인. 단 mapping row 의 구체적 column schema(external_standard/external_token_name/external_version)는 family-specific(미표준화, D4). ca-tmpl error envelope 의 RFC 9457 compliant 여부 미검증 |
OTel log/metric registry 에 최소 3 row 추가 후 mapping column 으로 표현 가능한지 walkthrough; error registry 에 RFC 9457 type URI mapping row 추가 PoC (RFC9457-C2 근거 — type URI 가 primary identifier) |
planned |
| company-tech-blog (카카오뱅크 Modulith / 우아한형제들 Hexagonal) 사례는 official best practice 가 아니라 case study 임을 본 결정 라인이 명시한다 | "company-tech-blog → 공식 best practice" 격상 금지 (CLAUDE.md §5). 현 branch 의 결정 라인이 carry over 하는지 검증 | branch-note 의 모든 결정 라인 grep → company-tech-blog 인용이 "공식 best practice" 표현으로 격상되지 않았는지 확인 | planned |
관심사 커버리지
/coverage가 채우는 생성물 — governing §21 (raw/project-notes/ca-skeleton-operational-contract) 이 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지. 기준:rules/coverage-gate.md. 본 branch 는 schema/governance owner 이므로 registry 값 은 sibling 에 위임(delegated), schema·저장·절차 는 covered-here.
| 관심사 | 상태 | owner | 심각도 | 근거 |
|---|---|---|---|---|
| registry 공통 schema (column 구조) | covered-here | — | — | D4, 구현 가이드 §2 |
| registry 저장 형식·경로 | covered-here | — | — | D3/D6, 구현 가이드 §1 |
| registry 변경 절차 | covered-here | — | — | D1/D2/D7, 구현 가이드 §4 |
| schema-owner vs row-owner 분리 | covered-here | — | — | 구현 가이드 §3 |
| Error Codes registry 값 | delegated | raw/branch-notes/feature-operational-error-observability-foundation | OK | 구현 가이드 §2 |
| Error category enum 값 | delegated | raw/branch-notes/feature-operational-error-observability-foundation | OK | §엣지·실패·의존 + Audit F4 |
| Env Keys registry 값 | delegated | raw/branch-notes/feature-env-driven-runtime-configuration | OK | 구현 가이드 §2 |
| Secrets Classification 값 | delegated | raw/branch-notes/feature-secrets-config-source-contract | OK | 구현 가이드 §2 |
| HTTP Headers registry 값 | delegated | raw/branch-notes/feature-api-contract-baseline | OK | 구현 가이드 §2 |
| MDC / Log Keys 값 | delegated | raw/branch-notes/feature-operational-error-observability-foundation | OK | 구현 가이드 §2 |
| Metrics registry 값 | delegated | raw/branch-notes/feature-metrics-alerting-contract | OK | 구현 가이드 §2 |
| Capabilities registry 값 | delegated | raw/branch-notes/feature-repository-access-permission-contract | OK | 구현 가이드 §2 |
| Response / error envelope schema | delegated | raw/branch-notes/feature-operational-error-observability-foundation | OK | 구현 가이드 §2 (Response 재분류, Audit F3) |
| SENSITIVE_READ 메타표(entity FQN+field) + field-level enforcement (← raw/branch-notes/feature-repository-access-permission-contract 위임 수신) | documented-defer | 본 branch (schema governance), row=planned |
OK (ack) | 위임 수신 확인. sensitive-field metadata table 은 별도 registry 로 본 branch 의 schema governance 적용 대상이나, 도메인 entity 부재로 row 는 planned(아직 sensitive-fields.yaml 미존재). capabilities 의 SENSITIVE_READ 어휘 는 feature-repository-access-permission-contract 소유 |
위임 수신 (incoming delegation, 2026-06-15): raw/branch-notes/feature-repository-access-permission-contract 가
SENSITIVE_READ의 메타표(entity FQN + field) + field-level enforcement 를 본 branch 에documented-defer로 위임했다(그 branch §Coverage). governing §21 은 이 메타표를 7 registry 로 명시 요구하지 않으므로 coverage Blocking 은 아니나, 본 branch 가 수신을 명시한다: sensitive-field 메타표는 향후 별도 registry(예:sensitive-fields.yaml)로 본 branch 의 registry schema governance(D4 universal-3 + family-specific) 를 적용해 정의한다. 도메인 entity 가 도입되기 전까지 row 는planned— 현재 ca-tmpldocs/registries/에 해당 yaml 부재. 어휘(SENSITIVE_READcapability 자체)는 capabilities.yaml owner(feature-repository-access-permission-contract) 소유로 유지.
마주친 문제
- 2026-06-20 (Phase C2): schema-owner gate 구현 중,
secrets-classification.yaml의 15 row 중 5개(Tier-1 public-config: APP_PROFILE / APP_NAME / SERVER_PORT / SPRING_PROFILES_ACTIVE / OTEL_EXPORTER_OTLP_ENDPOINT)가 universal-3 의compatibility_impact/required_test를 의도적으로 생략(reference:로env-keys.yaml에 위임, 파일 헤더 L17). 모든 row 에 universal-3 를 요구하는 naive 게이트는 이 5 row 에서 false-FAIL 한다. → 게이트를 "reference row(=reference:키 보유)는 contract column 면제, identity+owner_branch+reference target 만 요구" 로 모델링해 해소. 상세: raw/errors/contract-registry-reference-row-universal-column-false-fail-2026-06-20.
완료 후 wiki 추출 대상
wiki/projects/ca-skeleton-operational-contract.md(또는 canonicalwiki/projects/ca-tmpl.md§Contract Registry) 의 contract registry canonical section.
묶음
- raw/official-docs/archunit-annotation-as-registry-evaluation
- raw/official-docs/governance-archunit-official
- raw/official-docs/opentelemetry-http-semconv-migration-guide
- raw/official-docs/opentelemetry-versioning-stability-spec
- raw/official-docs/registry-adr-official
- raw/official-docs/rfc9457-problem-details-http-apis
- raw/official-docs/trace-context-w3c-recommendation
본 feature branch 는 leaf — 자식 자료 없음. Phase C2 실 코드 작성 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.
오류 기록 (본 feature 작업 중 발생)
- raw/errors/contract-registry-reference-row-universal-column-false-fail-2026-06-20 — reference row 면제를 누락한 naive schema 게이트의 false-FAIL 함정(resolved, 2026-06-20).
면접 준비 (이 작업에서 나올 수 있는 면접 질문)
- (없음 — 추가 추출 없음. schema-owner vs row-owner 분리 논점은 아래 Blog topics 로 캡처.)
Blog topics
- raw/blog-topics/contract-registry-schema-owner-vs-row-owner-gate-2026-06-20 — multi-owner registry 의 schema-owner vs row-owner 분리를 cross-file 정합 테스트로 박제하는 패턴(Phase C2 schema-owner gate 에서 추출).
관련 일일 노트
- (아직 연결된 일일 노트 없음 — 현재 문서 단계. 실 구현 착수 시 작업일 daily note 를 양방향 연결.)
완료 후 정리
머지/종료 시점에 채움.
- PR 링크:
- 리뷰 메모:
- 머지 결과 / 배포 환경:
- wiki 추출 대상 (verified만,
wiki/projects/로만 추출):actually-implemented항목:locally-verified항목:prod-verified항목:
- 추출하지 않을 항목 (planned / documented-only / abandoned):