--- title: branch / feature-frontend-contract-compatibility-governance source_type: branch-note status: raw id: BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-023 kind: project-work-item project: ca-skeleton-frontend-operational-contract work_item: WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-023 inherits: [DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1] refines: [] overrides: [] depends_on: [WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-022, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011] contract_packet: 1 branch: feature-frontend-contract-compatibility-governance parent_branch: related_projects: [ca-skeleton-frontend, ca-skeleton] governing_docs: [raw/project-notes/ca-skeleton-frontend-operational-contract] tags: [branch, ca-skeleton, frontend, api-design, semver, api-contract] created: 2026-07-18 target_merge: status_label: in-progress contract_packet_sha256: eb4a422e6da50f16e5b6d59964943ebca79d655fc09066815953aa3ba22e4311 imports: [ART-FE-003@1, FE-GATE-004@1, FE-GATE-015@1, FE-GATE-016@1, FE-OC-004@1, FE-OC-007@1, FE-OC-012@1, FE-OC-013@1, FE-OC-016@1, FE-OC-017@1] --- # branch: feature-frontend-contract-compatibility-governance > Layer: `raw/branch-notes/` — TODO·결정·진행 기록. 구현 결과는 검증 뒤 `/ingest`로만 추출한다. ## 부모 (필수) [[raw/project-notes/ca-skeleton-frontend-operational-contract]] ## 브랜치 계약 패킷 - **생성 시 프로젝트 개정**: `1` - **패킷 스키마**: `contract_packet: 1` - **완료 조건**: version tuple·additive/breaking fixture·migration/rollback rule가 검증된다 ### 상속한 프로젝트 결정 | Decision Ref | Project Summary | Branch Application | Source | |---|---|---|---| | `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1` | route, API operation, env, storage, error, query, telemetry, release token을 8개 registry로 관리한다 | registry 변경의 compatibility impact와 version tuple 입력을 집행한다 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | | `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1` | runtime config fallback 시 environment별 rebuild는 허용하되 artifact의 multi-environment 재사용은 금지한다 | config 변경의 migration·fallback·rollback 호환성 규칙에 적용한다 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | ### 브랜치 지역 결정 | Decision ID | Decision | Relation | Supporting Claims | Status | |---|---|---|---|---| | D1 | compatibility impact 공통 어휘를 고정한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | | D2 | boot compatibility를 version tuple로 판정한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | | D3 | schema 계열별 독립 version field를 사용한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | | D4 | breaking 변경은 migration·version bump·discard·fallback과 test evidence를 요구한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | | D5 | rollback은 coherent tuple 집합을 복원한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | | D6 | 호환 불가 cache data는 기본 discard한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` | ### 선언한 예외 | Override ID | Overrides | Reason | Approval | Status | |---|---|---|---|---| 없음. ## 목표 이 브랜치는 프로젝트 계약 `FE-OC-023`("API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨", minimum evidence = compatibility report)을 **구현 착수 가능한 명세**로 낮춘다. hub는 호환성 규칙을 여러 곳에 흩어 정의해 두었다 — 분류 어휘([[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3), registry 변경 프로토콜(§5.10), boot compatibility tuple(§12.3), rollback invariant(§12.5). 본 브랜치는 이들을 **하나의 governance 계약**(버전 tuple 행렬 + additive/breaking 분류 fixture + migration/rollback 규칙)으로 통합해 owner로서 mechanism과 test를 제공한다. 결정 자체(`FE-D012/013/016/019`)는 다른 owner 브랜치가 소유하고, 본 브랜치는 그 결정들이 공유하는 `FE-OC-023` 계약의 **집행 규칙**만 소유한다. - 이슈: 없음 (스캐폴딩 단계) - PR: 없음 산출물 등급: 프론트엔드 코드가 없으므로 이 브랜치의 모든 구현 주장은 `planned`이다. ## 범위 ### 포함 범위 - **버전 tuple 행렬**: `(buildId, configSchemaVersion, apiContractVersion, assetManifestHash, releaseId)` + storage schemaVersion + query namespace version 을 필드별 source·compatibility 역할·mismatch 결과로 정리한 표(hub §12.3 / §5.9 통합). - **additive vs breaking 분류 fixture**: `compatibility_impact ∈ {none, additive, behavior-change, breaking}` 어휘(hub §3.3)를 API/config/storage/release 4개 schema 계열에 적용하는 synthetic fixture 집합과 각 등급의 required action. - **migration/rollback 규칙**: breaking 변경이 version bump·migration·discard·fallback 없이 merge/배포되지 않게 하는 규칙 + rollback이 coherent tuple 집합을 복원하도록 하는 규칙(hub §5.10 / §9.2 / §12.5). - **compatibility gate 소유**: `FE-GATE-014@1`(config compatibility) 의 fixture·report artifact 정의. `FE-GATE-015`(release coherence) 는 **소유가 아니라 소비/기여** 다 — Owner 는 hub §2.1.1 이 [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] 로 확정했고, 본 branch 는 그 gate 가 쓰는 version tuple 호환 판정을 공급한다. ### 제외 범위 > 의도적으로 제외. 인접 계약은 각 owner 브랜치가 소유하며 본 브랜치는 그 계약을 *소비*하고 호환성 영향만 집행한다. - runtime config schema 정의·boot 검증 mechanism → [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] (owns `FE-OC-004`). - boundary runtime(Zod) schema 검증 → [[raw/branch-notes/feature-runtime-schema-validation-contract]] (owns `FE-OC-007`). - storage key namespace·schemaVersion·migration mechanism → [[raw/branch-notes/feature-frontend-storage-registry-contract]] (owns `FE-OC-013`). - 8개 registry single-owner·diff-check tooling → [[raw/branch-notes/feature-frontend-contract-registry-governance]] (owns `FE-OC-022`). - release directory·atomic pointer·실제 rollback drill 실행 → [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] (owns `FE-OC-016`, `FE-OC-017`). - API client retry/idempotency 동작 → [[raw/branch-notes/feature-api-client-response-envelope-contract]] (owns `FE-OC-006`, `FE-OC-009`). - CI gate blocking 분리 wiring → [[raw/branch-notes/feature-frontend-ci-quality-gates-contract]]. - backend API versioning 정책과 실제 migration 실행 → backend / 외부 owner (frontend 계약 밖). ## 근거 (필수, 최소 1개+) | Source | 정당화하는 결정 | |---|---| | [[raw/official-docs/semver-2-0-0-spec-semver-official]] | D1 분류 어휘의 공식 근거(`SEMVER-C1`: MAJOR=incompatible / MINOR=backward-compatible additive / PATCH=backward-compatible fix). 단 SEMVER-C1은 "무엇이 breaking인지" 자동 분류는 증명하지 않으므로 경계 정의는 project decision(D1). | | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | §3.3 compatibility_impact 어휘·§5.10 registry change protocol·§12.3 compatibility tuple·§12.5 rollback invariant·§9.2 cache discard·§6.4 config 검증·§15 `FE-GATE-014/015` — D1~D6 전부의 project-decision 근거. | > 공식 표준(semver)이 *어휘*를 주고, hub가 *프로젝트 적용 규칙과 tuple 필드*를 준다. 두 계층이 함께 D1~D6을 닫는다. ## TODO 각 항목 등급: `planned`(코드 없음). - [ ] 버전 tuple 행렬을 §구현 가이드 1에 확정 — 필드·source·compatibility 역할·mismatch 결과 — 등급: `planned` - [ ] additive/breaking 분류 fixture 표를 §구현 가이드 2에 확정(4개 schema 계열 × 각 등급 예시) — 등급: `planned` - [ ] migration/rollback 규칙 R1~R5를 §구현 가이드 3에 확정 — 등급: `planned` - [ ] `FE-GATE-014` config compatibility fixture(old/new config) + report artifact 스펙 — 등급: `planned` - [ ] `FE-GATE-015` release coherence fixture(mixed HTML/asset/config) + verification artifact 스펙 — 등급: `planned` - [ ] cache 호환성 default(discard) vs migration 선택 규칙 명세(§9.2 소유 조건) — 등급: `planned` ## 진행 중 메모 - hub는 `FE-OC-023`의 owner를 이 브랜치로 지정하지만 `FE-D*` 결정 표에는 이 브랜치를 owner로 둔 행이 없다. 즉 이 브랜치는 *결정*이 아니라 *집행 규칙(governance)*을 소유한다 — 다른 브랜치의 `FE-D012/013/016/019`가 만든 schema 변경을 `FE-OC-023` 규칙으로 검사한다. - 미해결 위험(seed에서 승계): additive 변경이 cache+config+release **조합**에서 breaking이 될 수 있다(§구현 가이드 3의 Open Risk / R4에서 추적). - 버전 encoding(정수 MAJOR vs semver 문자열)은 hub가 "major incompatibility"만 말하고 literal 표기는 정하지 않았다 → §구현 가이드에서 `UNSUPPORTED_IMPL_DECISION`으로 표시. ## 결정 사항 > 아래는 Decision Evidence Map의 prose 요약. 근거는 Sources 및 hub 섹션 참조. - 2026-07-18: **D1** compatibility_impact 분류 어휘를 `{none, additive, behavior-change, breaking}` 단일 enum으로 채택하고 API/config/storage/release 4개 schema 계열 모두에 적용 / 이유: hub §3.3이 이 4값을 이미 정의; semver `SEMVER-C1`이 breaking/additive/fix 의미론을 공식 뒷받침 / 대안: 계열별 별도 어휘 / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3 + `raw/official-docs/semver-2-0-0-spec-semver-official.md#SEMVER-C1`. - 2026-07-18: **D2** boot 호환성 identity를 `(buildId, configSchemaVersion, apiContractVersion, assetManifestHash, releaseId)` tuple로 판정하고 string lexical compare를 금지 / 이유: hub §12.3이 tuple과 비교 규칙을 명시 / 대안: 단일 monolithic release 버전 문자열 비교 / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.3 + §5.9. - 2026-07-18: **D3** 각 schema 계열은 독립 버전 필드를 가지며 breaking = MAJOR 상향(config/API), storage는 `schemaVersion` increment, query는 namespace version bump / 이유: hub §5.4/§5.5/§5.7이 필드를 정의; semver `SEMVER-C1` MAJOR 의미론 / 대안: 전 계약 공통 단일 버전 / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.4 §5.5 §5.7. - 2026-07-18: **D4** breaking/behavior-change 변경은 migration·version bump·discard·fallback 중 하나 + test evidence 없이 merge 금지 / 이유: hub §3.3(4)·§5.10(4) 규칙 / 대안: 없음(invariant) / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3 §5.10. - 2026-07-18: **D5** rollback은 coherent tuple 집합(HTML+asset manifest+assets+compatible config+compatible API+release manifest)을 복원하고 HTML-only rollback을 금지 / 이유: hub §12.5 rollback invariant / 대안: 없음(invariant) / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.5. - 2026-07-18: **D6** 호환 불가 cache data는 default로 discard(재사용 금지)하며 migration을 선택할 때만 본 브랜치가 fixture·rollback을 소유 / 이유: hub §9.2 / 대안: 항상 migration / 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §9.2. ## 결정-근거 매핑 | Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk | |---|---|---|---|---|---| | D1 | compatibility_impact 어휘 = `{none, additive, behavior-change, breaking}` 단일 enum, 4개 schema 계열 공통 (`FE-OC-023`) | 4개 계열이 하나의 governance register를 공유하는 한 유지; 어떤 계열이 5번째 impact class가 필요하면 계열별 어휘로 분기 | `raw/official-docs/semver-2-0-0-spec-semver-official.md#SEMVER-C1`; [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3 | `official-standard`(어휘) + `project-decision`(경계) | semver는 "무엇이 breaking인지"를 자동 분류하지 않음(`SEMVER-C1` does-not-prove) — 경계 정의가 사람 판단에 남음 | | D2 | boot 호환성 identity = 5-field tuple `(buildId, configSchemaVersion, apiContractVersion, assetManifestHash, releaseId)`, lexical compare 금지 (`FE-OC-023`, `FE-OC-016`) | static SPA release 인 동안 유지; SSR/edge 도입 시 별도 project fork(§6.2) 또는 tuple 차원 추가 시 재검토 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.3, §5.9 | `project-decision` | tuple 필드 중 하나라도 source가 비어 있으면(예: provider가 releaseId 미노출) 판정 불가 → §9 검증 대상 | | D3 | 계열별 독립 버전 필드; breaking→config/API MAJOR 상향, storage `schemaVersion` increment, query namespace version bump (`FE-OC-004`, `FE-OC-007`, `FE-OC-012`, `FE-OC-013`) | 외부 codegen SSOT가 없는 동안 유지; code generation SSOT 채택 시 버전 표기를 codegen 산출로 이관(hub `FE-D018` revisit trigger와 정렬) | `raw/official-docs/semver-2-0-0-spec-semver-official.md#SEMVER-C1`; [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.4, §5.5, §5.7 | `official-standard` + `project-decision` | literal encoding(정수 MAJOR vs semver 문자열) 미확정 → §구현 가이드 `UNSUPPORTED_IMPL_DECISION` | | D4 | breaking/behavior-change는 migration·version bump·discard·fallback 중 하나 + test evidence 없이 merge 금지 (`FE-OC-023`) | invariant — 항상 성립. 단 "additive"로 분류된 변경은 이 게이트를 우회하므로 분류 정확성이 전제 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3, §5.10 | `project-decision`(invariant) | 오분류(breaking을 additive로) 시 게이트가 조용히 통과 → D1 분류 fixture로 방어 | | D5 | rollback은 coherent tuple 집합 복원, HTML-only rollback 금지 (`FE-OC-017`, `FE-OC-023`) | invariant — 항상 성립. 실제 drill 실행·pointer switch mechanism은 release-cache-rollback owner에 위임 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.5 | `project-decision`(invariant) | provider가 atomic pointer/cache purge를 지원하지 않으면 coherence 보장 불가 → reachability probe 필요(§12.5) | | D6 | 호환 불가 cache data는 default discard; migration 선택 시에만 본 브랜치가 fixture·rollback 소유 (`FE-OC-012`, `FE-OC-013`) | offline/persistence 요구가 없어 data 손실이 허용되는 동안 discard 유지; offline 요구가 생기면 migration으로 전환(hub `FE-D019` service worker off 조건과 연동) | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §9.2 | `project-decision` + `conditional-default` | discard가 UX상 허용되는지 미검증(현재 persistence default off이라 위험 낮음) | ## 구현 가이드 > `planned` blueprint. 프론트엔드 코드가 없으므로 경로는 hub §4.6 Planned directory blueprint / §5 registry owner map에서 인용한 *예정 경로*이다. 실제 path는 repository 생성 후 확정한다. ### 1. 버전 tuple 행렬 (Version tuple matrix) > **Trace**: D2 (5-field boot tuple) + D3 (계열별 버전 필드). 근거 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §12.3 (tuple + 비교 규칙), §5.9 (release token registry), §5.4 (`CONFIG_SCHEMA_VERSION`/`API_CONTRACT_VERSION`). > > - **UNSUPPORTED_IMPL_DECISION**: literal 버전 encoding(정수 MAJOR `"3"` vs semver 문자열 `"3.1.0"`). hub는 "major incompatibility"만 말하고 표기를 정하지 않음. trade-off: 정수 MAJOR는 boot 호환 판정이 가장 단순하나 additive/minor 가시성을 잃음 → **boot 판정용 정수 MAJOR + 진단용 optional MINOR** 병기를 제안(planned). > - **UNSUPPORTED_IMPL_DECISION**: 필드 저장 위치 파일명(예: `src/contracts/compatibility-tuple.js`). hub §4.6은 `src/bootstrap/`, `src/contracts/` 계층만 주고 파일명은 미지정. trade-off: contract 계층에 두어 boot·application 양쪽이 참조 가능하게 함. | 버전 필드 | Source (§5 registry) | Compatibility 역할 | Mismatch 시 동작 (§12.3) | 정규화 error kind (§5.6) | |---|---|---|---|---| | `buildId` | CI build (`VITE_BUILD_ID`, §5.4) | asset/HTML coherence | assetManifestHash와 함께 coherence 판정 | `DEPLOY_MISMATCH` | | `configSchemaVersion` | runtime config schema (`CONFIG_SCHEMA_VERSION`, §5.4/§5.9) | boot compatibility | major incompatible → boot fail, product route 미mount | `BOOT_CONFIG_FAILURE` | | `apiContractVersion` | frontend/backend agreement (`API_CONTRACT_VERSION`, §5.4/§5.9) | schema compatibility | incompatible → route mount fail 또는 explicitly supported compatibility adapter | `DEPLOY_MISMATCH` | | `assetManifestHash` | build output (§5.9) | chunk integrity/mismatch | mismatch → controlled reload **once**(§10.2 guard) | `CHUNK_LOAD_FAILURE` | | `releaseId` | deploy system (§5.9) | rollback target | 나머지 버전 호환 시 mismatch → warning telemetry 후 continue 가능 | (telemetry only) | | storage `schemaVersion` | storage registry physicalKey `v` (§5.5) | 영속 data 호환 | previous version 읽으면 migration 또는 discard | `STORAGE_*` / discard | | query namespace version | query key registry (§5.7) | cache identity partition | API/schema breaking → namespace version bump; 호환 불가 cache → discard(D6) | `QUERY_CACHE_FAILURE` | 핵심 규칙(§12.3 그대로): **string lexical compare로 버전 호환을 판정하지 않는다.** 각 필드는 선언된 버전 값으로만 비교한다. ### 2. Additive vs breaking 분류 fixture > **Trace**: D1 (분류 어휘) + D4 (분류→required action). 근거 `raw/official-docs/semver-2-0-0-spec-semver-official.md#SEMVER-C1`, [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3, §6.4 (unknown key policy), §5.5, §5.7. > > - **UNSUPPORTED_IMPL_DECISION**: 분류를 사람이 PR checklist로 판정할지 diff 도구로 자동화할지. hub §3.3은 *수동 프로토콜*만 정의. trade-off: 초기엔 수동 checklist + fixture로 회귀 방지, 자동 diff 도구는 registry-governance 브랜치 tooling으로 위임(planned). > - **UNSUPPORTED_IMPL_DECISION**: fixture 디렉터리·파일명(예: `test/compatibility/fixtures/*.json`). hub는 fixture *존재*(§15 "old/new config versions", "mixed HTML/assets/config")만 요구, 경로 미지정. trade-off: gate별 하위 폴더로 분리해 `FE-GATE-014`/`015`가 독립 소비. | 변경 예시 | compatibility_impact | 근거 규칙 | Required action | |---|---|---|---| | config에 optional key 추가(schema passthrough/default 존재) | `additive` | §6.4 unknown key: additive keys allowed only if schema explicitly passthroughs | 버전 bump optional, migration 불필요 | | config에 required key 추가 / 기존 key 의미 변경 | `breaking` | §5.4 `CONFIG_SCHEMA_VERSION` compatibility fail | configSchemaVersion MAJOR 상향 + migration/fallback + `FE-GATE-014` fixture | | API 응답에 optional field 추가(schema가 unknown 안전 처리) | `additive` | §6.4 default strict; passthrough 시 additive | none/additive, apiContractVersion 유지 | | API 응답 field 제거·rename(mapper가 소비) | `breaking` | §5.7 "API/schema breaking change" | apiContractVersion 상향 + compatibility adapter 또는 coordinated release | | storage 값 shape 변경 | `breaking` | §5.5 "incompatible change 시 increment", migration/discard | storage `schemaVersion` increment + migration 또는 discard(D6) | | release asset set 변경(chunk hash 변경) | 호환상 `none` | §12.3 assetManifestHash coherence | atomic deploy 순서(§12.4), coherence는 `FE-GATE-015`가 검증 | | error kind enum 제거 | `breaking`(behavior-change) | §5.6 stable enum | consumer migration + version note, D4 게이트 | 분류 경계의 근거 한계: `SEMVER-C1`은 MAJOR=incompatible / MINOR=additive / PATCH=fix *의미론*을 주지만 "내부 구현 변경이 API에 미치는 영향을 자동 분류하지 않는다"(does-not-prove). 따라서 위 표의 각 행 경계는 **project decision(D1)**이며 fixture로 회귀 고정한다. ### 3. rollback 규칙 > **Trace**: D4 (merge 게이트) + D5 (rollback coherence) + D6 (cache discard). 근거 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §3.3, §5.10, §9.2, §12.5. > > - **UNSUPPORTED_IMPL_DECISION**: migration 함수 배치·명명(예: storage per-version migrator API 모양). hub §5.5는 "migration 또는 discard" 원칙만, mechanism 미지정. trade-off: storage adapter 소유이므로 storage-registry 브랜치와 공동 정의 — 본 브랜치는 *규칙*만, migrator *구현*은 위임(R3). - **R1 (no silent breaking)**: `compatibility_impact ∈ {behavior-change, breaking}` 인 변경은 migration OR version bump + test evidence 없이 merge 금지(§3.3.4). additive/none은 게이트 우회 가능하나 §2 분류 fixture로 오분류 방어. - **R2 (breaking → 처리 택1)**: registry/storage/cache breaking은 version bump와 함께 **migration · discard · fallback** 중 하나를 명시(§5.10.4, §9.2). "택1"을 비우면 orphan token scan(§5.10.8)과 D4 게이트가 fail. - **R3 (rollback coherence)**: rollback target은 prior HTML + prior asset manifest·assets + compatible runtime config + compatible API contract(또는 backend compatibility window) + release manifest 의 **coherent set**을 복원한다(§12.5). HTML만 과거로 되돌리고 config를 최신에 남기는 rollback 금지. - **R4 (조합 breaking 방어)**: 개별 additive라도 cache+config+release **조합**에서 incompatible하면 D6에 따라 cache discard로 강등한다(§9.2). 이 조합 판정은 §1 tuple 행렬 전체를 함께 평가한다. — *잔여 위험: 조합 폭발을 전수 fixture로 덮지 못할 수 있음(§9 검증 대상).* - **R5 (비교 방식)**: 모든 버전 비교는 선언 필드 기준(§12.3), lexical string compare 금지. gate 소유 매핑: | Gate | 이 브랜치 산출물 | |---|---| | `FE-GATE-014@1` config compatibility (Owner = 본 branch) | old/new config version fixture 제공 | | `FE-GATE-015@1` release coherence (Owner = release-cache) | version tuple 호환 판정 공급 | | `FE-GATE-004@1` runtime schema (Owner = runtime-schema-validation) | config invalid matrix 에 compatibility 필드 기여 | 각 gate 의 blocking scope·pass condition·evidence artifact 는 hub §15.1 소유이며 여기에 옮겨 적지 않는다. > **UNSUPPORTED_IMPL_DECISION**: artifact 파일 경로(예: `artifacts/release/compatibility-report.json`). hub §15는 artifact *이름*("compatibility report"/"release verification")만 주고 경로 미지정. trade-off: §14.3 `pnpm verify:release`(`artifacts/release/verification.json`) 관례를 따라 `artifacts/release/` 하위로 통일(planned). ## 엣지·실패·의존 - **실패·엣지 경로**: - config schema major incompatible → `BOOT_CONFIG_FAILURE`, product route 미mount, boot error shell만 렌더(§6.3). - API contract incompatible → route mount fail 또는 supported compatibility adapter, `DEPLOY_MISMATCH`(§12.3). - asset manifest mismatch → controlled reload **once**; 같은 release pair 두 번째 실패 시 auto reload 중단·rollback/support surface(§10.2 `CHUNK_RELOAD_GUARD`). - releaseId만 mismatch·나머지 호환 → warning telemetry(`release.mismatch.detected`) 후 continue(§12.3). - 호환 불가 cache → discard, 재사용 금지(§9.2, D6). - partial rollout / cached config / mixed release: tuple 조합이 incompatible일 수 있음 → R4로 강등, 잔여는 `needs-confirmation`. - **다른 계약 의존** (§20 Dependency + §4.3 matrix; 각 sibling은 FE-OC 계약으로만 참조 — 로컬 D 번호 미확인): - [[raw/branch-notes/feature-frontend-contract-registry-governance]] 의 `FE-OC-022` — 8개 registry가 single owner·compatibility impact를 기록해야 본 브랜치 분류가 대상 필드를 가짐. 그 계약이 바뀌면 §1 tuple 행렬 필드 source가 흔들린다. - [[raw/branch-notes/feature-runtime-schema-validation-contract]] 의 `FE-OC-007` — boundary schema 검증이 additive/breaking을 실제로 감지(unknown key strict/passthrough)한다. §2 분류의 런타임 근거. - [[raw/branch-notes/feature-frontend-storage-registry-contract]] 의 `FE-OC-013` — storage `schemaVersion`·migration/discard mechanism 소유. 본 브랜치의 cache-discard 결정과 §3 R2가 이 계약 위에서 동작. - [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] 의 `FE-OC-004` — `CONFIG_SCHEMA_VERSION` 을 runtime config로 공급(그 브랜치 결정 근거는 hub [[raw/project-notes/ca-skeleton-frontend-operational-contract]] FE-D012, FE-D013). - [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] 의 `FE-OC-016`, `FE-OC-017` — 실제 rollback drill·release tuple 산출. 본 브랜치 rollback-coherence 규칙의 집행 주체(그 브랜치 근거는 hub [[raw/project-notes/ca-skeleton-frontend-operational-contract]] FE-D019~FE-D023). ## 검증해야 할 주장 | Claim | Why uncertain | How to verify | Status | |---|---|---|---| | breaking change가 migration/version bump 없이 배포되지 않는다 | CI·release flow 없음, 코드 없음 | additive/breaking synthetic fixture(§2) → `FE-GATE-014` config compatibility test(old/new config: supported pass / incompatible boot fail) | `needs-confirmation` | | release coherence가 mixed HTML/asset/config를 탐지한다 | 실제 release verification 미실행 | `FE-GATE-015` mixed fixture → mismatch detected / coherent set passes → release verification artifact | `needs-confirmation` | | 버전 비교가 lexical string compare에 의존하지 않는다 | 구현 없음 | tuple 비교 함수 unit test에 `"9" vs "10"` 류 lexical trap fixture 포함 | `planned` | | 호환 불가 cache data가 discard되고 재사용되지 않는다 | query cache 구현 없음 | query namespace version bump 시 stale cache discard integration test(§9.2) | `planned` | | rollback이 coherent tuple 집합을 복원한다(HTML-only rollback 차단) | 실제 rollback drill 없음 | `FE-GATE-016` rollback drill: HTML-only rollback fixture가 fail, coherent tuple rollback이 pass(§12.5) | `needs-confirmation` | | additive 변경이 cache+config+release 조합에서 breaking이 되지 않는다(또는 R4로 강등된다) | 조합 폭발, 전수 fixture 어려움 | 대표 조합 fixture matrix로 R4 강등 경로 검증; 미커버 조합은 명시적 잔여 위험 기록 | `needs-confirmation` | ## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때) - 스캐폴딩 단계: `/coverage` 실행 전 수동 행을 만들지 않는다. ## 마주친 문제 - 없음 — 스캐폴딩 단계. ## 묶음 (이 branch에서 파생된 자료) ### 가져온 artifact 계약 | Artifact Ref | Owner | Producer | Schema Ref | |---|---|---|---| | `ART-FE-003@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | `harness/source/artifact-schemas/ca-skeleton-frontend/release-verification.schema.json` | ## 가져온 프로젝트 계약 | Ref | Owner | 요약 | Branch 적용 | |---|---|---|---| | `FE-GATE-004@1` | [[raw/branch-notes/feature-runtime-schema-validation-contract]] | invalid fixture 가 예상 kind 로 거부되지 않으면 merge 를 MUST 차단 | import 참조로 적용 | | `FE-GATE-015@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | 혼재된 release 조합이 감지되지 않으면 release 를 MUST 차단 | import 참조로 적용 | | `FE-GATE-016@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | rollback 과 smoke 증거가 없으면 production promotion 을 MUST 차단 | import 참조로 적용 | | `FE-OC-004@1` | [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] | build-time, runtime-public, secret config를 MUST 분리하고 boot 전에 runtime config를 검증 | import 참조로 적용 | | `FE-OC-007@1` | [[raw/branch-notes/feature-runtime-schema-validation-contract]] | JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 | import 참조로 적용 | | `FE-OC-012@1` | [[raw/branch-notes/feature-server-state-caching-contract]] | query key와 invalidation은 registry factory만 MUST 사용 | import 참조로 적용 | | `FE-OC-013@1` | [[raw/branch-notes/feature-frontend-storage-registry-contract]] | storage key는 namespace·version·classification을 MUST 가지며 token/secret 저장을 금지 | import 참조로 적용 | | `FE-OC-016@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | HTML, asset, runtime config, release manifest cache policy를 MUST 구분 | import 참조로 적용 | | `FE-OC-017@1` | [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] | rollback은 immutable prior release로 수행하고 build/config/API compatibility를 MUST 검증 | import 참조로 적용 | - 없음 — 자식 자료는 생성 후 controller가 parent Cluster와 함께 등록한다. ## 관련 일일 노트 - 없음 — daily note는 이 작업에서 수정하지 않는다. ## 완료 후 정리 - PR 링크: 없음 - 리뷰 메모: 없음 - 머지 결과 / 배포 환경: `planned` - **wiki 추출 대상** (verified만): 없음 - **추출하지 않을 항목** (planned / documented-only / abandoned): 현재 전체