Files
llm-wiki/raw/branch-notes/feature-contract-registry-governance.md

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
ca-skeleton
raw/project-notes/ca-skeleton-operational-contract
branch
ca-skeleton
registry
governance
contract
2026-05-22 in-progress BR-CA-SKELETON-OPERATIONAL-CONTRACT-041 project-work-item ca-skeleton-operational-contract WI-CA-SKELETON-OPERATIONAL-CONTRACT-041
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-ERROR-ENVELOPE-001@1
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-OPENAPI-001@1
1 583c60a41462cd57c1c9bf3c27759eaa9ea2597db7633e5507c9577c6467d81e

branch: feature-contract-registry-governance

Layer: raw/branch-notes/ — error/env/header/log/metric/capability 같은 contract 문자열과 enum을 registry로 관리합니다.

부모 (필수)

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.durationhttp.server.request.duration)과 단위(mss)가 실제로 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 registryraw/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.durationhttp.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/*.yaml 7개 + 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 는 category column 이 있어야 한다는 schema 만 소유.
    • D5(외부표준 mapping) 공식 근거 4종 확보 → UNSUPPORTED 해소.
    • D3/D4/Registry Tables 의 path·schema·family 수가 as-built 와 달라 §Audit & Findings(F1~F3)로 정합.
  • 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); 음성 변이 검사(illegal compatibility_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/*.yaml 7개 파일(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.yaml 2개로 분리, 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_test 3개뿐 + 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.durationhttp.server.request.duration rename 직접 증거. W3C-TC-C1: traceparent/tracestate 가 W3C Recommendation 규범 표준 — registry "외부 표준" 표기 근거. W3C-TC-C4: 내부 shorter identifier 와 표준 trace-idtracestate 로 병행 전파 권고("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/*.yaml 7개 + 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/*.yaml7 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_test 3개 + 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 는 category column 존재만 강제, 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 확장 대상.
  1. registry row를 먼저 추가.
  2. 관련 branch note의 Decision/Failure condition을 수정.
  3. contract test 또는 architecture test mapping을 추가.
  4. .env.example, OpenAPI snapshot, log assertion, metric assertion 중 영향받는 산출물을 갱신.
  5. backward compatibility 또는 migration 영향이 있으면 canonical 승급 전 기록 (compatibility_impact column 갱신).
  6. 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 는 category column 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-Id kebab / request_id snake / meta.requestId camel)를 가짐 — 표기 매핑 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).
  • 실패·엣지 경로:
    • 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.yaml L580 주석에 deprecated PERSISTENCE 문자열 잔존(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-tmpl docs/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-contractSENSITIVE_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-tmpl docs/registries/ 에 해당 yaml 부재. 어휘(SENSITIVE_READ capability 자체)는 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 (또는 canonical wiki/projects/ca-tmpl.md §Contract Registry) 의 contract registry canonical section.

묶음

본 feature branch 는 leaf — 자식 자료 없음. Phase C2 실 코드 작성 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.

오류 기록 (본 feature 작업 중 발생)

면접 준비 (이 작업에서 나올 수 있는 면접 질문)

  • (없음 — 추가 추출 없음. schema-owner vs row-owner 분리 논점은 아래 Blog topics 로 캡처.)

Blog topics

관련 일일 노트

  • (아직 연결된 일일 노트 없음 — 현재 문서 단계. 실 구현 착수 시 작업일 daily note 를 양방향 연결.)

완료 후 정리

머지/종료 시점에 채움.

  • PR 링크:
  • 리뷰 메모:
  • 머지 결과 / 배포 환경:
  • wiki 추출 대상 (verified만, wiki/projects/로만 추출):
    • actually-implemented 항목:
    • locally-verified 항목:
    • prod-verified 항목:
  • 추출하지 않을 항목 (planned / documented-only / abandoned):