capability 가 OFF 인 프로젝트에서 gate 를 PASS 라 하면 거짓말이고 FAIL 이라 하면 영원히 배포할 수 없다. NOT_APPLICABLE 을 도입하되 FE-GATE-033 이 번들 부재를 증명했을 때만 유효하게 묶었다. FE-GATE-033 자신은 NOT_APPLICABLE 을 취할 수 없다 — capability 를 하나도 쓰지 않는 프로젝트도 '쓰지 않는다'를 증명해야 한다.
233 KiB
title, source_type, status, confidence, tags, related_projects, last_reviewed, diagrams, architecture_review, status_label, project_revision, url, semantic_surface_exclusions, imports
| title | source_type | status | confidence | tags | related_projects | last_reviewed | diagrams | architecture_review | status_label | project_revision | url | semantic_surface_exclusions | imports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CA Skeleton Frontend Operational Contract | project-note | draft | medium |
|
|
2026-07-18 |
|
|
active | 1 |
|
|
CA Skeleton Frontend Operational Contract
이 문서는 도메인·비즈니스 기능을 제거한 frontend skeleton의 prospective operational contract다. 현재 LLM Wiki workspace에서 manifest·lockfile·Vite config·
src/mainentry pattern을 검색했으나 일치 파일을 찾지 못했다. frontend 구현 repository 위치는 아직 식별되지 않았다. test, CI, deploy artifact는 별도 전용 탐색 command를 실행하지 않았으므로 존재 여부가UNVERIFIED다. 따라서 본문에 적힌 architecture, command, threshold, file path, component, test, runbook은 모두planned또는documented-only다. 이 문서만으로actually-implemented,locally-verified,prod-verified를 주장할 수 없다.
0. 문서 사용 계약
0.1 규범 키워드
이 문서의 규범 문장은 다음 의미로 사용한다.
| 키워드 | 의미 | 위반 처리 |
|---|---|---|
MUST |
구현과 검증에 반드시 반영할 project-wide invariant | acceptance gate 실패 |
MUST NOT |
허용하지 않는 구현·운영 상태 | acceptance gate 실패 |
SHOULD |
기본적으로 따르되 예외 근거와 owner 승인이 있으면 변경 가능 | risk 또는 decision row 필요 |
MAY |
조건부 선택 사항 | 활성화 시 owner·test·runbook 필요 |
규범 키워드는 구현 완료 사실이 아니라 앞으로 구현이 따라야 할 계약을 뜻한다.
0.2 증거 등급 경계
| 등급 | 현재 허용 여부 | 이 문서에서의 의미 |
|---|---|---|
planned |
허용 | 목표, 기본값, command, artifact path가 문서에만 있음 |
documented-only |
허용 | 근거 raw 또는 설계 문서가 있으나 대응 코드·실행 결과가 없음 |
actually-implemented |
현재 금지 | repository의 구체 path와 commit이 확인되어야 함 |
locally-verified |
현재 금지 | 재현 가능한 command의 exit code와 artifact가 있어야 함 |
prod-verified |
현재 금지 | release ID, 운영 측정, incident 또는 dashboard evidence가 있어야 함 |
현재 workspace에서 다음 탐색은 결과가 없었다.
rg --files | rg '(^|/)(package\.json|pnpm-lock\.yaml|yarn\.lock|package-lock\.json|bun\.lockb?|vite\.config\.[^/]+|src/main\.(jsx|js))$'
이 결과가 증명하는 범위는 현재 LLM Wiki workspace에서 위 정규식에 해당하는 entry artifact를 찾지 못했다는 사실뿐이다. 전체 src/, test, CI, deploy artifact의 부재나 원격·별도 workspace의 부재로 확장 해석하지 않는다.
0.3 현재 판정
Contract maturity: documented-only
Implementation entry evidence: searched patterns not found in current wiki workspace
Diagram files: scoped reviewer PASS — overview 100/100, deployment 100/100
Test evidence: UNVERIFIED — dedicated search/command not recorded
CI evidence: UNVERIFIED — dedicated search/command not recorded
Deployment evidence: UNVERIFIED — dedicated search/command not recorded
Readiness: NOT_READY
NOT_READY는 설계 문서가 무효라는 뜻이 아니다. 구현·검증·운영 주장을 승격할 evidence gate가 아직 닫히지 않았다는 뜻이다.
0.4 원래 목표 → 가정 → 조치
- 목표: 새 frontend feature가 추가되어도 API 호출, 실패 분류, runtime validation, async UI, telemetry, release rollback을 같은 규칙으로 수행한다.
- 가정 A: client-only SPA가 browser에서 실행되고 backend API와 분리 배포된다.
- 무효 조건: SSR, server component, edge rendering이 필수인 제품으로 범위가 바뀐다.
- 확인 방법: repository 생성 시 deployment target과 rendering mode를
FE-D003에 기록한다.
- 가정 B: source language는 JavaScript ESM이며 compile-time type coverage가 제한된다.
- 무효 조건: TypeScript strict mode로 project constraint가 변경된다.
- 확인 방법:
package.json,jsconfig.json또는tsconfig.json과 source extension을 확인한다.
- 가정 C: backend가 structured JSON envelope와 stable error vocabulary를 제공하거나 frontend adapter가 이를 정규화할 수 있다.
- 무효 조건: 여러 backend가 서로 다른 protocol·schema를 제공하고 통합 adapter를 둘 수 없다.
- 확인 방법: OpenAPI 또는 captured fixture를 runtime schema와 대조한다.
- 문제: 이 가정 아래에서 owner·default·failure·test가 없으면 page마다 다른 retry, storage, route, error UI가 생기고 release mismatch를 일관되게 복구할 수 없다.
- 조치: stable
FE-D*,FE-OC-*, registry owner, acceptance gate, runbook을 project hub에 고정하고 상세 구현은 single-owner branch로 위임한다. - 반대 논거: 단일 화면 prototype이라면 이 계약의 초기 비용이 기능 가치보다 클 수 있다.
- 확인 방법: route 1개, 외부 API 0개, 배포 0회인 throwaway prototype인지 확인한다.
- 처리: 그런 경우 이 skeleton을 채택하지 않고 별도 experiment로 격리한다.
0.5 범위
In scope:
- client-only React SPA의 boot, routing, API boundary, state, cache, storage, render failure, telemetry, build, release, rollback 계약
- JavaScript의 typecheck-equivalent gate와 runtime schema validation
- backend API 및 auth provider와 연결되는 얇은 integration port
- static hosting과 browser runtime의 failure mode
- sample feature slice를 통한 contract enforcement
Out of scope:
- domain-specific page, business rule, copy, branding, product analytics taxonomy
- token 발급, token 저장, refresh token rotation, logout propagation의 lifecycle 소유
- backend authorization 판정 대체
- SSR, RSC, edge rendering, native mobile runtime
- DB, Kafka, JVM, server thread pool, container orchestration 세부 구현
- 특정 CDN·cloud vendor의 console 절차
인증 lifecycle은 raw/project-notes/keycloak-patterns-overview가 다룬다. 본 skeleton은 외부 auth owner가 제공하는 최소 session interface만 소비한다.
1. 프로젝트 개요
1.1 한 줄 요약
도메인 기능 없이도 새 React SPA가 같은 architecture, API failure language, runtime validation, quality gate, release rollback을 재사용하도록 만드는 frontend operational skeleton이다.
1.2 현재 상태
| 항목 | 값 |
|---|---|
| 기간 | 2026-07-18 ~ in-progress |
| status | draft, active |
| 역할 | 설계자 / 향후 구현자 |
| implementation repository | current wiki workspace의 entry artifact search에서 미식별; remote/other workspace UNVERIFIED |
| architecture diagram | 2개 scoped review 100/100; implementation·full release topology는 UNVERIFIED |
| test / CI / deploy | dedicated evidence search/command 미기록, UNVERIFIED |
| 외부 공개 가능 범위 | 설계 의도·검토 대안·계약 구조만 |
1.3 해결하려는 문제
- page마다
fetch, timeout, retry, error mapping을 다시 만들면 동일 status가 서로 다른 UX로 나타난다. - JavaScript boundary에 runtime validation이 없으면 malformed JSON과 schema drift가 render tree 내부의
TypeError로 늦게 나타난다. - route, env, query key, storage key, telemetry event, release token이 분산되면 rename과 rollback 영향 범위를 계산하기 어렵다.
- build-time config와 runtime config를 구분하지 않으면 한 environment의 endpoint가 다른 release bundle에 굳어지거나 public bundle에 secret이 들어갈 수 있다.
- hashed chunk와 HTML·runtime config가 서로 다른 release를 가리키면
ChunkLoadError, boot loop, stale cache가 발생할 수 있다. - architecture rule이 문장에만 있으면 presentation이 adapter를 직접 import하고 application port owner가 흐려진다.
1.4 성공 조건
아래는 목표이며 아직 측정 결과가 아니다.
| ID | 성공 조건 | 현재 상태 |
|---|---|---|
FE-SC-001 |
repository, lockfile, bootstrap command가 존재하고 fresh clone install/build가 exit 0 | planned |
FE-SC-002 |
sample slice가 API → schema → mapper → application → presentation을 관통 | planned |
FE-SC-003 |
금지 import fixture가 architecture gate를 실패시킴 | planned |
FE-SC-004 |
failure taxonomy의 각 blocking row에 최소 1개 automated test가 있음 | planned |
FE-SC-005 |
route/API-operation/env/storage/error/query/telemetry/release registry의 ad hoc token이 0건 | planned |
FE-SC-006 |
lint, checkJs, runtime-schema, unit, component, integration, e2e, a11y, build, bundle, security gate가 CI에서 분리 실행 | planned |
FE-SC-007 |
release mismatch와 rollback runbook이 staging drill evidence를 남김 | planned |
FE-SC-008 |
두 draw.io 파일이 wiki-diagram-reviewer 기준을 통과하고 contract ID와 일치 |
documented-only — reviewer 100/100, 구현 topology는 UNVERIFIED |
2. Stable Contract Index
2.1 Contract lifecycle
FE-OC-* ID는 rename하지 않는다. 의미가 바뀌면 기존 ID를 superseded로 남기고 새 ID를 추가한다. branch는 이 표를 복사해 재정의하지 않고 owner로서 상세 mechanism과 test를 제공한다.
| Contract ID | Single owner | Normative summary | Minimum evidence | Status |
|---|---|---|---|---|
FE-OC-001 |
project hub (this file) | 모든 구현 주장은 evidence grade를 MUST 표시하고 repo evidence가 없는 상태에서 구현 완료를 MUST NOT 주장 | evidence ledger | documented-only |
FE-OC-002 |
feature-frontend-clean-architecture-layering-contract |
domain <- application <- presentation 의존 방향과 application-owned output port를 MUST 지킴 |
dependency rule report | planned |
FE-OC-003 |
feature-frontend-project-bootstrap-toolchain-contract |
package manager, engine, lockfile, source language, checkJs command를 한 곳에서 MUST 고정 | manifest + lockfile | planned |
FE-OC-004 |
feature-frontend-env-runtime-config-contract |
build-time, runtime-public, secret config를 MUST 분리하고 boot 전에 runtime config를 검증 | config schema test | planned |
FE-OC-005 |
feature-routing-navigation-guard-contract |
route ID/path/params/access/loading/error owner는 route registry 하나여야 함 | route registry snapshot | planned |
FE-OC-006 |
feature-api-client-response-envelope-contract |
모든 HTTP는 shared client를 MUST 통과하고 timeout·abort·response parsing을 page에서 구현하면 안 됨 | API contract tests | planned |
FE-OC-007 |
feature-runtime-schema-validation-contract |
JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 | schema fixtures | planned |
FE-OC-008 |
feature-frontend-error-classification-boundary-contract |
모든 failure는 stable frontend error kind로 MUST 정규화하고 raw body·stack을 UI에 노출하면 안 됨 | error catalog tests | planned |
FE-OC-009 |
feature-api-client-response-envelope-contract |
retry는 safe/idempotent request에 한정하고 cap·jitter·Retry-After를 MUST 적용 |
deterministic retry tests | planned |
FE-OC-010 |
feature-frontend-auth-session-integration-contract |
skeleton은 session state를 소비하되 token lifecycle을 MUST 소유하지 않음 | port contract test | planned |
FE-OC-011 |
feature-async-ui-state-contract |
async surface는 initial-loading, success, empty, terminal-error를 MUST 표현 | component state matrix | planned |
FE-OC-012 |
feature-server-state-caching-contract |
query key와 invalidation은 registry factory만 MUST 사용 | cache tests | planned |
FE-OC-013 |
feature-frontend-storage-registry-contract |
storage key는 namespace·version·classification을 MUST 가지며 token/secret 저장을 금지 | storage registry tests | planned |
FE-OC-014 |
feature-frontend-observability-logging-trace-contract |
telemetry는 best-effort이며 render·API success를 차단하면 안 되고 PII·token을 전송하면 안 됨 | redaction + sink failure test | planned |
FE-OC-015 |
feature-frontend-render-recovery-boundary-contract |
expected operational error와 render defect를 MUST 분리하고 reload loop를 금지 | error boundary tests | planned |
FE-OC-016 |
feature-frontend-release-cache-rollback-contract |
HTML, asset, runtime config, release manifest cache policy를 MUST 구분 | header evidence | planned |
FE-OC-017 |
feature-frontend-release-cache-rollback-contract |
rollback은 immutable prior release로 수행하고 build/config/API compatibility를 MUST 검증 | rollback drill artifact | planned |
FE-OC-018 |
feature-frontend-build-bundle-supply-chain-contract |
frozen lockfile, dependency review, secret scan, SBOM 또는 dependency inventory를 release gate에 MUST 포함 | security artifacts | planned |
FE-OC-019 |
feature-frontend-browser-security-boundary-contract |
browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | scan + lint tests | planned |
FE-OC-020 |
feature-frontend-test-taxonomy-contract |
gate 종류별 책임·fixture·artifact를 분리하고 실패를 warning으로 낮추면 안 됨 | CI workflow | planned |
FE-OC-021 |
feature-web-vitals-performance-budget-contract |
NFR은 device/network/cache/build context와 함께 MUST 측정 | machine-readable report | planned |
FE-OC-022 |
feature-frontend-contract-registry-governance |
9개 registry는 single primary owner와 compatibility impact를 MUST 기록 | registry diff check | planned |
FE-OC-023 |
feature-frontend-contract-compatibility-governance |
API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 | compatibility report | planned |
FE-OC-024 |
feature-sample-feature-slice-contract-fixture |
sample은 contract fixture이며 production feature가 의존하면 안 됨 | sample removal smoke | planned |
FE-OC-025 |
feature-frontend-operational-runbook-contract |
boot, chunk mismatch, API degradation, telemetry failure, rollback, realtime 연결, background 실행 runbook을 MUST 유지 | drill records | planned |
FE-OC-026 |
project hub (this file) | 외부 답변은 evidence grade를 MUST 보존하고 목표 수치를 측정 결과처럼 말하면 안 됨 | answer boundary checklist | documented-only |
FE-OC-027 |
feature-frontend-binary-file-io-store-contract |
파일 선택·다운로드·로컬 바이너리 저장은 등록된 port를 MUST 경유하고, 원시 File/Blob handle과 object URL 수명은 adapter 경계를 MUST NOT 벗어남 |
binary I-O fixtures | planned |
FE-OC-028 |
feature-frontend-cache-tier-cross-tab-invalidation-contract |
캐시 계층과 탭 간 무효화는 QueryCachePort 정책과 registry를 MUST 경유하고, release·config·API version이 불일치하는 영속 캐시를 MUST NOT 재사용 |
cache tier + cross-tab tests | planned |
FE-OC-029 |
feature-frontend-large-object-transfer-contract |
대용량 전송은 presigned 획득과 byte 전송의 credential 경계를 MUST 분리하고, 재개 가능 전송의 part 상태·무결성·취소를 MUST 소유 | transfer fixtures | planned |
FE-OC-030 |
feature-frontend-multi-protocol-api-transport-contract |
모든 protocol adapter는 동일한 application output port를 구현하고 protocol별 성공/실패를 정규화된 failure로 MUST 매핑하며, transport status만으로 성공을 판정하면 안 됨 | protocol mapping tests | planned |
FE-OC-031 |
feature-frontend-realtime-subscription-lifecycle-contract |
실시간 구독은 연결·재연결·재개·이벤트 검증·해제를 MUST 계약하고, 스키마 미검증 이벤트를 application으로 MUST NOT 전달하며 unmount 후 열린 구독을 MUST NOT 남김 | realtime lifecycle tests | planned |
FE-OC-032 |
feature-frontend-background-execution-worker-contract |
백그라운드 실행은 명시 owner·update UX·idempotency 조건을 MUST 갖추고, precaching으로 release coherence를 MUST NOT 훼손 | background execution tests | planned |
2.1.1 Contract Registry (typed)
위 §2.1 을 기계가 읽는 형식으로 고정한 것이다. 같은 사실이며 새 계약을 만들지 않는다. 소비 문서는 이 표를 복사하지 않고 frontmatter
imports에FE-OC-0NN@1로 pin 한다. owner 가 revision 을 올리면 pin 이 낡은 문서가STALE_IMPORTED_CONTRACT로 잡히고, 두 문서가 같은 계약을 소유하면DUPLICATE_CONTRACT_OWNER로 막힌다. 남의 계약 표를 다시 적으면FOREIGN_CONTRACT_RESTATEMENT다.Owner값은 문서 slug 다.FE-OC-001·FE-OC-026은 §20 서두가 밝힌 대로 이 project hub 가 owner 다.Trigger는 §15.1 에서 해당 계약을 Covered FE-OC 로 가진 gate 다 — 여기서 새로 만든 값이 아니다. gate(FE-GATE-*) 행의Owner와Revision은 이 표가 SSOT 다. 각 gate 의 fixture·Covered FE-OC·pass condition 규범은 §15.1 이 계속 보유하며 여기로 옮기지 않는다 — 이 표는 누가 소유하고 몇 번째 판인가, §15.1 은 무엇을 검사하는가 다. Owner 는 §15.1 의Evidence artifact를 §20Measurable completion이 실제로 산출하는 branch 다.FE-GATE-017만 검토 대상 다이어그램이 hub frontmatterdiagrams:소유이므로 hub 가 owner 다.
| Contract ID | Concern Key | Revision | Type | Owner | Trigger | Required Effect | Enforcement | Status |
|---|---|---|---|---|---|---|---|---|
FE-OC-001 |
fe.evidence-grade |
1 | operational-contract | ca-skeleton-frontend-operational-contract |
구현 주장을 문서에 쓸 때 | 모든 구현 주장은 evidence grade를 MUST 표시하고 repo evidence가 없는 상태에서 구현 완료를 MUST NOT 주장 | evidence ledger | active |
FE-OC-002 |
fe.clean-architecture-layering |
1 | operational-contract | feature-frontend-clean-architecture-layering-contract |
layer 간 import 를 추가·변경할 때 | domain <- application <- presentation 의존 방향과 application-owned output port를 MUST 지킴 |
dependency rule report | active |
FE-OC-003 |
fe.project-bootstrap-toolchain |
1 | operational-contract | feature-frontend-project-bootstrap-toolchain-contract |
toolchain·manifest·lockfile 을 변경할 때 | package manager, engine, lockfile, source language, checkJs command를 한 곳에서 MUST 고정 | manifest + lockfile | active |
FE-OC-004 |
fe.env-runtime-config |
1 | operational-contract | feature-frontend-env-runtime-config-contract |
config key 를 추가하거나 boot 순서를 바꿀 때 | build-time, runtime-public, secret config를 MUST 분리하고 boot 전에 runtime config를 검증 | config schema test | active |
FE-OC-005 |
fe.routing-navigation-guard |
1 | operational-contract | feature-routing-navigation-guard-contract |
route 를 추가·변경할 때 | route ID/path/params/access/loading/error owner는 route registry 하나여야 함 | route registry snapshot | active |
FE-OC-006 |
fe.api-client.shared-transport |
1 | operational-contract | feature-api-client-response-envelope-contract |
HTTP 요청을 보낼 때 | 모든 HTTP는 shared client를 MUST 통과하고 timeout·abort·response parsing을 page에서 구현하면 안 됨 | API contract tests | active |
FE-OC-007 |
fe.runtime-schema-validation |
1 | operational-contract | feature-runtime-schema-validation-contract |
외부 응답을 경계에서 받을 때 | JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 | schema fixtures | active |
FE-OC-008 |
fe.error-classification-boundary |
1 | operational-contract | feature-frontend-error-classification-boundary-contract |
failure 가 발생할 때 | 모든 failure는 stable frontend error kind로 MUST 정규화하고 raw body·stack을 UI에 노출하면 안 됨 | error catalog tests | active |
FE-OC-009 |
fe.api-client.retry-policy |
1 | operational-contract | feature-api-client-response-envelope-contract |
요청이 실패해 재시도를 판단할 때 | retry는 safe/idempotent request에 한정하고 cap·jitter·Retry-After를 MUST 적용 |
deterministic retry tests | active |
FE-OC-010 |
fe.auth-session-integration |
1 | operational-contract | feature-frontend-auth-session-integration-contract |
session 상태를 읽거나 갱신할 때 | skeleton은 session state를 소비하되 token lifecycle을 MUST 소유하지 않음 | port contract test | active |
FE-OC-011 |
fe.async-ui-state |
1 | operational-contract | feature-async-ui-state-contract |
async surface 를 렌더할 때 | async surface는 initial-loading, success, empty, terminal-error를 MUST 표현 | component state matrix | active |
FE-OC-012 |
fe.server-state-caching |
1 | operational-contract | feature-server-state-caching-contract |
server state 를 캐시하거나 무효화할 때 | query key와 invalidation은 registry factory만 MUST 사용 | cache tests | active |
FE-OC-013 |
fe.storage-registry |
1 | operational-contract | feature-frontend-storage-registry-contract |
browser storage 에 값을 쓸 때 | storage key는 namespace·version·classification을 MUST 가지며 token/secret 저장을 금지 | storage registry tests | active |
FE-OC-014 |
fe.observability-logging-trace |
1 | operational-contract | feature-frontend-observability-logging-trace-contract |
telemetry event 를 emit 할 때 | telemetry는 best-effort이며 render·API success를 차단하면 안 되고 PII·token을 전송하면 안 됨 | redaction + sink failure test | active |
FE-OC-015 |
fe.render-recovery-boundary |
1 | operational-contract | feature-frontend-render-recovery-boundary-contract |
render 중 예외가 boundary 에 도달할 때 | expected operational error와 render defect를 MUST 분리하고 reload loop를 금지 | error boundary tests | active |
FE-OC-016 |
fe.release.cache-policy |
1 | operational-contract | feature-frontend-release-cache-rollback-contract |
release asset 을 배포하거나 cache header 를 정할 때 | HTML, asset, runtime config, release manifest cache policy를 MUST 구분 | header evidence | active |
FE-OC-017 |
fe.release.rollback |
1 | operational-contract | feature-frontend-release-cache-rollback-contract |
rollback 을 수행할 때 | rollback은 immutable prior release로 수행하고 build/config/API compatibility를 MUST 검증 | rollback drill artifact | active |
FE-OC-018 |
fe.build-bundle-supply-chain |
1 | operational-contract | feature-frontend-build-bundle-supply-chain-contract |
의존성을 설치하거나 production build 를 만들 때 | frozen lockfile, dependency review, secret scan, SBOM 또는 dependency inventory를 release gate에 MUST 포함 | security artifacts | active |
FE-OC-019 |
fe.browser-security-boundary |
1 | operational-contract | feature-frontend-browser-security-boundary-contract |
bundle·HTML·env 에 값을 넣을 때 | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | scan + lint tests | active |
FE-OC-020 |
fe.test-taxonomy |
1 | operational-contract | feature-frontend-test-taxonomy-contract |
gate 나 fixture 를 추가·변경할 때 | gate 종류별 책임·fixture·artifact를 분리하고 실패를 warning으로 낮추면 안 됨 | CI workflow | active |
FE-OC-021 |
fe.web-vitals-performance-budget |
1 | operational-contract | feature-web-vitals-performance-budget-contract |
NFR 을 측정하거나 보고할 때 | NFR은 device/network/cache/build context와 함께 MUST 측정 | machine-readable report | active |
FE-OC-022 |
fe.contract-registry |
1 | operational-contract | feature-frontend-contract-registry-governance |
9개 registry 중 하나를 변경할 때 | 9개 registry는 single primary owner와 compatibility impact를 MUST 기록 | registry diff check | active |
FE-OC-023 |
fe.contract-compatibility |
1 | operational-contract | feature-frontend-contract-compatibility-governance |
API·config·storage·release schema 를 변경할 때 | API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 | compatibility report | active |
FE-OC-024 |
fe.sample-feature-slice-contract |
1 | operational-contract | feature-sample-feature-slice-contract-fixture |
sample slice 를 만들거나 제거할 때 | sample은 contract fixture이며 production feature가 의존하면 안 됨 | sample removal smoke | active |
FE-OC-025 |
fe.operational-runbook |
1 | operational-contract | feature-frontend-operational-runbook-contract |
운영 장애가 발생하거나 drill 을 돌릴 때 | boot, chunk mismatch, API degradation, telemetry failure, rollback, realtime 연결, background 실행 runbook을 MUST 유지 | drill records | active |
FE-OC-026 |
fe.answer-boundary |
1 | operational-contract | ca-skeleton-frontend-operational-contract |
외부 공개 답변을 작성할 때 | 외부 답변은 evidence grade를 MUST 보존하고 목표 수치를 측정 결과처럼 말하면 안 됨 | answer boundary checklist | active |
FE-OC-027 |
fe.binary-file-io-store |
1 | operational-contract | feature-frontend-binary-file-io-store-contract |
파일을 고르거나 내려받거나 바이너리를 로컬에 쓸 때 | 파일 선택·다운로드·로컬 바이너리 저장은 등록된 port를 MUST 경유하고, 원시 File/Blob handle과 object URL 수명은 adapter 경계를 MUST NOT 벗어남 |
binary I-O fixtures | active |
FE-OC-028 |
fe.cache-tier-cross-tab |
1 | operational-contract | feature-frontend-cache-tier-cross-tab-invalidation-contract |
캐시를 영속화하거나 다른 탭에 무효화를 전파할 때 | 캐시 계층과 탭 간 무효화는 QueryCachePort 정책과 registry를 MUST 경유하고, release·config·API version이 불일치하는 영속 캐시를 MUST NOT 재사용 |
cache tier + cross-tab tests | active |
FE-OC-029 |
fe.large-object-transfer |
1 | operational-contract | feature-frontend-large-object-transfer-contract |
대용량 객체를 올리거나 스트리밍으로 내려받을 때 | 대용량 전송은 presigned 획득과 byte 전송의 credential 경계를 MUST 분리하고, 재개 가능 전송의 part 상태·무결성·취소를 MUST 소유 | transfer fixtures | active |
FE-OC-030 |
fe.multi-protocol-transport |
1 | operational-contract | feature-frontend-multi-protocol-api-transport-contract |
REST 이외 protocol 로 operation 을 호출할 때 | 모든 protocol adapter는 동일한 application output port를 구현하고 protocol별 성공/실패를 정규화된 failure로 MUST 매핑하며, transport status만으로 성공을 판정하면 안 됨 | protocol mapping tests | active |
FE-OC-031 |
fe.realtime-subscription-lifecycle |
1 | operational-contract | feature-frontend-realtime-subscription-lifecycle-contract |
스트림을 구독하거나 해제할 때 | 실시간 구독은 연결·재연결·재개·이벤트 검증·해제를 MUST 계약하고, 스키마 미검증 이벤트를 application으로 MUST NOT 전달하며 unmount 후 열린 구독을 MUST NOT 남김 | realtime lifecycle tests | active |
FE-OC-032 |
fe.background-execution |
1 | operational-contract | feature-frontend-background-execution-worker-contract |
worker·service worker·background sync 를 등록하거나 갱신할 때 | 백그라운드 실행은 명시 owner·update UX·idempotency 조건을 MUST 갖추고, precaching으로 release coherence를 MUST NOT 훼손 | background execution tests | active |
FE-GATE-001 |
fe.gate.manifest-lockfile |
1 | gate | feature-frontend-project-bootstrap-toolchain-contract |
의존성을 설치하거나 lockfile 을 변경할 때 | lockfile 이 manifest 와 어긋나면 merge·release 를 MUST 차단 | install log | active |
FE-GATE-002 |
fe.gate.lint |
1 | gate | feature-frontend-architecture-enforcement-lint-contract |
소스를 수정해 merge 를 요청할 때 | 금지된 API·import 가 남아 있으면 merge 를 MUST 차단 | lint report | active |
FE-GATE-003 |
fe.gate.typecheck |
1 | gate | feature-frontend-project-bootstrap-toolchain-contract |
타입 주석이나 checkJs 설정을 변경할 때 | production diagnostic 이 남아 있으면 merge 를 MUST 차단 | check-types report | active |
FE-GATE-004 |
fe.gate.runtime-schema |
1 | gate | feature-runtime-schema-validation-contract |
경계에서 외부 응답·boot config 를 받을 때 | invalid fixture 가 예상 kind 로 거부되지 않으면 merge 를 MUST 차단 | schema + timing report | active |
FE-GATE-005 |
fe.gate.unit |
1 | gate | feature-frontend-test-taxonomy-contract |
unit 레벨 테스트를 추가·변경할 때 | unit 레벨이 실패하면 merge 를 MUST 차단하고 warning 으로 낮추면 안 됨 | unit XML | active |
FE-GATE-006 |
fe.gate.component |
1 | gate | feature-frontend-test-taxonomy-contract |
component 레벨 테스트를 추가·변경할 때 | component 레벨이 실패하면 merge 를 MUST 차단 | component XML | active |
FE-GATE-007 |
fe.gate.integration |
1 | gate | feature-frontend-test-taxonomy-contract |
integration 레벨 테스트를 추가·변경할 때 | MSW 기반 integration 매트릭스가 미충족이면 merge 를 MUST 차단 | integration XML | active |
FE-GATE-008 |
fe.gate.e2e |
1 | gate | feature-frontend-test-taxonomy-contract |
critical 사용자 시나리오를 변경할 때 | critical e2e 시나리오가 실패하면 merge·release 를 MUST 차단 | Playwright report | active |
FE-GATE-009 |
fe.gate.accessibility |
1 | gate | feature-accessibility-baseline-contract |
sample route 의 UI 를 변경할 때 | automated threshold 미달이거나 manual checklist 서명이 없으면 merge·release 를 MUST 차단 | a11y artifacts | active |
FE-GATE-010 |
fe.gate.architecture |
1 | gate | feature-frontend-architecture-enforcement-lint-contract |
layer 간 import 를 추가·변경할 때 | 금지된 layer import 가 통과하면 merge 를 MUST 차단 | dependency report | active |
FE-GATE-011 |
fe.gate.build |
1 | gate | feature-frontend-build-bundle-supply-chain-contract |
production build 를 만들 때 | clean production build 가 실패하거나 기대 artifact 가 없으면 merge·release 를 MUST 차단 | build manifest | active |
FE-GATE-012 |
fe.gate.bundle |
1 | gate | feature-frontend-build-bundle-supply-chain-contract |
번들 구성이나 chunk 분할을 바꿀 때 | 번들 NFR threshold 초과면 release 를 MUST 차단 | bundle report | active |
FE-GATE-013 |
fe.gate.security |
1 | gate | feature-frontend-build-bundle-supply-chain-contract |
의존성·시크릿·라이선스 표면을 변경할 때 | secret·vulnerability·license·dependency review 정책 위반이면 merge·release 를 MUST 차단 | SARIF/inventory/dependency diff report | active |
FE-GATE-014 |
fe.gate.config-compatibility |
1 | gate | feature-frontend-contract-compatibility-governance |
config schema 를 변경해 release 할 때 | 지원 대상 config 버전이 boot 에 실패하면 release 를 MUST 차단 | compatibility report | active |
FE-GATE-015 |
fe.gate.release-coherence |
1 | gate | feature-frontend-release-cache-rollback-contract |
HTML·asset·config 를 한 release 로 묶을 때 | 혼재된 release 조합이 감지되지 않으면 release 를 MUST 차단 | release verification | active |
FE-GATE-016 |
fe.gate.rollback-drill |
1 | gate | feature-frontend-release-cache-rollback-contract |
직전 release 로 되돌릴 때 | rollback 과 smoke 증거가 없으면 production promotion 을 MUST 차단 | drill record | active |
FE-GATE-017 |
fe.gate.diagram-review |
1 | gate | ca-skeleton-frontend-operational-contract |
hub 소유 아키텍처 다이어그램을 갱신할 때 | scoped 다이어그램 2종이 reviewer threshold 미달이면 documentation readiness 를 MUST 차단 | reviewer report | active |
FE-GATE-018 |
fe.gate.field-web-vitals |
1 | gate | feature-web-vitals-performance-budget-contract |
field 측정 창을 마감해 보고할 때 | p75 목표 미달이거나 표본 임계가 미해결이면 field readiness 를 MUST 차단 | field Web Vitals report | active |
FE-GATE-019 |
fe.gate.hosting-header |
2 | gate | feature-frontend-release-cache-rollback-contract |
hosting 의 header(cache·security) 설정을 배포할 때 | 선언한 Cache-Control·content-type·security header 와 실제 응답이 다르면 release 를 MUST 차단 | hosting header report | active |
FE-GATE-020 |
fe.gate.sample-removal |
1 | gate | feature-sample-feature-slice-contract-fixture |
sample slice 를 제거하거나 제품이 참조할 때 | sample 제거 후 build·smoke 가 실패하면 merge·release 를 MUST 차단 | sample-removal report | active |
FE-GATE-021 |
fe.gate.runbook-boot-config |
1 | gate | feature-frontend-operational-runbook-contract |
boot config 실패 drill 을 돌릴 때 | FE-RB-001 의 containment·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 |
FE-RB-001 record |
active |
FE-GATE-022 |
fe.gate.runbook-chunk-mismatch |
1 | gate | feature-frontend-operational-runbook-contract |
chunk·release manifest 실패 drill 을 돌릴 때 | FE-RB-002 의 containment·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 |
FE-RB-002 record |
active |
FE-GATE-023 |
fe.gate.runbook-api-degradation |
1 | gate | feature-frontend-operational-runbook-contract |
API degradation drill 을 돌릴 때 | FE-RB-003 의 containment·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 |
FE-RB-003 record |
active |
FE-GATE-024 |
fe.gate.runbook-telemetry |
1 | gate | feature-frontend-operational-runbook-contract |
telemetry degradation drill 을 돌릴 때 | FE-RB-004 의 containment·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 |
FE-RB-004 record |
active |
FE-GATE-025 |
fe.gate.runbook-release-rollback |
1 | gate | feature-frontend-operational-runbook-contract |
release 차단 결함으로 rollback 을 판단할 때 | FE-RB-005 의 rollback 결정·escalation·recovery 단언이 실패하면 production promotion 을 MUST 차단 |
FE-RB-005 record |
active |
FE-GATE-026 |
fe.gate.lab-performance |
1 | gate | feature-web-vitals-performance-budget-contract |
lab 성능을 측정해 보고할 때 | lab threshold 미달이거나 재현 메타데이터가 없으면 release 를 MUST 차단 | lab performance report | active |
FE-GATE-027 |
fe.gate.binary-file-io |
1 | gate | feature-frontend-binary-file-io-store-contract |
파일 I-O 또는 로컬 바이너리 저장 코드를 변경할 때 | picker·다운로드·quota·object URL 해제 fixture 가 실패하면 merge 를 MUST 차단 | binary I-O report | active |
FE-GATE-028 |
fe.gate.cache-tier-cross-tab |
1 | gate | feature-frontend-cache-tier-cross-tab-invalidation-contract |
캐시 영속화나 탭 간 전파를 변경할 때 | version 파티션·탭 간 무효화 fixture 가 실패하면 merge 를 MUST 차단 | cache tier report | active |
FE-GATE-029 |
fe.gate.large-object-transfer |
1 | gate | feature-frontend-large-object-transfer-contract |
대용량 전송 경로를 변경할 때 | presign 만료·part 재시도·무결성·credential 경계 fixture 가 실패하면 merge·release 를 MUST 차단 | transfer report | active |
FE-GATE-030 |
fe.gate.multi-protocol-transport |
1 | gate | feature-frontend-multi-protocol-api-transport-contract |
protocol adapter 나 codec 을 변경할 때 | protocol 별 성공/실패 정규화 fixture 가 실패하면 merge 를 MUST 차단 | protocol mapping report | active |
FE-GATE-031 |
fe.gate.realtime-lifecycle |
1 | gate | feature-frontend-realtime-subscription-lifecycle-contract |
실시간 연결·구독 코드를 변경할 때 | backoff·resume·구독 해제·이벤트 검증 fixture 가 실패하면 merge·release 를 MUST 차단 | realtime lifecycle report | active |
FE-GATE-032 |
fe.gate.background-execution |
1 | gate | feature-frontend-background-execution-worker-contract |
worker·service worker·background sync 를 변경할 때 | SW update UX·sync idempotency·worker timeout fixture 가 실패하면 merge·release 를 MUST 차단 | background execution report | active |
FE-GATE-033 |
fe.gate.capability-default-off |
1 | gate | feature-frontend-env-runtime-config-contract |
capability flag 나 adapter 등록을 변경할 때 | 기본 config build 에 비활성 capability 의 adapter 가 포함되면 merge·release 를 MUST 차단 | capability bundle report | active |
2.1.3 Artifact Registry (typed)
두 개 이상의 branch 가 같은 파일의 필드를 각자 정하고 있던 artifact 만 등록한다. 단일 branch 전용 artifact 는 desync 원인이 아니므로 넣지 않는다.
Schema Ref는 실제 JSON Schema 파일이며 검사기가 존재를 확인한다. 필드 추가·rename 은Schema Owner단독 결정이고, 소비 branch 는 본문에 스키마를 옮겨 적지 않고 frontmatterimports에ART-FE-0NN@1로 pin 한다. JSON artifact 필드 명명은 camelCase 로 통일한다 —artifacts/**의 report 파일에 한하며, telemetry attribute 어휘(§11.1 allowlist, snake_case)는 별개 규약이다.
| Artifact ID | Revision | Name | Schema Owner | Producer | Consumers | Schema Ref | Status |
|---|---|---|---|---|---|---|---|
ART-FE-001 |
1 | build manifest | feature-frontend-project-bootstrap-toolchain-contract |
feature-frontend-project-bootstrap-toolchain-contract |
feature-frontend-build-bundle-supply-chain-contract, feature-frontend-release-cache-rollback-contract, feature-frontend-test-taxonomy-contract |
harness/source/artifact-schemas/ca-skeleton-frontend/build-manifest.schema.json |
active |
ART-FE-002 |
1 | bundle report | feature-frontend-build-bundle-supply-chain-contract |
feature-frontend-build-bundle-supply-chain-contract |
feature-web-vitals-performance-budget-contract, feature-frontend-test-taxonomy-contract |
harness/source/artifact-schemas/ca-skeleton-frontend/bundle-report.schema.json |
active |
ART-FE-003 |
1 | release verification | feature-frontend-release-cache-rollback-contract |
feature-frontend-release-cache-rollback-contract |
feature-frontend-contract-compatibility-governance |
harness/source/artifact-schemas/ca-skeleton-frontend/release-verification.schema.json |
active |
ART-FE-004 |
1 | a11y report | feature-accessibility-baseline-contract |
feature-accessibility-baseline-contract |
feature-frontend-test-taxonomy-contract |
harness/source/artifact-schemas/ca-skeleton-frontend/a11y-report.schema.json |
active |
2.1.4 Flow Stage Registry (typed)
§7.3 응답 처리 순서 8단계에 단계별 owner 를 붙인 것이다. 순서 자체는 §7.3 이 계속 소유하고, 이 표는 각 단계를 누가 소유하며 그 단계가 지켜야 할 불변식이 무엇인가 를 고정한다. 이 표가 없을 때 stage 4
6 의 throw/non-throw 경계와 stage 7 산출물(model vs view-model)이 branch 마다 다르게 적혀 있었다. 단계 계약을 바꾸려면 owner 가 revision 을 올리고, 인접 단계 branch 는 pin 이 낡아4단계에서 같은 runtime schema owner 를 공유하지만 순서를 합치지 않는다 — 스트림에는 요청이 없고 응답에는 재개 커서가 없다. 구독 해제(cleanup)는 어느 흐름도 소유하지 않고STALE_IMPORTED_CONTRACT로 잡힌다.FLOW-FE-RESP-*는 요청/응답 한 번의 여정이고FLOW-FE-EVENT-*는 인바운드 프레임 하나의 여정이다. 두 흐름은 3RealtimeSubscriptionPort계약이 소유한다.
| Stage ID | Order | Owner | Input | Action | Output | Invariants | Revision |
|---|---|---|---|---|---|---|---|
FLOW-FE-RESP-001 |
1 | feature-api-client-response-envelope-contract |
HTTP 요청 | transport 완료 대기 | raw Response | timeout·abort 는 이 단계가 소유하고 이후 단계로 예외를 넘기지 않는다 | 1 |
FLOW-FE-RESP-002 |
2 | feature-api-client-response-envelope-contract |
raw Response | content-type 기대값 검사 | 본문 판독 가능 Response | 기대와 다르면 본문을 파싱하지 않고 실패로 전환 | 1 |
FLOW-FE-RESP-003 |
3 | feature-api-client-response-envelope-contract |
본문 판독 가능 Response | JSON parse | unvalidated JSON | parse 실패는 raw body 를 버리고 실패로 전환 | 1 |
FLOW-FE-RESP-004 |
4 | feature-runtime-schema-validation-contract |
unvalidated JSON | envelope 공유 스키마 검증 | discriminated envelope | 경계 검증은 .safeParse() non-throwing — throw 를 상위로 누출하지 않는다 |
1 |
FLOW-FE-RESP-005 |
5 | feature-runtime-schema-validation-contract |
discriminated envelope | success/failure 분기 검증 | 분기 확정 envelope | 200 이어도 envelope 이 invalid 하면 success 로 반환하지 않는다 | 1 |
FLOW-FE-RESP-006 |
6 | feature-runtime-schema-validation-contract |
분기 확정 envelope | payload per-operation 스키마 검증 | 검증된 payload(deep clone) | payload invalid 는 SCHEMA_MISMATCH; mapper 는 검증 통과분만 받는다 |
1 |
FLOW-FE-RESP-007 |
7 | feature-boundary-mapper-viewmodel-contract |
검증된 payload | DTO → application model 매핑 | application model | 이 단계 산출물은 model 이고 view-model 이 아니다 — view-model 투영은 application/view-models/ 소유(§4.2·§4.4 2-stage) |
1 |
FLOW-FE-RESP-008 |
8 | feature-frontend-error-classification-boundary-contract |
application model 또는 실패 신호 | 정규화된 결과 반환 | application result 또는 normalized failure | 총함수 — 미매핑 예외는 UNKNOWN_FAILURE 로 귀결하고 throw 를 presentation 으로 통과시키지 않는다 |
1 |
FLOW-FE-EVENT-001 |
1 | feature-frontend-realtime-subscription-lifecycle-contract |
열린 연결 | 프레임 수신 대기 | raw frame | 연결 오류는 이 단계가 소유하고 이후 단계로 예외를 넘기지 않는다 | 1 |
FLOW-FE-EVENT-002 |
2 | feature-frontend-realtime-subscription-lifecycle-contract |
raw frame | transport decode (SSE 필드 / WebSocket frame / poll 응답 본문) | unvalidated event JSON | decode 실패는 프레임을 버리고 실패로 전환하며 연결을 즉시 끊지 않는다 | 1 |
FLOW-FE-EVENT-003 |
3 | feature-runtime-schema-validation-contract |
unvalidated event JSON | event envelope 공유 스키마 검증 | discriminated event envelope | 경계 검증은 non-throwing 이며 throw 를 상위로 누출하지 않는다 | 1 |
FLOW-FE-EVENT-004 |
4 | feature-runtime-schema-validation-contract |
discriminated event envelope | eventSchema per-event 검증 |
검증된 event payload | 미검증 프레임은 EVENT_SCHEMA_MISMATCH 로 드롭하고 application 에 도달시키지 않는다 |
1 |
FLOW-FE-EVENT-005 |
5 | feature-frontend-error-classification-boundary-contract |
검증된 event payload 또는 실패 신호 | 정규화된 이벤트 또는 failure 반환 | application event 또는 normalized failure | 총함수 — 미매핑 예외는 UNKNOWN_FAILURE 로 귀결한다 |
1 |
2.1.2 Delegation Registry (typed)
한 branch 가 다른 branch 에 관심사를 넘길 때 여기에 행을 만든다.
Status가accepted가 되려면 delegate 쪽 문서가 frontmatteraccepts_delegations로 접수해야 한다. 접수 전에는proposed이고UNACCEPTED_DELEGATION으로 계속 잡힌다 — "A 가 넘겼는데 B 는 받은 적 없는" 공백이 조용히 남지 않게 하는 장치다.DELEG-FE-001DELEG-FE-006은 2026-07-20 문서 간 정합성 감사에서 미접수 위임으로 발견됐고, 이후 delegate 6곳이 모두accepts_delegations로 접수해 현재는 전부accepted다(2026-07-21 frontmatter 왕복 대조 6/6 일치,UNACCEPTED_DELEGATION0건).DELEG-FE-007DELEG-FE-011은 2026-07-28 runtime capability 확장에서 추가했다. 신규 6개 능력 도메인이 서로 또는 기존 branch 에 넘기는 관심사이며, delegate 5곳의accepts_delegations를 같은 변경에서 채워 접수까지 마쳤다. 즉 이 표는 지금 열려 있는 공백 목록이 아니라 닫힌 위임의 등록부다.
| Delegation ID | Concern Key | Revision | Delegator | Delegate | Scope | Status |
|---|---|---|---|---|---|---|
DELEG-FE-001 |
fe.deleg.dynamic-class-lint |
1 | feature-tailwind-design-token-styling-contract |
feature-frontend-browser-security-boundary-contract |
dynamic/untrusted class-string 구성 금지의 정적 lint 강제 | accepted |
DELEG-FE-002 |
fe.deleg.lint-toolchain-substrate |
1 | feature-frontend-architecture-enforcement-lint-contract |
feature-frontend-project-bootstrap-toolchain-contract |
eslint.config.js·.dependency-cruiser.cjs 설치와 base flat-config substrate |
accepted |
DELEG-FE-003 |
fe.deleg.composition-root-review |
1 | feature-frontend-architecture-enforcement-lint-contract |
feature-frontend-clean-architecture-layering-contract |
composition-root business-rule 혼입에 대한 코드리뷰 체크리스트 | accepted |
DELEG-FE-004 |
fe.deleg.color-contrast |
1 | feature-accessibility-baseline-contract |
feature-tailwind-design-token-styling-contract |
color contrast token 값 결정 | accepted |
DELEG-FE-005 |
fe.deleg.injectable-random |
1 | feature-api-client-response-envelope-contract |
feature-frontend-clean-architecture-layering-contract |
full-jitter backoff 를 결정론 테스트 가능하게 하는 random source 주입 형태 | accepted |
DELEG-FE-006 |
fe.deleg.reload-once-action |
1 | feature-async-ui-state-contract |
feature-frontend-render-recovery-boundary-contract |
reload-once action 의 실제 실행(5-condition guard 경유) |
accepted |
DELEG-FE-007 |
fe.deleg.sw-host-for-push |
1 | feature-frontend-realtime-subscription-lifecycle-contract |
feature-frontend-background-execution-worker-contract |
WebPush 가 요구하는 service worker 등록·수명주기 호스팅 | accepted |
DELEG-FE-008 |
fe.deleg.binary-handle-ownership |
1 | feature-frontend-large-object-transfer-contract |
feature-frontend-binary-file-io-store-contract |
전송 대상 File/Blob handle 과 object URL 수명 소유 |
accepted |
DELEG-FE-009 |
fe.deleg.persistent-cache-key |
1 | feature-frontend-cache-tier-cross-tab-invalidation-contract |
feature-frontend-storage-registry-contract |
영속 캐시의 physical key·namespace·classification·quota fallback 소유 | accepted |
DELEG-FE-010 |
fe.deleg.decoded-payload-validation |
1 | feature-frontend-multi-protocol-api-transport-contract |
feature-runtime-schema-validation-contract |
codec 디코드 이후 payload 의 runtime schema 검증 | accepted |
DELEG-FE-011 |
fe.deleg.sw-release-coherence |
1 | feature-frontend-background-execution-worker-contract |
feature-frontend-release-cache-rollback-contract |
service worker 버전과 release·rollback coherence 판정 | accepted |
2.2 Universal acceptance questions
각 FE-OC-* owner branch는 완료 전에 다음 질문에 답해야 한다.
- 이 contract가 막는 concrete failure는 무엇인가?
- input과 output은 무엇인가?
- project-wide default와 limit은 무엇인가?
- 허용되는 예외와 승인 owner는 누구인가?
- 금지 구현은 무엇인가?
- failure가 어떤 normalized error와 UX로 나타나는가?
- 어떤 telemetry가 남고 어떤 data가 redacted되는가?
- 어떤 test가 위반 시 실패하는가?
- 어떤 evidence artifact가 생성되는가?
- release 또는 rollback에 미치는 영향은 무엇인가?
하나라도 비어 있으면 branch는 documented-only를 넘을 수 없다.
3. Stable Decision Register
Legacy reference (v1). 기존
FE-D*식별자와 세부 rationale은 이력·설명용으로 보존한다. project-wide 결정의 현재 owner와 branch 상속 기준은 아래## 6.1 Project Decision Registry / 안정 결정 레지스트리다.
3.1 Decision status
| status | 의미 |
|---|---|
conditional-default |
현재 project default지만 trigger가 오면 재검토 |
accepted-documented-only |
문서상 채택, 코드 evidence 없음 |
deferred |
owner와 trigger만 있고 선택 미확정 |
superseded |
후속 FE-D row로 대체, 삭제 금지 |
3.2 Decision rows
FE-D*는 v1 결정 레지스터다. project-wide 결정의 현재 owner 는 §6.1 Project Decision Registry(DEC-...)이며 이 표는 이력·설명용으로 보존한다.Affected FE-OC열은 결정과 계약의 대응 관계이지 계약 내용의 사본이 아니다.
| Decision ID | Decision | Status | Owner | Affected FE-OC | Evidence / rationale | Revisit trigger | Supersedes |
|---|---|---|---|---|---|---|---|
FE-D001 |
package manager default는 pnpm; packageManager field와 pnpm-lock.yaml을 commit |
conditional-default |
feature-frontend-project-bootstrap-toolchain-contract |
FE-OC-003, FE-OC-020 |
project-local reproducibility default, 외부 source claim 아님 | 조직 표준이 npm/yarn/Bun을 강제하거나 target CI가 pnpm을 지원하지 않음 | — |
FE-D002 |
source는 JavaScript ESM, typecheck-equivalent는 tsc --allowJs --checkJs --noEmit |
accepted-documented-only |
feature-frontend-project-bootstrap-toolchain-contract |
FE-OC-003, FE-OC-007, FE-OC-020 |
사용자 제약 + runtime schema 필요성 | TypeScript strict 전환 승인 | — |
FE-D003 |
Vite client-only SPA를 build baseline으로 사용 | accepted-documented-only |
feature-frontend-project-bootstrap-toolchain-contract |
FE-OC-003, FE-OC-016, FE-OC-021 |
raw/official-docs/vite-build-tool-official VITE-C2 |
SSR/SEO/edge rendering이 product requirement가 됨 | — |
FE-D004 |
UI composition은 React를 사용 | accepted-documented-only |
feature-async-ui-state-contract |
FE-OC-002, FE-OC-011, FE-OC-015 |
raw/official-docs/react-ui-library-official REACT-UI-C1 |
native/custom-element 또는 다른 framework로 project fork | — |
FE-D005 |
styling default는 Tailwind theme token + component primitive | conditional-default |
feature-tailwind-design-token-styling-contract |
FE-OC-011, FE-OC-019, FE-OC-021 |
raw/official-docs/tailwind-css-utility-first-official TAILWIND-UTIL-C1, TAILWIND-UTIL-C2, TAILWIND-UTIL-C4 |
runtime theming 또는 product design system이 다른 compiler를 요구 | — |
FE-D006 |
server state policy는 application-owned QueryCachePort가 정의하고 TanStack Query adapter가 구현하며 client store에 복제하지 않음 |
accepted-documented-only |
feature-server-state-caching-contract |
FE-OC-011, FE-OC-012 |
raw/official-docs/tanstack-query-server-state-official TSQ-C1, TSQ-C3, TSQ-C5; port ownership·non-duplication은 project decision |
offline-first normalized entity cache가 필요 | — |
FE-D007 |
boundary runtime validation은 Zod schema로 수행 | accepted-documented-only |
feature-runtime-schema-validation-contract |
FE-OC-007, FE-OC-008 |
raw/official-docs/zod-runtime-schema-validation-official ZOD-VALID-C2, ZOD-VALID-C3, ZOD-VALID-C4 |
bundle budget 또는 generated schema pipeline이 대체안을 요구 | — |
FE-D008 |
routing은 React Router Declarative Mode를 default로 사용 | conditional-default |
feature-routing-navigation-guard-contract |
FE-OC-005, FE-OC-015 |
raw/official-docs/react-router-official REACT-ROUTER-C1, REACT-ROUTER-C4 |
data router/framework mode가 loader·SSR requirement로 필요 | — |
FE-D009 |
domain, application, presentation, adapters, bootstrap responsibility를 분리 |
accepted-documented-only |
feature-frontend-clean-architecture-layering-contract |
FE-OC-002 |
raw/project-notes/ca-skeleton-operational-contract의 운영 계약 철학을 frontend에 적용 | sample slice가 불필요한 ceremony를 증명하거나 FSD fork 승인 | — |
FE-D010 |
output port interface는 application이 소유하고 adapter가 구현 |
accepted-documented-only |
feature-frontend-clean-architecture-layering-contract |
FE-OC-002 |
dependency inversion의 project decision | port가 domain invariant 자체를 표현해야 하는 concrete case 발생 | — |
FE-D011 |
composition root는 bootstrap 하나이며 concrete adapter를 application에 주입 |
accepted-documented-only |
feature-frontend-clean-architecture-layering-contract |
FE-OC-002, FE-OC-004 |
owner ambiguity 제거 | framework DI container 도입 | — |
FE-D012 |
deploy별 public value는 pre-render runtime config, compiler value는 build-time config로 분리 | conditional-default |
feature-frontend-env-runtime-config-contract |
FE-OC-004, FE-OC-016, FE-OC-023 |
environment-specific rebuild 감소; project inference | hosting이 runtime config atomic publish를 지원하지 않음 | — |
FE-D013 |
runtime config fallback은 environment별 rebuild를 허용하되 한 artifact를 여러 env에 재사용하지 않음 | conditional-default |
feature-frontend-env-runtime-config-contract |
FE-OC-004, FE-OC-016, FE-OC-023 |
fallback의 deploy ambiguity 제한 | runtime config endpoint 도입 | — |
FE-D014 |
default request timeout은 total 10s; 별도 connect timeout은 browser API가 직접 제공하지 않으므로 주장하지 않음 | conditional-default |
feature-api-client-response-envelope-contract |
FE-OC-006, FE-OC-009, FE-OC-021 |
project-local initial limit | measured p95가 10s를 정당하게 초과하거나 streaming 도입 | — |
FE-D015 |
retry는 initial call 이후 최대 2회, exponential backoff + full jitter, cap 2s | conditional-default |
feature-api-client-response-envelope-contract |
FE-OC-009, FE-OC-021 |
retry storm 억제를 위한 project default | backend SLO·rate limit contract 확정 | — |
FE-D016 |
mutation 자동 retry는 stable idempotency key와 backend replay contract가 있을 때만 허용 | accepted-documented-only |
feature-api-client-response-envelope-contract |
FE-OC-009, FE-OC-023 |
duplicate write 방지 invariant | mutation이 naturally idempotent임이 schema로 증명 | — |
FE-D017 |
auth lifecycle은 외부 owner, skeleton은 AuthSessionPort만 소비 |
accepted-documented-only |
feature-frontend-auth-session-integration-contract |
FE-OC-010 |
raw/project-notes/keycloak-patterns-overview | skeleton이 독립 auth product로 scope 변경 | — |
FE-D018 |
route/API-operation/env/storage/error/query/telemetry/release/capability token은 9개 registry로 관리 | accepted-documented-only |
feature-frontend-contract-registry-governance |
FE-OC-013, FE-OC-022 |
rename·compatibility 영향 추적 | code generation SSOT 채택 | — |
FE-D019 |
service worker와 offline asset cache는 default off | superseded |
feature-frontend-release-cache-rollback-contract |
FE-OC-016, FE-OC-017, FE-OC-023 |
stale asset·config mismatch surface 축소 | FE-D034가 2026-07-28에 대체 — SW 역할을 precaching과 push/sync 호스트로 분리 |
— |
FE-D020 |
hashed asset은 immutable, HTML·runtime config·release manifest는 revalidate/no-store 정책 분리 | accepted-documented-only |
feature-frontend-release-cache-rollback-contract |
FE-OC-016, FE-OC-017 |
release coherence invariant | hosting cache primitive 제약 | — |
FE-D021 |
telemetry는 best-effort queue + redaction, sink failure는 UI를 실패시키지 않음 | accepted-documented-only |
feature-frontend-observability-logging-trace-contract |
FE-OC-014 |
operational isolation | regulated audit event처럼 delivery guarantee가 필요한 별도 channel 도입 | — |
FE-D022 |
test stack default는 Vitest + RTL + MSW + Playwright + axe | conditional-default |
feature-frontend-test-taxonomy-contract |
FE-OC-020 |
Vite/browser/component/e2e responsibility 분리 | organization test platform이 대체 | — |
FE-D023 |
static release는 immutable release directory + atomic active pointer로 배포 | conditional-default |
feature-frontend-release-cache-rollback-contract |
FE-OC-016, FE-OC-017, FE-OC-025 |
rollback 가능 artifact requirement | provider가 다른 atomic primitive만 제공 | — |
FE-D024 |
dependency lock, secret scan, vulnerability scan, license inventory, dependency review를 merge/release gate로 분리 (lock 은 FE-GATE-001, 나머지 4개는 FE-GATE-013) |
accepted-documented-only |
feature-frontend-build-bundle-supply-chain-contract |
FE-OC-018, FE-OC-019, FE-OC-020 |
supply-chain scope 최소값 | organization security policy가 더 강한 gate 지정 | — |
FE-D025 |
sample slice는 제거 가능한 contract fixture이며 product import를 금지 | accepted-documented-only |
feature-sample-feature-slice-contract-fixture |
FE-OC-024 |
backend skeleton의 sample-fixture 운영 원칙을 frontend에 적용 | fixture 없이 동일 gate coverage를 증명 | — |
FE-D026 |
신규 runtime capability 6종은 FE-REG-CAPABILITY flag로 default OFF이며 활성화는 owner·gate·runbook을 동반한다 |
conditional-default |
feature-frontend-env-runtime-config-contract |
FE-OC-004, FE-OC-022, FE-OC-027, FE-OC-028, FE-OC-029, FE-OC-030, FE-OC-031, FE-OC-032 |
project-local default, 외부 source claim 아님 | 특정 capability가 제품 필수가 되어 상시 활성이 요구됨 | — |
FE-D027 |
로컬 바이너리 backend는 IndexedDB를 default로 하고 OPFS는 대용량 순차 write에 opt-in, Cache Storage는 service worker 호스팅 response cache 전용이다 | conditional-default |
feature-frontend-binary-file-io-store-contract |
FE-OC-013, FE-OC-027 |
project-local default, 외부 source claim 아님 | OPFS 브라우저 지원 또는 quota 정책이 바뀜 | — |
FE-D028 |
탭 간 무효화는 BroadcastChannel 우선에 storage event fallback을 쓰고 leader election 없이 무효화 key만 전파한다 |
conditional-default |
feature-frontend-cache-tier-cross-tab-invalidation-contract |
FE-OC-012, FE-OC-028 |
project-local default, 외부 source claim 아님; 값 전파는 PII·stale 표면을 넓힘 | 다중 탭 실시간 협업이 제품 요구가 됨 | — |
FE-D029 |
presigned URL 획득은 shared client를 경유하고 실제 byte 전송은 session credential을 첨부하지 않는 transfer adapter가 수행한다 | accepted-documented-only |
feature-frontend-large-object-transfer-contract |
FE-OC-006, FE-OC-019, FE-OC-029 |
credential 유출 방지 invariant, project decision | 스토리지가 same-origin proxy만 제공 | — |
FE-D030 |
재개 가능 전송은 part size·병렬도·part 재시도 상한을 registry로 고정하고 part 상태를 BlobStorePort에 보존한다 |
conditional-default |
feature-frontend-large-object-transfer-contract |
FE-OC-029 |
project-local default, 외부 source claim 아님 | 스토리지 제공자가 다른 multipart 제약을 요구 | — |
FE-D031 |
transport default는 REST이고 GraphQL·gRPC-Web·Connect-Web은 FE-REG-API의 protocol 필드로 opt-in하며 미지원 환경은 REST gateway로 fallback한다 |
conditional-default |
feature-frontend-multi-protocol-api-transport-contract |
FE-OC-006, FE-OC-007, FE-OC-030 |
project-local default, 외부 source claim 아님 | backend가 단일 비-REST protocol만 제공 | — |
FE-D032 |
실시간 transport는 SSE를 우선하고 양방향이 필요하면 WebSocket, 둘 다 불가할 때만 최소 간격·backoff·visibility gating을 갖춘 bounded polling을 쓴다 | conditional-default |
feature-frontend-realtime-subscription-lifecycle-contract |
FE-OC-031 |
project-local default, 외부 source claim 아님; polling은 마지막 수단 | backend가 SSE를 제공하지 않거나 양방향이 기본 요구가 됨 | — |
FE-D033 |
실시간 연결은 full jitter backoff와 30초 cap을 쓰고 재시도 상한 후 terminal 상태로 전이하며 resume은 Last-Event-ID 또는 cursor로 수행하고 unmount 시 구독을 해제한다 |
conditional-default |
feature-frontend-realtime-subscription-lifecycle-contract |
FE-OC-011, FE-OC-031 |
재연결 폭주·구독 누수 억제, project decision | backend가 서버 주도 재연결 정책을 계약으로 제공 | — |
FE-D034 |
service worker는 역할을 분리해 release asset precaching은 default off로 유지하고 push·background sync·Cache Storage 호스트 역할만 capability opt-in으로 허용하며 update UX 계약을 요구한다 | conditional-default |
feature-frontend-background-execution-worker-contract |
FE-OC-016, FE-OC-017, FE-OC-023, FE-OC-032 |
precaching은 release coherence 훼손 원인이나 push·sync는 SW 없이는 불가; project decision | offline-first가 제품 요구가 되고 update UX가 설계됨 | FE-D019 |
FE-D035 |
background sync 재생은 idempotency: keyed operation만 허용한다 |
accepted-documented-only |
feature-frontend-background-execution-worker-contract |
FE-OC-009, FE-OC-032 |
FE-D016의 중복 write 방지 invariant를 지연 재생에 확장 |
mutation이 naturally idempotent임이 schema로 증명됨 | — |
FE-D036 |
Web Worker 작업은 structured-clone 또는 Transferable로만 통신하고 timeout과 terminate를 계약하며 worker 안에서 application port를 재구현하지 않는다 | accepted-documented-only |
feature-frontend-background-execution-worker-contract |
FE-OC-002, FE-OC-032 |
worker 안 로직 중복이 layer 경계를 우회하는 것을 차단, project decision | SharedArrayBuffer 기반 병렬 처리가 요구됨 | — |
FE-D026~FE-D036의 Evidence / rationale에 적힌 project-local default, 외부 source claim 아님은 FE-D001이 쓰는 표기와 같다. 대응 raw 근거 문서가 아직 없다는 사실을 감추지 않고 명시하는 장치이며, 수집 계획은 FE-Q-011이 소유한다.
3.3 Decision change protocol
- 변경 제안자는 새
FE-D*를 만들지, 기존 row의 compatible clarification인지 분류한다. - owner는 영향을 받는
FE-OC-*와 registry row를 나열한다. compatibility_impact를none,additive,behavior-change,breaking중 하나로 기록한다.behavior-change와breaking은 migration·rollback·test evidence 없이 merge하지 않는다.- 기존 의미를 대체하면 기존 row를
superseded로 바꾸고Supersedeschain을 연결한다. - source link가 추가되면 실제 raw 파일만 사용한다. placeholder wikilink를 만들지 않는다.
- implementation repository가 생기면 commit·path·test artifact를 evidence ledger에 추가한다.
- hub와 owner branch가 모순되면 project-wide default를 바꾸기 전 이 register를 먼저 갱신한다.
6.1 안정 결정 레지스트리
Project contract v2의 project-wide decision SSOT. 기존
FE-D*는 아래 stable ID로 일대일 이관되며 branch는DEC-...@1만 pin한다.
| Decision ID | Revision | Domain | Decision Summary | Status | Owner | Evidence |
|---|---|---|---|---|---|---|
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TOOLCHAIN-001 |
1 | toolchain |
package manager default는 pnpm이며 packageManager field와 pnpm-lock.yaml을 commit한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D001 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-LANGUAGE-001 |
1 | language |
JavaScript ESM과 tsc allowJs/checkJs/noEmit을 typecheck-equivalent baseline으로 사용한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D002 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BUILD-001 |
1 | build |
Vite client-only SPA를 build baseline으로 사용한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D003; raw/official-docs/vite-build-tool-official VITE-C2 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-UI-001 |
1 | ui |
UI composition은 React를 사용한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D004; raw/official-docs/react-ui-library-official REACT-UI-C1 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-STYLING-001 |
1 | styling |
styling default는 Tailwind theme token과 component primitive다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D005; raw/official-docs/tailwind-css-utility-first-official |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SERVER-STATE-001 |
1 | server-state |
application-owned QueryCachePort와 TanStack Query adapter를 사용하고 client store에 server state를 복제하지 않는다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D006; raw/official-docs/tanstack-query-server-state-official |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001 |
1 | validation |
boundary runtime validation은 Zod schema로 수행한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D007; raw/official-docs/zod-runtime-schema-validation-official |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ROUTING-001 |
1 | routing |
routing default는 React Router Declarative Mode다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D008; raw/official-docs/react-router-official |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001 |
1 | architecture |
domain, application, presentation, adapters, bootstrap 책임을 분리한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D009 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PORT-OWNERSHIP-001 |
1 | port-ownership |
output port interface는 application이 소유하고 adapter가 구현한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D010 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-COMPOSITION-ROOT-001 |
1 | composition-root |
bootstrap을 단일 composition root로 두고 concrete adapter를 application에 주입한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D011 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RUNTIME-CONFIG-001 |
1 | runtime-config |
deploy별 public value는 runtime config, compiler value는 build-time config로 분리한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D012 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001 |
1 | config-fallback |
runtime config fallback 시 environment별 rebuild는 허용하되 artifact의 multi-environment 재사용은 금지한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D013 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TIMEOUT-001 |
1 | timeout |
request total timeout default는 10초이며 별도 browser connect timeout은 주장하지 않는다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D014 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RETRY-001 |
1 | retry |
retry는 initial call 이후 최대 2회, exponential backoff와 full jitter, 2초 cap을 사용한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D015 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-IDEMPOTENCY-001 |
1 | idempotency |
mutation auto-retry는 stable idempotency key와 backend replay contract가 있을 때만 허용한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D016 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-AUTH-BOUNDARY-001 |
1 | auth-boundary |
auth lifecycle은 외부 owner가 소유하고 skeleton은 AuthSessionPort만 소비한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D017; raw/project-notes/keycloak-patterns-overview |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001 |
1 | registry |
route, API operation, env, storage, error, query, telemetry, release token, capability를 9개 registry로 관리한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D018 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-OFFLINE-CACHE-001 |
2 | offline-cache |
service worker의 release asset precaching은 default off이고 push·background sync·Cache Storage 호스트 역할만 capability opt-in으로 허용한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D034 (FE-D019 supersede) |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CACHE-POLICY-001 |
1 | cache-policy |
hashed asset은 immutable, HTML·runtime config·release manifest는 revalidate/no-store로 분리한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D020 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TELEMETRY-001 |
1 | telemetry |
telemetry는 best-effort queue와 redaction을 사용하며 sink failure가 UI를 실패시키지 않는다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D021 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001 |
1 | test-stack |
test stack default는 Vitest, RTL, MSW, Playwright, axe다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D022 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001 |
1 | deployment |
static release는 immutable release directory와 atomic active pointer로 배포한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D023 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001 |
1 | supply-chain |
dependency lock, secret scan, vulnerability scan, license inventory, dependency review를 merge/release gate로 분리한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D024 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SAMPLE-FIXTURE-001 |
1 | sample-fixture |
sample slice는 제거 가능한 contract fixture이며 product import를 금지한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D025 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001 |
1 | capability |
신규 runtime capability 6종은 FE-REG-CAPABILITY flag로 default OFF이며 활성화는 owner·gate·runbook을 동반한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D026 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BINARY-STORE-001 |
1 | binary-store |
로컬 바이너리 backend는 IndexedDB를 default로 하고 OPFS는 대용량 순차 write에 opt-in, Cache Storage는 service worker 호스팅 response cache 전용이다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D027 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CROSS-TAB-001 |
1 | cross-tab |
탭 간 무효화는 BroadcastChannel 우선에 storage event fallback을 쓰고 leader election 없이 무효화 key만 전파한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D028 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TRANSFER-CREDENTIAL-001 |
1 | transfer-credential |
presigned URL 획득은 shared client를 경유하고 실제 byte 전송은 session credential을 첨부하지 않는 transfer adapter가 수행한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D029 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RESUMABLE-TRANSFER-001 |
1 | resumable-transfer |
재개 가능 전송은 part size·병렬도·part 재시도 상한을 registry로 고정하고 part 상태를 BlobStorePort에 보존한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D030 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PROTOCOL-001 |
1 | protocol |
transport default는 REST이고 GraphQL·gRPC-Web·Connect-Web은 FE-REG-API의 protocol 필드로 opt-in하며 미지원 환경은 REST gateway로 fallback한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D031 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REALTIME-TRANSPORT-001 |
1 | realtime-transport |
실시간 transport는 SSE를 우선하고 양방향이 필요하면 WebSocket, 둘 다 불가할 때만 최소 간격·backoff·visibility gating을 갖춘 bounded polling을 쓴다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D032 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REALTIME-LIFECYCLE-001 |
1 | realtime-lifecycle |
실시간 연결은 full jitter backoff와 30초 cap을 쓰고 재시도 상한 후 terminal 상태로 전이하며 resume은 Last-Event-ID 또는 cursor로 수행하고 unmount 시 구독을 해제한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D033 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SERVICE-WORKER-ROLE-001 |
1 | service-worker-role |
service worker는 역할을 분리해 release asset precaching은 default off로 유지하고 push·background sync·Cache Storage 호스트 역할만 capability opt-in으로 허용하며 update UX 계약을 요구한다 | conditional-default |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D034 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BACKGROUND-SYNC-001 |
1 | background-sync |
background sync 재생은 idempotency keyed operation만 허용한다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D035 |
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-WORKER-TASK-001 |
1 | worker-task |
Web Worker 작업은 structured-clone 또는 Transferable로만 통신하고 timeout과 terminate를 계약하며 worker 안에서 application port를 재구현하지 않는다 | accepted-documented-only |
raw/project-notes/ca-skeleton-frontend-operational-contract | §3.2 FE-D036 |
개정 기록 (§3.3 protocol)
- 2026-07-21 ·
DEC-...-SUPPLY-CHAIN-001·compatibility_impact: additive· revision 유지(1). Decision Summary 에dependency review를 추가했다. 이는 새 결정이 아니라 불완전한 요약의 정정이다 —FE-OC-018과 §13.1 이 처음부터 dependency review 를 요구했고 §3.2FE-D024도 이를 포함하는데 이 registry 행만 4개 control 로 적혀 있었다. 기존 4개 control 의 동작은 바뀌지 않고, gate 정의(§15.1FE-GATE-013)도 이미 dependency-review fixture 를 포함한 채 revision 1 이므로 같은 판정을 적용한다.- 2026-07-28 ·
DEC-...-OFFLINE-CACHE-001·compatibility_impact: behavior-change· revision 1→2.FE-D034가FE-D019를 supersede 하면서 service worker 를 "전면 off" 에서 "precaching off + 역할별 capability opt-in" 으로 바꿨다. WebPush·Background Sync·Cache Storage 가 service worker 없이는 동작하지 않기 때문이다. behavior-change 이므로 §3.3 4단계에 따라FE-GATE-032(SW update UX + rollback 시 SW 되돌림)와FE-RB-007이 migration·rollback evidence 를 담당한다. 이 결정을 pin 한 raw/branch-notes/feature-frontend-release-cache-rollback-contract 는@2로 갱신했다.- 2026-07-28 ·
DEC-...-REGISTRY-001·compatibility_impact: additive· revision 유지(1). 9번째 registryFE-REG-CAPABILITY를 추가했다. 기존 8개 registry 의 owner·schema·동작은 바뀌지 않으므로DEC-...-SUPPLY-CHAIN-001선례와 같은 판정을 적용한다. 다만 Summary 문자열이 바뀌므로 이를 복사해 둔 소비 branch 4곳(raw/branch-notes/feature-frontend-storage-registry-contract·raw/branch-notes/feature-frontend-observability-logging-trace-contract·raw/branch-notes/feature-frontend-contract-registry-governance·raw/branch-notes/feature-frontend-contract-compatibility-governance)의 상속 표를 함께 갱신했다.- 2026-07-28 ·
DEC-...-CAPABILITY-001외 10건 신규 등록. 근거 raw 문서가 아직 없으므로 §3.2 대응 행의Evidence / rationale에project-local default, 외부 source claim 아님을 명시했고, 수집 계획은FE-Q-011이 소유한다.- Summary 셀은 소비 branch 의 상속 표와 문자열이 정확히 일치해야 한다(
wiki_consistency_check.py의CONFLICTS_WITH_PROJECT_DECISION). 분류·근거 같은 메타는 이 기록에 적고 Summary 에 섞지 않는다. 조사 앞에 공백을 넣지 않는다 —…release token을 8개 registry로형태가 기준이다.
4. System Architecture Contract
4.1 Architecture diagrams
!raw/diagrams/ca-skeleton-frontend/architecture-overview-2026-07-18.drawio
!raw/diagrams/ca-skeleton-frontend/architecture-deployment-2026-07-18.drawio
두 파일은 wiki-diagram-reviewer의 rules/diagram-standards.md v2 심사에서 각각 100/100 PASS를 받았다. PASS scope는 overview의 Clean Architecture dependency ownership view와 deployment의 static asset·/config.json delivery slice다. §12 전체 release/rollback topology, 실제 구현 topology, hosting 상태는 이 review가 증명하지 않는다. 근거: docs/superpowers/specs/2026-07-18-ca-skeleton-frontend-operational-contract-review/diagram-review.md.
4.2 Component responsibility
| Component | Owns | Consumes | MUST NOT own | Evidence status |
|---|---|---|---|---|
domain |
framework-neutral model, value semantics, pure policy | standard JavaScript only | React, router, Query, fetch, storage, telemetry | planned |
application |
use case, input/output port, QueryCachePort policy, orchestration, view-model contract |
domain | concrete adapter, browser global, React component | planned |
presentation |
page/component, user event, view state rendering | application public API | raw API DTO, fetch, storage key, telemetry transport | planned |
adapters/http |
application output port implementation, envelope/schema/error mapping | application port, browser fetch | use-case policy, component rendering | planned |
adapters/storage |
storage port implementation, serialization, quota mapping | application port, Web Storage | token lifecycle, domain policy | planned |
adapters/telemetry |
telemetry port implementation, queue, redaction, sink | application port, browser transport | UX decision, navigation | planned |
adapters/query-cache |
application-owned QueryCachePort implementation, TanStack Query key/invalidation bridge |
application port, TanStack Query | use-case policy, page-local query key | planned |
adapters/capability |
capability flag 해석, 브라우저 feature detection, 비활성 사유 | application port, runtime config, browser globals | 활성화 여부의 제품 판단 | planned |
adapters/file |
파일 선택·저장 dialog, object URL 생성/해제 | application port, File System Access / input element | 파일 내용 해석, 도메인 검증 | planned |
adapters/blob-store |
IndexedDB·OPFS·Cache Storage 백엔드, quota 매핑, eviction | application port, browser storage API | 저장 대상의 의미, 도메인 정책 | planned |
adapters/cache-persistence |
캐시 직렬화, version partition, 복원 거부 | application port, 자체 영속 백엔드 | 캐시 정책 결정(QueryCachePort 소유) |
planned |
adapters/cross-tab |
BroadcastChannel·storage event 전송, 메시지 봉투 |
application port, browser globals | 무효화 대상 결정 | planned |
adapters/transfer |
part 분할·병렬·재시도·무결성·진행 보고, credential-less 전송 | application port, fetch, Streams | presign 발급, 업로드 대상 도메인 규칙 | planned |
adapters/protocol |
GraphQL·gRPC-Web·Connect-Web codec 과 status 정규화 | application output port, fetch | operation 정의, use-case policy | planned |
adapters/realtime |
연결 수명주기, 재연결 backoff, resume cursor, 프레임 디코드, 구독 해제 | application port, EventSource·WebSocket·fetch | 이벤트의 도메인 의미, 상태 병합 정책 | planned |
adapters/worker |
worker 생성·통신·timeout·terminate | application port, Worker API | 도메인 계산 규칙 | planned |
adapters/service-worker |
SW 등록·갱신 상태, background sync 큐 등록 | application port, ServiceWorker API | precache 정책 결정(FE-D034 소유), mutation 의미 |
planned |
bootstrap |
config load, capability 해석, adapter construction, dependency injection, React mount | all runtime modules | business rule, page-specific orchestration | planned |
4.3 Dependency matrix
화살표는 source import 방향이다.
| From | May import | MUST NOT import | Planned enforcement |
|---|---|---|---|
domain |
domain sibling modules | application, presentation, adapters, bootstrap, React, browser globals | dependency-cruiser + ESLint restricted imports |
application |
domain, application-owned ports/contracts | presentation, concrete adapters, bootstrap, React, window, localStorage, fetch |
architecture fixture |
presentation |
application facade, view-model types, shared UI primitive | adapters, raw DTO schema, registry storage implementation | restricted import rule |
adapters/* |
application-owned output ports, domain value contract if required | presentation, bootstrap internals, other adapter concrete implementation | dependency graph snapshot |
bootstrap |
presentation root, application factory, all selected adapters | page-specific business rule | composition-root review |
test fixtures |
public contracts, explicit test helpers, 그리고 테스트 대상 계층 + 선택된 test stack 패키지 (예시적) | production secret, real telemetry endpoint | test config guard |
test fixtures 행의 May import 열은 예시(illustrative)이고 MUST NOT 열이 규범(normative) 이다. 즉 tests/** 는 "production secret 모듈과 real telemetry endpoint 설정을 import 하지 않는다"는 forbidden-only 규칙으로 강제한다. allow-only 로 읽으면 FE-D022 가 의무화한 test stack(Vitest·RTL·MSW·Playwright·axe) 과 테스트 대상 계층 import 가 전부 금지되어 정상 테스트가 실패한다.
Normative dependency summary:
application -> adaptersconcrete import는MUST NOT이다.- output port definition은
application이MUST소유한다. - adapter는 application port를 구현하지만 application은 adapter 이름을 알면 안 된다.
- presentation은 application facade를 호출하며 raw backend envelope를 직접 다루면 안 된다.
- bootstrap만 concrete adapter를 조립할 수 있다.
adapters/transfer는UploadTransferPort입력으로 바이너리 descriptor를 받는다.adapters/file·adapters/blob-store의 concrete 모듈을 import하지 않으며, descriptor 조립은bootstrap또는 application orchestration이 한다 (DELEG-FE-008).adapters/realtime/push는ServiceWorkerHostPort인터페이스를 통해 SW 등록 상태를 읽는다.adapters/service-worker의 concrete 모듈을 import하지 않는다 (DELEG-FE-007).src/workers/*.worker.js와public/sw.js는 별도 실행 컨텍스트이므로presentation·application·domain을 import하지 않는다. 공유가 필요하면domain의 순수 모듈만 참조하고 그 사실을FE-REG-CAPABILITY행에 기록한다.- worker 엔트리는
adapters/worker가 소유한다.bootstrap이 직접new Worker()를 부르지 않는다.
4.4 Port ownership matrix
| Port | Definition owner | Planned implementation | Consumer | Input / output | Failure vocabulary |
|---|---|---|---|---|---|
ResourceQueryPort |
application |
adapters/http |
query use case | query object → validated model | ApiFailure |
ResourceCommandPort |
application |
adapters/http |
command use case | command + idempotency context → model | ApiFailure |
QueryCachePort |
application |
adapters/query-cache (TanStack Query) |
application query/mutation orchestration | registry query key + cache command → cache state/invalidation result | QUERY_CACHE_FAILURE |
AuthSessionPort |
application integration boundary |
external auth adapter | routing + API client interceptor | opaque session state / request header callback | AuthRequired, AuthIntegrationFailure |
StoragePort |
application |
adapters/storage |
preference/session-neutral use case | classified key + serializable value | StorageUnavailable, StorageQuotaExceeded |
TelemetryPort |
application |
adapters/telemetry |
application + boundary | sanitized event → best-effort ack | TelemetryDropped internal only |
ClockPort |
application |
browser/system clock adapter | retry/release logic | now / monotonic duration | no user-facing error |
ReleaseInfoPort |
application |
runtime config/release adapter | boot + chunk recovery | release manifest → compatible release info | RELEASE_MANIFEST_FAILURE, DEPLOY_MISMATCH |
CapabilityPort |
application |
adapters/capability |
bootstrap + capability 소비 use case | capability ID → 활성 여부 + 사유 | CAPABILITY_DISABLED, CAPABILITY_UNSUPPORTED |
FileDialogPort |
application |
adapters/file |
파일 입출력 use case | 선택 제약(accept·multiple·max) → 파일 descriptor 목록 / 저장 요청 → 저장 결과 | FILE_PICKER_DISMISSED, FILE_REJECTED |
BlobStorePort |
application |
adapters/blob-store |
로컬 바이너리 보관 use case | 등록 key + 바이너리 descriptor → 저장/조회/삭제 결과 | BLOB_STORE_UNAVAILABLE, BLOB_STORE_QUOTA_EXCEEDED |
CachePersistencePort |
application |
adapters/cache-persistence |
QueryCachePort 구현 보조 |
캐시 스냅샷 + version tuple → 영속/복원 결과 | CACHE_PERSISTENCE_FAILURE |
CrossTabSyncPort |
application |
adapters/cross-tab |
캐시 무효화 orchestration | 무효화 key 메시지 → 발행/수신 구독 | CROSS_TAB_CHANNEL_UNAVAILABLE |
UploadTransferPort |
application |
adapters/transfer/upload |
업로드 use case | 전송 계획(source descriptor + presign 결과) → 진행 스트림 + 완료 결과 | PRESIGN_EXPIRED, UPLOAD_PART_FAILED, TRANSFER_INTEGRITY_MISMATCH |
StreamingDownloadPort |
application |
adapters/transfer/download |
다운로드 use case | operation + range/resume 위치 → 진행 스트림 + 완료 결과 | STREAM_INTERRUPTED |
RealtimeSubscriptionPort |
application |
adapters/realtime/{sse,websocket,polling} |
스트림 소비 use case | 구독 descriptor + resume cursor → 검증된 이벤트 스트림 + 해제 handle | REALTIME_CONNECT_FAILED, REALTIME_DISCONNECTED, REALTIME_RESUME_GAP, EVENT_SCHEMA_MISMATCH |
PushSubscriptionPort |
application |
adapters/realtime/push |
알림 등록 use case | 권한 요청 + 공개키 → 구독 descriptor | PUSH_PERMISSION_DENIED, PUSH_SUBSCRIPTION_EXPIRED |
WorkerTaskPort |
application |
adapters/worker |
CPU 오프로드 use case | task 이름 + 직렬화 가능 입력 + timeout → 결과 또는 종료 | WORKER_UNAVAILABLE, WORKER_TASK_TIMEOUT |
ServiceWorkerHostPort |
application |
adapters/service-worker |
bootstrap + release 감시 | 등록 요청 → 등록/갱신 상태 스트림 | SW_REGISTRATION_FAILED |
BackgroundSyncPort |
application |
adapters/service-worker/sync |
지연 mutation use case | keyed mutation descriptor → 큐 등록 결과 | BACKGROUND_SYNC_UNSUPPORTED, BACKGROUND_SYNC_REPLAY_REJECTED |
AuthSessionPort는 token 문자열을 domain/application model로 반환하지 않는 형태를 우선한다. header supplier나 opaque credential attachment callback을 사용하고, 구현 세부는 auth owner가 정한다.
멀티프로토콜(FE-OC-030)은 신규 port가 0개다. GraphQL·gRPC-Web·Connect-Web은 기존 ResourceQueryPort/ResourceCommandPort의 다른 구현체다. 프로토콜이 application에 새 인터페이스로 새면 FE-D010의 dependency inversion이 무너지고, backend가 REST에서 gRPC로 옮겨갈 때 use case를 다시 써야 한다. 프로토콜 선택은 FE-REG-API.protocol 필드 = 데이터이지 타입이 아니다.
Image CDN은 adapter가 아니라 application의 순수 정책이다. URL 파생에는 I-O가 없다. MediaUrlPolicy를 application/policies/에 두고 CDN base·허용 transform은 FE-REG-ENV 행에서 읽는다. port로 만들면 테스트에 불필요한 test double만 늘어난다.
4.5 Composition root
Planned location:
src/bootstrap/main.jsx
src/bootstrap/composition-root.js
Boot order는 다음을 MUST 따른다.
- build identity 읽기
- runtime config fetch
- config envelope·schema·compatibility 검증
- release manifest 정합성 확인
- registry snapshot load
- capability 해석 — flag × 브라우저 feature detection → 활성 capability 집합 확정
- auth integration adapter 주입
- HTTP/storage/telemetry/query-cache adapter 생성
- 활성 capability 의 adapter 생성 (비활성 capability 의 adapter 는 생성하지 않음)
- application facade 생성
- router 생성
- React root mount
2~4단계가 실패하면 product route를 mount하지 않고 boot error shell만 렌더한다. telemetry adapter 생성 실패는 console-safe fallback으로 계속 진행할 수 있다.
6단계와 9단계는 다음을 MUST 지킨다.
- 6단계는 실패하지 않는다. flag가 ON인데 브라우저가 미지원이면 해당 capability를 비활성으로 확정하고
capability.activation.rejectedtelemetry를 남긴 뒤 boot를 계속한다. capability 부재가 boot를 막으면 skeleton이 특정 브라우저에 묶인다. - 9단계는 비활성 capability의 adapter 모듈을 정적 import하지 않는다. 정적 import하면
FE-NFR-020(비활성 시 initial JS 증가 0)이 깨지고FE-GATE-033이 실패한다.
4.6 Planned directory blueprint
src/
bootstrap/
main.jsx
composition-root.js
load-runtime-config.js
domain/
models/
policies/
application/
ports/
use-cases/
view-models/
policies/
presentation/
app/
routes/
pages/
components/
boundaries/
adapters/
http/
storage/
telemetry/
query-cache/
auth/
release/
capability/
file/
blob-store/
cache-persistence/
cross-tab/
transfer/
upload/
download/
protocol/
graphql/
grpc-web/
connect-web/
realtime/
sse/
websocket/
polling/
push/
worker/
service-worker/
sync/
contracts/
routes.js
api-operations.js
env.js
storage-keys.js
errors.js
query-keys.js
telemetry.js
release-tokens.js
capabilities.js
workers/
sample/
contract-fixture/
public/
sw.js
tests/
unit/
component/
integration/
e2e/
artifacts/
quality/
tests/
performance/
security/
release/
runbooks/
경로는 planned이며 repository가 생성될 때 변경될 수 있다. responsibility mapping이 유지되지 않으면 FE-D009 변경 절차를 거쳐야 한다.
5. Contract Registries
5.1 Registry owner map
| Registry ID | Registry | Planned path | Single owner | Ad hoc use failure |
|---|---|---|---|---|
FE-REG-ROUTE |
route ID/path/params/access | src/contracts/routes.js |
feature-routing-navigation-guard-contract |
component에 literal route path 추가 |
FE-REG-API |
API method/path/operation/auth/timeout/idempotency/schema | src/contracts/api-operations.js |
feature-api-client-response-envelope-contract |
raw request config 또는 unregistered operation 사용 |
FE-REG-ENV |
build/runtime public config | src/contracts/env.js |
feature-frontend-env-runtime-config-contract |
registry 없는 import.meta.env 또는 config key 사용 |
FE-REG-STORAGE |
storage key/version/classification | src/contracts/storage-keys.js |
feature-frontend-storage-registry-contract |
raw localStorage key literal 사용 |
FE-REG-ERROR |
frontend error kind/code/default UX | src/contracts/errors.js |
feature-frontend-error-classification-boundary-contract |
raw status/message로 UI 분기 |
FE-REG-QUERY |
query key factory/invalidation | src/contracts/query-keys.js |
feature-server-state-caching-contract |
page 안에서 ad hoc array key 생성 |
FE-REG-TELEMETRY |
event/attribute/redaction | src/contracts/telemetry.js |
feature-frontend-observability-logging-trace-contract |
자유 문자열 event 전송 |
FE-REG-RELEASE |
build/config/API/release token | src/contracts/release-tokens.js |
feature-frontend-release-cache-rollback-contract |
string version 비교 또는 cache key 직접 작성 |
FE-REG-CAPABILITY |
capability 활성 조건/owner/gate/fallback | src/contracts/capabilities.js |
feature-frontend-env-runtime-config-contract |
registry 없이 config를 직접 읽어 기능 분기 |
5.2 Route registry minimum schema
| Field | Required | Rule |
|---|---|---|
routeId |
yes | stable UPPER_SNAKE_CASE; rename은 breaking |
path |
yes | centralized literal; component 내부 literal 금지 |
paramsSchema |
conditional | dynamic param이 있으면 runtime validation |
searchSchema |
conditional | query string을 application input으로 넘기기 전 validation |
access |
yes | public, session-required, integration-defined |
loadingSurface |
yes | route-level fallback owner |
errorSurface |
yes | route-level error owner |
chunkId |
generated | release manifest와 매핑 |
Initial planned rows:
| routeId | path | access | Notes |
|---|---|---|---|
APP_HOME |
/ |
public |
sample shell |
SAMPLE_RESOURCE_LIST |
/sample/resources |
integration-defined |
contract fixture |
NOT_FOUND |
* |
public |
no API retry |
5.3 API operation registry minimum schema
모든 shared-client request는 아래 필드가 채워진 FE-REG-API row를 먼저 가져야 한다. raw path·timeout·auth·schema를 call site에서 다시 정의하면 registry violation이다.
| Field | Required | Rule |
|---|---|---|
method |
yes | uppercase HTTP method |
path |
yes | path template; query value와 host를 포함하지 않음 |
operationId |
yes | stable UPPER_SNAKE_CASE; telemetry·test·owner key |
auth |
yes | none 또는 external-session |
timeoutMs |
yes | default 10000; override는 decision change 필요 |
idempotency |
yes | safe, keyed, none 중 하나 |
requestSchema |
yes | body가 없으면 explicit none; params/search도 검증 |
responseSchema |
yes | success envelope의 payload schema reference |
owner |
yes | owning feature or branch slug |
protocol |
yes | rest(기본), graphql, grpc-web, connect-web, sse, websocket, poll. rest 외 값은 대응 capability 활성 필요 |
transferMode |
yes | unary(기본), stream, upload, download |
operationRef |
conditional | graphql은 persisted-document ID, grpc-web/connect-web은 package.Service/Method. rest는 none |
eventSchema |
conditional | transferMode: stream이면 이벤트 union schema reference 필수 |
resumeStrategy |
conditional | stream/download는 none, last-event-id, cursor, range 중 하나 |
timeoutMs는 transferMode: stream 행에서 연결 수립 timeout을 뜻하고 스트림 총 수명에는 적용하지 않는다. 스트림 수명은 FE-D033의 재연결·terminal 전이 계약이 소유한다. 이 구분이 없으면 정상적으로 살아 있는 구독이 10초마다 timeout으로 끊긴다.
Initial planned rows:
| operationId | method | path | auth | timeoutMs | idempotency | requestSchema | responseSchema | owner |
|---|---|---|---|---|---|---|---|---|
LIST_SAMPLE_RESOURCES |
GET |
/api/sample/resources |
external-session |
10000 |
safe |
SampleResourceListQuery |
SampleResourceListPayload |
feature-sample-feature-slice-contract-fixture |
CREATE_SAMPLE_RESOURCE |
POST |
/api/sample/resources |
external-session |
10000 |
keyed |
CreateSampleResourceCommand |
SampleResourcePayload |
feature-sample-feature-slice-contract-fixture |
Capability 확장 field를 쓰는 planned rows (전부 feature-sample-feature-slice-contract-fixture owner, 대응 capability가 OFF면 등록만 되고 호출되지 않음):
| operationId | method | path | protocol | transferMode | idempotency | operationRef | eventSchema | resumeStrategy |
|---|---|---|---|---|---|---|---|---|
STREAM_SAMPLE_EVENTS |
GET |
/api/sample/events |
sse |
stream |
safe |
none |
SampleEventUnion |
last-event-id |
PRESIGN_SAMPLE_UPLOAD |
POST |
/api/sample/uploads/presign |
rest |
unary |
keyed |
none |
— | none |
DOWNLOAD_SAMPLE_OBJECT |
GET |
/api/sample/objects/:id/content |
rest |
download |
safe |
none |
— | range |
PRESIGN_SAMPLE_UPLOAD는 presign을 획득하는 operation이며 byte 전송이 아니다. 실제 전송은 registry에 등록하지 않는 제3자 URL로 나가고, FE-D029에 따라 session credential을 첨부하지 않는다.
5.4 Environment registry minimum schema
| Key | Phase | Classification | Required | Default | Failure |
|---|---|---|---|---|---|
VITE_BUILD_ID |
build | public metadata | yes | none | build fail |
VITE_COMMIT_SHA |
build | public metadata | yes in CI | local sentinel allowed | release evidence fail |
VITE_ROUTER_BASE_PATH |
build | non-secret compile-time constant | yes | / |
route mount fail |
VITE_RUNTIME_CONFIG_URL |
build | non-secret compile-time constant | yes | /config.json |
boot fail |
APP_ENV |
runtime | public | yes | none | boot fail |
API_BASE_URL |
runtime | public-sensitive | yes | none | boot fail |
REQUEST_TIMEOUT_MS |
runtime | public | no | 10000 |
invalid value boot fail |
MAX_RETRY_ATTEMPTS |
runtime | public | no | 2 after initial |
invalid value boot fail |
TELEMETRY_ENABLED |
runtime | public | yes | false |
invalid value boot fail |
TELEMETRY_ENDPOINT |
runtime | public-sensitive | conditional | none | telemetry degrade |
AUTH_MODE |
runtime | public | yes | external |
unsupported mode boot fail |
CONFIG_SCHEMA_VERSION |
runtime | public | yes | none | compatibility fail |
API_CONTRACT_VERSION |
runtime | public | yes | none | compatibility fail |
RELEASE_MANIFEST_URL |
runtime | public | yes | /release-manifest.json |
mismatch detection degrade/fail per policy |
CAPABILITY_BINARY_IO_ENABLED |
runtime | public | no | false |
invalid value boot fail |
CAPABILITY_CACHE_PERSISTENCE_ENABLED |
runtime | public | no | false |
invalid value boot fail |
CAPABILITY_LARGE_TRANSFER_ENABLED |
runtime | public | no | false |
invalid value boot fail |
CAPABILITY_ALT_PROTOCOL_ENABLED |
runtime | public | no | false |
invalid value boot fail |
CAPABILITY_REALTIME_ENABLED |
runtime | public | no | false |
invalid value boot fail |
CAPABILITY_BACKGROUND_EXEC_ENABLED |
runtime | public | no | false |
invalid value boot fail |
ALT_PROTOCOL_BASE_URL |
runtime | public-sensitive | conditional | none | capability 활성 시 boot fail |
REALTIME_ENDPOINT_URL |
runtime | public-sensitive | conditional | none | capability 활성 시 boot fail |
MEDIA_CDN_BASE_URL |
runtime | public-sensitive | conditional | none | 미설정 시 원본 URL 사용 |
MEDIA_CDN_ALLOWED_TRANSFORMS |
runtime | public | conditional | [] |
허용 외 transform 요청은 무시 |
PUSH_PUBLIC_KEY |
runtime | public | conditional | none | push 활성 시 boot fail |
TRANSFER_PART_SIZE_BYTES |
runtime | public | no | 8388608 |
invalid value boot fail |
TRANSFER_MAX_PARALLEL_PARTS |
runtime | public | no | 3 |
invalid value boot fail |
REALTIME_RECONNECT_CAP_MS |
runtime | public | no | 30000 |
invalid value boot fail |
WORKER_TASK_TIMEOUT_MS |
runtime | public | no | 30000 |
invalid value boot fail |
public-sensitive는 browser에서 볼 수 있지만 로그·telemetry에 원문을 남기지 않는 endpoint-like value를 뜻한다. secret 분류가 아니다.
PUSH_PUBLIC_KEY는 VAPID 공개키이므로 public이다. 대응 개인키는 backend 소유이며 이 registry에 등록할 수 없다.
capability flag 6개의 기본값이 전부 false인 것은 FE-D026의 default-OFF 자세이며, 이 기본값 조합으로 build했을 때 대응 adapter가 번들에 없어야 한다는 사실은 FE-GATE-033이 검증한다.
5.5 Storage registry minimum schema
| Field | Required | Rule |
|---|---|---|
logicalName |
yes | 의미 이름, raw key가 아님 |
physicalKey |
yes | <app>:<scope>:v<schema>:<name> |
backend |
yes | memory, sessionStorage, localStorage, indexedDB, opfs, cacheStorage |
classification |
yes | public-preference, opaque-cache, sensitive-forbidden |
schemaVersion |
yes | incompatible change 시 increment |
ttl |
conditional | persistent cache는 expiry 필수 |
migration |
conditional | previous version을 읽으면 migration 또는 discard |
quotaFallback |
yes | memory/no-persist/feature-disable 중 하나. correctness에 영향을 주는 값은 없음으로 선언 |
payloadClass |
yes | structured(기본) 또는 binary. binary는 sensitive-forbidden classification과 조합할 수 없음 |
evictionOrder |
yes | quota 압박 시 제거 순서(정수, 낮을수록 먼저). 제거 불가 값은 null |
Initial planned rows:
| logicalName | backend | classification | payloadClass | TTL / fallback | evictionOrder |
|---|---|---|---|---|---|
COLOR_SCHEME |
localStorage |
public-preference |
structured |
no TTL / system default | 4 |
CHUNK_RELOAD_GUARD |
sessionStorage |
opaque-cache |
structured |
session / no second auto reload | null |
QUERY_PERSISTENCE |
disabled | sensitive-forbidden default |
structured |
opt-in contract required | — |
AUTH_TOKEN |
forbidden | sensitive-forbidden |
— | external auth owner only | — |
UPLOAD_PART_STATE |
indexedDB |
opaque-cache |
structured |
전송 완료 또는 24h / fallback 없음 | null |
TRANSFER_OBJECT_BUFFER |
opfs |
opaque-cache |
binary |
전송 완료 시 삭제 / no-persist | 1 |
QUERY_CACHE_SNAPSHOT |
indexedDB |
opaque-cache |
structured |
release·config·API version 파티션 / memory-only | 2 |
SW_RESPONSE_CACHE |
cacheStorage |
opaque-cache |
binary |
release 단위 파티션 / feature-disable | 3 |
UPLOAD_PART_STATE의 quotaFallback이 없음이고 evictionOrder가 null인 것은 §9.4의 "correctness에 영향을 주는 값은 storage fallback을 임의 적용하지 않는다"를 이 행에 적용한 것이다. part 상태가 조용히 memory로 넘어가면 새로고침 한 번에 이어받기가 불가능해지고, 사용자는 그 사실을 전송이 실패한 뒤에야 알게 된다.
5.6 Error registry minimum schema
| Field | Required | Rule |
|---|---|---|
kind |
yes | frontend stable enum |
defaultRetryable |
yes | request context가 override 가능 |
severity |
yes | telemetry routing hint, user copy와 분리 |
userMessageKey |
yes | raw backend message 사용 금지 |
action |
yes | retry, reauth, navigate, reload-once, contact-support, none |
telemetryEvent |
yes | registry event에 매핑 |
redaction |
yes | cause/body/header drop rule |
Planned kind enum:
NETWORK_UNREACHABLE
REQUEST_TIMEOUT
REQUEST_ABORTED
CONTENT_TYPE_MISMATCH
MALFORMED_JSON
ENVELOPE_MISMATCH
SCHEMA_MISMATCH
AUTH_REQUIRED
AUTH_INTEGRATION_FAILURE
FORBIDDEN
NOT_FOUND
CONFLICT
VALIDATION_REJECTED
UNKNOWN_CLIENT_FAILURE
RATE_LIMITED
SERVER_FAILURE
CHUNK_LOAD_FAILURE
BOOT_CONFIG_FAILURE
RELEASE_MANIFEST_FAILURE
DEPLOY_MISMATCH
STORAGE_UNAVAILABLE
STORAGE_QUOTA_EXCEEDED
RENDER_FAILURE
TELEMETRY_FAILURE
QUERY_CACHE_FAILURE
CAPABILITY_DISABLED
CAPABILITY_UNSUPPORTED
FILE_PICKER_DISMISSED
FILE_REJECTED
BLOB_STORE_UNAVAILABLE
BLOB_STORE_QUOTA_EXCEEDED
CACHE_PERSISTENCE_FAILURE
CROSS_TAB_CHANNEL_UNAVAILABLE
PRESIGN_EXPIRED
UPLOAD_PART_FAILED
TRANSFER_INTEGRITY_MISMATCH
STREAM_INTERRUPTED
PROTOCOL_STATUS_MISMATCH
CODEC_DECODE_FAILURE
PARTIAL_RESULT_FAILURE
REALTIME_CONNECT_FAILED
REALTIME_DISCONNECTED
REALTIME_RESUME_GAP
EVENT_SCHEMA_MISMATCH
PUSH_PERMISSION_DENIED
PUSH_SUBSCRIPTION_EXPIRED
WORKER_UNAVAILABLE
WORKER_TASK_TIMEOUT
SW_REGISTRATION_FAILED
BACKGROUND_SYNC_UNSUPPORTED
BACKGROUND_SYNC_REPLAY_REJECTED
UNKNOWN_FAILURE
의도적으로 만들지 않은 kind가 셋 있다. TRANSFER_ABORTED는 기존 REQUEST_ABORTED를 재사용한다. SUBSCRIPTION_LEAKED는 사용자에게 보이는 실패가 아니라 FE-GATE-031이 잡는 결함이므로 kind가 아니라 fixture 이름이다. SW_UPDATE_PENDING도 실패가 아니라 §9.7의 surface state다.
5.7 Query key registry minimum schema
Query key는 factory로만 생성한다.
queryKeys.resource.all()
queryKeys.resource.list(filters)
queryKeys.resource.detail(resourceId)
| Rule | Normative behavior |
|---|---|
| namespace | feature prefix를 첫 element로 사용 |
| serialization | object key ordering을 canonicalize |
| identity | PII, token, raw URL을 key에 넣지 않음 |
| invalidation | mutation outcome과 mapping된 factory만 invalidate |
| version | API/schema breaking change 시 namespace version bump |
| persistence | default disabled; opt-in 시 release/config version partition |
persistenceTier |
memory(기본), session, local, indexedDB. memory 외 값은 CAP_FE_CACHE_PERSISTENCE 활성 필요 |
crossTabScope |
none(기본) 또는 same-origin. same-origin은 무효화 key만 전파하고 값은 전파하지 않음 (FE-D028) |
| version partition | 영속 tier는 releaseId·configSchemaVersion·apiContractVersion을 파티션 키에 포함. 불일치 시 복원하지 않고 폐기 |
5.8 Telemetry registry minimum schema
| Field | Required | Rule |
|---|---|---|
eventName |
yes | stable dotted name |
trigger |
yes | 발생 시점 단일 정의 |
requiredAttributes |
yes | low-cardinality only |
optionalAttributes |
yes | absence-safe |
forbiddenAttributes |
yes | token, email, raw URL/query/body, storage value, 파일명, object key, presigned URL, 구독 endpoint |
sampling |
yes | error/security event는 별도 정책 |
delivery |
yes | best-effort, audit channel 아님 |
Initial planned events:
| Event | Trigger | Required attributes |
|---|---|---|
app.boot.failed |
config/release validation 실패 | error_kind, build_id, config_schema_version |
api.request.failed |
terminal normalized API failure | error_kind, http_status_group, attempt_count_bucket, route_id |
ui.render.failed |
React boundary catch | route_id, build_id, component_boundary |
release.mismatch.detected |
chunk/config/API version mismatch | build_id, active_release_id, mismatch_kind |
telemetry.delivery.dropped |
sink/queue failure | reason, queue_size_bucket |
capability.activation.rejected |
flag ON인데 브라우저 미지원으로 비활성 확정 | capability_id, reason, build_id |
transfer.part.failed |
upload part 재시도 소진 | operation_id, part_index_bucket, error_kind |
transfer.completed |
전송 종료(성공/실패 공통) | operation_id, outcome, size_bucket, duration_bucket |
realtime.connection.state_changed |
연결 상태 전이 | operation_id, from_state, to_state, attempt_count_bucket |
realtime.event.rejected |
인바운드 프레임 스키마 거부 | operation_id, error_kind |
sw.update.applied |
service worker 신 버전 활성화 | build_id, previous_build_id |
background.sync.replayed |
background sync 재생 결과 | operation_id, outcome |
5.9 Release token registry minimum schema
| Token | Source | Compatibility role |
|---|---|---|
appVersion |
manifest | human release label |
buildId |
CI build | asset/HTML coherence |
commitSha |
VCS | source traceability |
configSchemaVersion |
runtime config schema | boot compatibility |
apiContractVersion |
frontend/backend agreement | schema compatibility |
assetManifestHash |
build output | chunk integrity/mismatch |
releaseId |
deploy system | rollback target |
builtAt |
CI | diagnostics, not cache identity |
serviceWorkerVersion |
build output | service worker 스크립트와 release의 coherence. rollback 시 SW도 함께 되돌아갔는지 판정 (FE-D034, DELEG-FE-011) |
5.10 Registry change protocol
- owner branch에 decision 또는 change row를 먼저 추가한다.
- registry schema validation을 갱신한다.
- compatibility impact를 기록한다.
- breaking이면 version bump와 migration·discard·fallback 중 하나를 정한다.
- producer와 consumer test를 함께 갱신한다.
- snapshot artifact를 생성한다.
- release note에 affected
FE-OC-*와 rollback condition을 적는다. - orphan token scan이 0건이어야 merge할 수 있다.
5.11 Capability registry minimum schema
이 절은 §5.10 뒤에 붙였다. §5.5 뒤에 끼워 넣으면 §5.6~§5.10이 밀려 이 문서와 27개 branch-note의 절 참조가 전부 어긋난다. 절 번호 순서보다 기존 참조 안정성이 우선이다.
FE-REG-CAPABILITY는 FE-D026이 정한 default-OFF 자세를 강제하는 장부다. flag의 타입·기본값·검증은 FE-REG-ENV가 계속 소유하고, 이 registry는 활성화 계약(누가 소유하고, 어떤 gate가 지켜보고, 못 켜면 무엇으로 대체하는가)만 가진다.
| Field | Required | Rule |
|---|---|---|
capabilityId |
yes | stable UPPER_SNAKE_CASE; rename은 breaking |
envFlagKey |
yes | FE-REG-ENV 행 포인터. 키의 타입·기본값·검증 규칙을 여기 재진술하지 않음 |
owner |
yes | 소유 branch slug |
requiredGate |
yes | 활성화 시 반드시 PASS해야 하는 FE-GATE-* |
browserRequirement |
yes | feature detection 식별자. 미지원이면 flag가 ON이어도 활성화되지 않음 |
disabledFallback |
yes | feature-hidden, degraded-alternative, error-surface 중 하나 |
runbookRef |
conditional | 운영 실패 절차가 있는 capability는 FE-RB-* 참조 필수 |
Initial planned rows:
| capabilityId | envFlagKey | owner | requiredGate | browserRequirement | disabledFallback | runbookRef |
|---|---|---|---|---|---|---|
CAP_FE_BINARY_IO |
CAPABILITY_BINARY_IO_ENABLED |
feature-frontend-binary-file-io-store-contract |
FE-GATE-027 |
indexedDB (OPFS·Cache Storage는 하위 detection) |
feature-hidden |
— |
CAP_FE_CACHE_PERSISTENCE |
CAPABILITY_CACHE_PERSISTENCE_ENABLED |
feature-frontend-cache-tier-cross-tab-invalidation-contract |
FE-GATE-028 |
indexedDB |
degraded-alternative (메모리 캐시만) |
— |
CAP_FE_LARGE_TRANSFER |
CAPABILITY_LARGE_TRANSFER_ENABLED |
feature-frontend-large-object-transfer-contract |
FE-GATE-029 |
ReadableStream, AbortController |
feature-hidden |
— |
CAP_FE_ALT_PROTOCOL |
CAPABILITY_ALT_PROTOCOL_ENABLED |
feature-frontend-multi-protocol-api-transport-contract |
FE-GATE-030 |
fetch streaming (gRPC-Web 시) |
degraded-alternative (REST gateway) |
— |
CAP_FE_REALTIME |
CAPABILITY_REALTIME_ENABLED |
feature-frontend-realtime-subscription-lifecycle-contract |
FE-GATE-031 |
EventSource 또는 WebSocket |
degraded-alternative (bounded polling) |
FE-RB-006 |
CAP_FE_BACKGROUND_EXEC |
CAPABILITY_BACKGROUND_EXEC_ENABLED |
feature-frontend-background-execution-worker-contract |
FE-GATE-032 |
Worker; SW 하위 기능은 serviceWorker |
feature-hidden |
FE-RB-007 |
src/workers/*.worker.js 또는 public/sw.js가 domain 순수 모듈을 참조하면 그 사실을 해당 행에 기록한다(§4.3).
6. Build-time, Runtime, Secret Configuration
6.1 Three-way distinction
| Class | Example | Visible to browser | Change mechanism | Cache policy | Rule |
|---|---|---|---|---|---|
| build-time public | BUILD_ID, COMMIT_SHA, ROUTER_BASE_PATH |
yes | rebuild | bundled | compiler behavior·asset identity만 |
| runtime public | API_BASE_URL, feature-public flag, telemetry endpoint |
yes | runtime config publish | no-store |
boot before React mount |
| secret | client secret, private key, DB credential, refresh token policy material | should not be bundled | server/auth owner | N/A | frontend env·bundle·HTML에 넣지 않음 |
VITE_* prefix는 build ID·commit SHA 같은 build metadata와 base path·/config.json 위치 같은 non-secret compile-time constant에만 사용한다. API endpoint, telemetry endpoint, public feature flag처럼 배포 후 달라질 수 있는 값은 /config.json에서 읽는다. 이름에 SECRET, PASSWORD, PRIVATE_KEY, TOKEN이 포함된 key는 build와 runtime registry 모두에서 거부한다. auth owner가 browser storage를 사용해야 한다면 별도 threat model과 owner evidence가 필요하며 본 skeleton default가 아니다.
6.2 Conditional deployment defaults
- If hosting이 runtime config를 HTML보다 먼저 atomic publish할 수 있음 →
FE-D012runtime config 사용. - If hosting이 정적 파일만 제공하고 atomic config publish가 불가능함 → environment별 rebuild를 허용하되 artifact를 env 간 재사용하지 않음.
- If SSR/edge runtime이 도입됨 → 본 config contract를 그대로 적용하지 않고 별도 project fork decision 필요.
6.3 Boot sequence
sequenceDiagram
autonumber
participant Browser
participant HTML as index.html
participant Boot as bootstrap
participant Config as /config.json
participant Release as release-manifest.json
participant Schema as Zod schemas
participant App as React App
Browser->>HTML: GET index.html
HTML-->>Browser: no-cache app shell
Browser->>Boot: load hashed entry chunk
Boot->>Config: GET runtime config (no-store)
Boot->>Release: GET release manifest (no-store)
Boot->>Schema: validate config + compatibility
alt valid and compatible
Schema-->>Boot: normalized public config
Boot->>App: compose dependencies and mount
else invalid config
Schema-->>Boot: BOOT_CONFIG_FAILURE
Boot-->>Browser: boot error shell, product routes not mounted
else version mismatch
Schema-->>Boot: DEPLOY_MISMATCH
Boot-->>Browser: controlled recovery UI, no reload loop
end
6.4 Runtime config validation
Validation MUST cover:
- required key presence
- URL protocol allowlist (
httpsin production policy; local exception documented) - integer range for timeout/retry
- boolean parsing without truthy string ambiguity
- config schema version compatibility
- API contract version compatibility
- release/build ID coherence when provider exposes both
- unknown key policy: additive keys allowed only if schema explicitly passthroughs; default strict for safety
Boot failure output MUST contain safe fields only:
error.kind
error.code
buildId
configSchemaVersion
releaseId (if present)
supportReference
Endpoint, query, header, raw config object, stack은 user-facing screen에 표시하지 않는다.
7. API Client Operational Contract
7.1 Shared client boundary
모든 API request는 application output port를 구현한 shared HTTP adapter를 통과해야 한다.
Page/component MUST NOT:
- 직접
fetch호출 AbortControllertimeout 구현 복제- backend status를 user copy로 직접 변환
- raw response body를 log
- page-local retry loop 생성
- auth token을 storage에서 읽음
7.2 Request context
각 logical request는 다음 context를 가진다.
| Field | Required | Rule |
|---|---|---|
operationId |
yes | registry-backed stable name |
method |
yes | uppercase HTTP method |
routeId |
yes | raw URL 대신 low-cardinality route ID |
timeoutMs |
yes | default 10000, operation override는 owner decision 필요 |
idempotency |
yes | safe, keyed, none |
attempt |
yes | initial=0, retry=1..N |
abortReason |
optional | navigation, user, timeout, superseded |
authMode |
yes | none, external-session |
7.3 Response envelope
Expected success shape:
success: true
data: <payload>
meta.requestId
meta.traceId
meta.correlationId (optional if backend contract omits)
Expected failure shape:
success: false
error.code
error.category
error.message
error.retryable
error.details (optional, client-safe)
meta.requestId
meta.traceId
Processing order:
- HTTP transport completion
- content-type expectation check
- JSON parse
- envelope schema validation
- success/failure branch validation
- payload schema validation
- DTO → application model mapper
- application result 또는 normalized failure 반환
Stage 7은 adapter 경계에서 validated model까지만 만든다. view-model 투영은 §4.2/§4.4가 정한 대로 application이 소유하며 application/view-models/에 둔다(2-stage 매핑). 따라서 QueryCachePort가 담는 것은 view-model이 아니라 model이다.
200이더라도 JSON/envelope/payload가 invalid하면 success로 반환하지 않는다. 4xx/5xx body가 invalid하면 status 기반 safe fallback error를 만들고 raw body는 버린다.
7.4 Timeout and abort
| Situation | Classification | Retry | Telemetry | UX |
|---|---|---|---|---|
| 10s total timeout | REQUEST_TIMEOUT |
safe/keyed만 policy 적용 | terminal일 때 1 event | retry action |
| navigation cancel | REQUEST_ABORTED |
no | debug counter only, error event 없음 | stale surface 제거 |
| user cancel | REQUEST_ABORTED |
no | optional interaction event | neutral canceled state |
| superseded query | REQUEST_ABORTED |
no | none | latest request 유지 |
| external signal abort | reason에 따라 | no unless timeout owner | redacted reason | context-specific |
Browser fetch는 portable connect/read timeout을 분리 제공하지 않으므로 이 문서는 total timeout만 기본값으로 둔다. 별도 transport가 도입되기 전 connect timeout을 구현 사실처럼 말하지 않는다.
7.5 Retry algorithm
Initial default:
maxRetries = 2
baseDelayMs = 250
maxDelayMs = 2000
algorithm = min(maxDelayMs, baseDelayMs * 2^retryIndex) * random(0, 1)
jitter = full jitter
Normative rules:
- initial request는 retry count에 포함하지 않는다.
- retry schedule은
ClockPort와 injectable random source로 test 가능해야 한다. REQUEST_ABORTED,MALFORMED_JSON,ENVELOPE_MISMATCH,SCHEMA_MISMATCH,401,403,404,409,422는 default non-retryable이다.- network failure, timeout,
429,502,503,504는 safe/keyed request에서만 retry candidate다. - generic
500은 automatic retry default off; operation owner가 safe condition을 증명해야 opt-in 가능하다. - browser offline signal은 hint일 뿐 최종 truth로 사용하지 않는다.
- retry 중 component가 unmount되거나 query가 superseded되면 남은 timer와 request를 취소한다.
7.6 Retry-After
429 또는 backend가 명시한 retryable response에 Retry-After가 있으면 다음 순서를 따른다.
- delta-seconds 또는 HTTP-date parse
- invalid/negative면 local backoff 사용
- valid delay가 30s를 넘으면 automatic retry하지 않고 terminal
RATE_LIMITEDUX로 전환 - valid delay가 30s 이하면 local backoff와 비교해 더 긴 값을 사용
- navigation/user abort 발생 시 wait 취소
Retry-After raw value를 telemetry에 남기지 않고 normalized delay bucket만 남긴다.
7.7 Idempotency
Mutation retry conditions:
- backend contract가
Idempotency-Key를 지원한다고 registry에 명시 - 한 logical user action에 하나의 key 사용
- retry마다 같은 key 재사용
- 새 user action은 새 key 사용
- key는 telemetry, URL, user message에 노출하지 않음
- concurrent double-submit은 같은 logical action이면 client-side single-flight 또는 UI disable로 합침
- backend가 replay 여부를 반환하면 result metadata로만 소비
Key 생성 책임은 auth token lifecycle과 분리한다. key persistence가 필요하면 storage registry에 TTL·classification·migration을 추가하기 전에는 memory-only다.
7.8 Auth integration boundary
Skeleton owns:
- route가 요구하는 session state 소비
- request 전
AuthSessionPort.attach(request)호출 401을AUTH_REQUIRED로 정규화403을FORBIDDEN으로 정규화- auth owner callback으로 unauthenticated transition 알림
- navigation guard는 UX hint이며 backend authorization을 대체하지 않는다는 규칙
Skeleton does not own:
- authorization code exchange
- token 저장 위치
- access token refresh
- refresh token rotation
- logout propagation
- revocation
- identity provider redirect detail
- backend permission decision
401 recovery는 session state transition만 소유하며 credential 획득·저장·회전은 계속 외부 auth owner가 소유한다. logical request당 recovery callback은 최대 1회다.
| Current session state | Event | Next state | Skeleton action |
|---|---|---|---|
authenticated |
first 401 |
recovery-pending |
external owner의 bounded recovery callback 1회 호출 |
recovery-pending |
owner reports session restored | authenticated |
아래 replay policy 적용 |
recovery-pending |
owner reports no session | unauthenticated |
terminal AUTH_REQUIRED 반환 |
recovery-pending |
adapter throws/rejects/invalid result | integration-failed |
terminal AUTH_INTEGRATION_FAILURE 반환 |
| any | second 401 for same logical request |
unauthenticated |
추가 recovery 없이 terminal AUTH_REQUIRED 반환 |
Recovery 이후 replay policy:
saferequest는 같은 logical request context로 최대 1회 replay할 수 있다.keyedmutation은 같은 stable idempotency key와 active backend replay contract를 유지할 때만 최대 1회 replay할 수 있다.none인 unkeyed mutation은 recovery 성공 후에도MUST NOTreplay한다. UI는 명시적 재시도를 요구한다.- replay와 일반 retry를 합친 총 시도 횟수는 operation registry와 test fixture가 추적하며 recovery loop를 만들 수 없다.
7.9 Request sequence
sequenceDiagram
autonumber
actor User
participant UI as Presentation
participant App as Application
participant Query as QueryCachePort / TanStack adapter
participant HTTP as HTTP Adapter
participant Auth as AuthSessionPort
participant API as Backend API
participant Schema as Runtime Schema
User->>UI: route enter or action
UI->>App: execute use case
App->>Query: query/mutation with registry key
Query->>HTTP: application output port
HTTP->>Auth: attach opaque session context
Auth-->>HTTP: request-ready callback result
HTTP->>API: request + timeout signal
alt success envelope
API-->>HTTP: JSON response
HTTP->>Schema: envelope + payload validate
Schema-->>HTTP: normalized model
HTTP-->>Query: result
Query-->>App: cache state
App-->>UI: view-model
UI-->>User: success or empty
else retry candidate
API-->>HTTP: network/429/502/503/504
HTTP->>HTTP: bounded backoff + jitter
HTTP-->>Query: result or terminal failure
Query-->>App: refreshing or terminal failure
App-->>UI: safe view state and action
else contract/auth failure
API-->>HTTP: invalid schema / 401 / 403
HTTP-->>Query: non-retryable normalized failure
Query-->>App: normalized failure
App-->>UI: safe action and message key
else query-cache adapter failure
Query-->>App: QUERY_CACHE_FAILURE
App-->>UI: uncached-safe fallback or terminal error
end
8. Frontend Failure Taxonomy
8.1 Normalized failure shape
kind
code
httpStatus (optional)
retryable
operationId
attemptCount
requestId (optional)
traceId (optional)
userMessageKey
action
causeClass (internal allowlist only)
Raw response body, token, authorization header, full URL/query, stack, storage value는 normalized failure에 포함하지 않는다.
8.2 Failure matrix
| Trigger | Normalized kind | Auto retry | Fallback | User UX | Telemetry rule |
|---|---|---|---|---|---|
| DNS/offline/CORS-like opaque network failure | NETWORK_UNREACHABLE |
safe/keyed, max 2 | cached safe data if available | offline/network message + manual retry | terminal 1회, raw URL 금지 |
| total timeout | REQUEST_TIMEOUT |
safe/keyed, max 2 | stale data 유지 가능 | timeout message + retry | elapsed bucket, attempts |
| navigation abort | REQUEST_ABORTED |
no | latest route state | error toast 금지 | error event 금지 |
| user abort | REQUEST_ABORTED |
no | neutral canceled state | canceled label if needed | interaction-only |
JSON operation의 response Content-Type 불일치 |
CONTENT_TYPE_MISMATCH |
no | prior safe cache 또는 error | incompatible response message | expected/actual media type category only |
| response not valid JSON | MALFORMED_JSON |
no | prior safe cache 또는 error | contract failure message | content-type/status group only |
| top-level envelope missing/invalid | ENVELOPE_MISMATCH |
no | prior safe cache 또는 error | service response incompatible | schema version, no body |
| payload schema invalid | SCHEMA_MISMATCH |
no | prior safe cache 또는 error | update/support message | schema ID + safe issue path count |
| HTTP 401 | AUTH_REQUIRED |
no in skeleton | external auth callback | sign-in/re-auth action | route ID, no principal/token |
| auth attach/recovery adapter throws, rejects, or returns invalid state | AUTH_INTEGRATION_FAILURE |
no | unauthenticated-safe shell | sign-in/support action | phase + safe adapter outcome only |
| HTTP 403 | FORBIDDEN |
no | keep shell | permission message, no retry | operation + status |
| HTTP 404 | NOT_FOUND |
no | route/resource not-found | navigate back/home | low severity |
| HTTP 409 | CONFLICT |
no | refetch authoritative data | conflict resolution action | operation + safe backend code |
| HTTP 422 | VALIDATION_REJECTED |
no | preserve user input | field/form safe details | field names allowlist only |
| other 4xx | UNKNOWN_CLIENT_FAILURE |
no | preserve safe shell/state | generic request correction/support action | operation + status group only |
| HTTP 429 | RATE_LIMITED |
safe/keyed + bounded Retry-After |
stale data if safe | countdown/manual retry | delay bucket, attempts |
| HTTP 500 | SERVER_FAILURE |
default no | stale safe data | service failure | error code/status group |
| HTTP 502 | SERVER_FAILURE |
safe/keyed, max 2 | stale safe data | temporary service failure | attempts + terminal |
| HTTP 503 | SERVER_FAILURE |
safe/keyed, max 2 | stale safe data | temporary service failure | Retry-After bucket |
| HTTP 504 | SERVER_FAILURE |
safe/keyed, max 2 | stale safe data | gateway timeout | attempts + duration bucket |
| other 5xx | SERVER_FAILURE |
default no | safe fallback | service failure | status group only |
| chunk fetch fails | CHUNK_LOAD_FAILURE |
one controlled reload only after release check | current shell | update/reload action | build/release IDs |
| runtime config missing/invalid | BOOT_CONFIG_FAILURE |
one refetch allowed | boot error shell | support reference | safe config schema fields |
| release manifest fetch, parse, or schema validation failure | RELEASE_MANIFEST_FAILURE |
one bounded refetch at boot only | boot/update shell | update/support action | phase + build ID, no raw manifest |
| HTML/asset/config release mismatch | DEPLOY_MISMATCH |
no request retry | controlled reload once or rollback | update message | mismatch kind + IDs |
| storage API unavailable/security error | STORAGE_UNAVAILABLE |
no | memory-only | usually silent, feature note if needed | backend type + reason enum |
| storage quota exceeded | STORAGE_QUOTA_EXCEEDED |
no | evict allowed cache then memory-only | non-blocking notice if feature affected | quota bucket, no values |
| React render throws | RENDER_FAILURE |
no auto retry | nearest boundary shell | retry route / reload action | component boundary + build ID |
| telemetry endpoint/network fails | TELEMETRY_FAILURE |
bounded internal queue only | console-safe/drop | no product error | self-metric, no recursion |
QueryCachePort read/write/invalidate throws or returns an invalid result |
QUERY_CACHE_FAILURE |
no automatic request retry | operation-declared uncached mode만 허용, 아니면 terminal | retry/support action; stale 표시를 위조하지 않음 | phase + query namespace, raw key/data 금지 |
| capability flag OFF 상태에서 해당 기능 진입 | CAPABILITY_DISABLED |
no | FE-REG-CAPABILITY의 disabledFallback |
fallback이 feature-hidden이면 진입점 자체를 노출하지 않음 |
capability ID only |
| flag ON이지만 브라우저 feature detection 실패 | CAPABILITY_UNSUPPORTED |
no | FE-REG-CAPABILITY의 disabledFallback |
대체 경로 안내, 브라우저 이름 단정 금지 | capability ID + reason enum |
| 사용자가 파일 선택 dialog를 닫음 | FILE_PICKER_DISMISSED |
no | 이전 상태 유지 | error surface 없음 — 취소는 실패가 아님 | error event 금지 |
| 선택 파일이 accept/size 제약 위반 | FILE_REJECTED |
no | 선택 목록에서 제외 | 위반 제약을 필드 단위로 안내 | 제약 종류만, 파일명 금지 |
| IndexedDB/OPFS/Cache Storage 접근 불가 또는 security error | BLOB_STORE_UNAVAILABLE |
no | registry quotaFallback; 없음이면 terminal |
기능 저하 고지, 무음 처리 금지 | backend type + reason enum |
| 로컬 바이너리 quota 초과 | BLOB_STORE_QUOTA_EXCEEDED |
no | evictionOrder 순 제거 후 재시도, null 행은 제거 금지 |
저장 실패 고지 + 정리 action | quota bucket, 값 금지 |
| 캐시 직렬화·영속·복원 실패 | CACHE_PERSISTENCE_FAILURE |
no | 메모리 캐시만 사용 | 무음, 필요 시 stale 표시 | phase + tier only |
BroadcastChannel과 storage event가 모두 불가 |
CROSS_TAB_CHANNEL_UNAVAILABLE |
no | 탭 내 무효화만 수행 | 무음, 다중 탭 stale 가능성 고지 가능 | reason enum only |
| presigned URL 만료/거부 | PRESIGN_EXPIRED |
presign 재획득 후 1회 | 재획득 성공 시 같은 위치에서 재개 | 자동 재개, 재획득도 실패하면 retry action | operation ID only, URL 금지 |
| upload part 재시도 상한 소진 | UPLOAD_PART_FAILED |
no (part 내부 재시도는 최대 2회) | part 상태 보존 후 일시정지 | 재개 action, 진행률 유지 | part index bucket + attempts |
| 체크섬 또는 크기 불일치 | TRANSFER_INTEGRITY_MISMATCH |
no | 해당 part 폐기 후 재전송 1회, 재실패면 terminal | 무결성 실패 고지 + 처음부터 다시 action | size bucket only |
| 다운로드 스트림 중단 | STREAM_INTERRUPTED |
resumeStrategy: range면 1회 |
받은 범위 보존 후 재개 | 재개 action | bytes bucket + resume 가능 여부 |
transport status와 protocol status 불일치 (HTTP 200 + grpc-status 비0 등) |
PROTOCOL_STATUS_MISMATCH |
protocol status가 재시도 가능일 때만 safe/keyed | prior safe cache 또는 error | 서비스 응답 비호환 메시지 | protocol + status code group |
| protobuf/GraphQL 디코드 실패 | CODEC_DECODE_FAILURE |
no | prior safe cache 또는 error | contract failure 메시지 | codec + operation ID, 본문 금지 |
GraphQL 200 OK + errors[] |
PARTIAL_RESULT_FAILURE |
no | 부분 데이터를 성공으로 취급하지 않음 | 실패한 필드 범위 안내 | error path count only, message 금지 |
| 최초 실시간 연결 수립 실패 | REALTIME_CONNECT_FAILED |
full jitter backoff, 30s cap, 상한까지 | 마지막 스냅샷 유지 | connecting 유지 후 상한 도달 시 전이 |
attempt bucket + transport |
| 재시도 상한 소진 후 terminal | REALTIME_DISCONNECTED |
no — 자동 재시도는 이미 끝났음 | 마지막 스냅샷을 stale로 표시 | 사용자 주도 retry action | terminal 1회, attempts |
| resume cursor로 메울 수 없는 공백 감지 | REALTIME_RESUME_GAP |
no | 권위 데이터 refetch 권고 | 공백 사실 표시 + 새로고침 action | gap 감지 방식 only |
인바운드 프레임이 eventSchema 위반 |
EVENT_SCHEMA_MISMATCH |
no | 해당 프레임만 드롭, 연결 유지 | 무음 (반복 시 저하 고지) | operation ID + issue path count |
| 알림 권한 거부 | PUSH_PERMISSION_DENIED |
no | push 없이 계속 | 재요청 반복 금지, 설정 안내 1회 | 결과 enum only |
| push 구독 만료 | PUSH_SUBSCRIPTION_EXPIRED |
재구독 1회 | 재구독 실패 시 push 비활성 | 무음, 필요 시 재활성 action | 결과 enum only, endpoint 금지 |
| Worker 생성 불가 | WORKER_UNAVAILABLE |
no | 메인 스레드 대체 경로 또는 기능 저하 | 무음 또는 느려짐 고지 | reason enum only |
| worker task timeout 후 terminate | WORKER_TASK_TIMEOUT |
no | worker 종료 후 재생성 | 작업 실패 + retry action | duration bucket + task 이름 |
| service worker 등록/갱신 실패 | SW_REGISTRATION_FAILED |
no | SW 없이 계속 — 제품 흐름 차단 금지 | 무음, 관련 기능만 저하 고지 | phase + reason enum |
| Background Sync API 미지원 | BACKGROUND_SYNC_UNSUPPORTED |
no | 온라인 복귀 시 전면 재시도로 대체 | 지연 전송 불가 고지 | 결과 enum only |
idempotency: keyed가 아닌 mutation의 재생 시도 |
BACKGROUND_SYNC_REPLAY_REJECTED |
no | 큐에서 제거, 재생하지 않음 | contact-support — 중복 write 방지가 우선 | operation ID + 거부 사유 |
| unknown thrown value | UNKNOWN_FAILURE |
no | nearest safe boundary | generic reference | type allowlist only |
Normalization은 total function이어야 한다. response/adapter/browser exception이 위 named branch와 일치하지 않거나 mapper 자체가 실패하면 최종 catch-all이 raw value를 폐기하고 UNKNOWN_FAILURE를 반환한다. normalized failure를 만들지 못한 채 throw를 presentation으로 통과시키는 경로는 허용하지 않는다.
8.3 Retry decision order
if aborted by navigation/user/superseded -> do not retry
else if parse/envelope/schema/auth/authz/not-found/conflict/validation -> do not retry
else if method is safe -> apply status/network policy
else if idempotency mode is keyed and backend contract is active -> apply status/network policy
else -> do not retry
Backend error.retryable=true는 necessary hint일 수 있지만 frontend가 unsafe mutation을 자동 retry할 충분 조건은 아니다. method/idempotency/client cap을 함께 만족해야 한다.
8.4 UX action vocabulary
| Action | When allowed | MUST NOT do |
|---|---|---|
retry |
terminal retryable failure | infinite spinner 또는 hidden loop |
reauth |
AUTH_REQUIRED + external owner available |
token lifecycle 직접 구현 |
navigate |
not-found/forbidden route recovery | history loop |
reload-once |
confirmed chunk/deploy mismatch | session guard 없이 반복 reload |
contact-support |
schema/internal repeated failure | raw stack/body 노출 |
none |
abort, telemetry-only degradation | user에게 false error 표시 |
8.5 Required negative fixtures
| Fixture | Expected normalized result |
|---|---|
JSON operation + text/html response |
CONTENT_TYPE_MISMATCH |
| auth attach callback throw/reject | AUTH_INTEGRATION_FAILURE |
| bounded recovery invalid state | AUTH_INTEGRATION_FAILURE |
| release manifest network/parse/schema failure | RELEASE_MANIFEST_FAILURE |
| QueryCachePort adapter throw 또는 invalid cache result | QUERY_CACHE_FAILURE |
unregistered 418 or other unmapped 4xx |
UNKNOWN_CLIENT_FAILURE |
thrown non-Error object, symbol, or mapper exception |
UNKNOWN_FAILURE |
| recovery succeeds for unkeyed mutation | no replay; terminal action requires explicit user retry |
9. Async UI, Query Cache, Routing, Storage
9.1 Async surface state model
Required visible states:
| State | Data | Activity | UI requirement |
|---|---|---|---|
initial-loading |
none | first request | stable skeleton, focus theft 금지 |
success |
present | idle | view-model render |
empty |
valid empty | idle | empty reason + primary action if applicable |
terminal-error |
none or unusable | stopped | safe message + registry action |
Additional non-blocking states:
| State | Data | Activity | UI requirement |
|---|---|---|---|
refreshing |
stale/present | background | existing content 유지, subtle indicator |
stale-degraded |
cached | retry exhausted | stale label + manual retry |
mutation-pending |
current view | write in flight | duplicate action 차단 |
mutation-conflict |
authoritative refetch needed | stopped | conflict action |
loading boolean 하나로 empty/error/refreshing을 합치면 contract violation이다.
9.2 Query cache defaults
Application use case는 QueryCachePort만 호출한다. bootstrap/composition-root.js가 adapters/query-cache의 TanStack Query implementation을 생성해 application facade에 주입하며, presentation과 application은 TanStack Query client를 직접 import하지 않는다.
Initial defaults, all planned:
| Area | Default | Exception trigger |
|---|---|---|
| query key | registry factory | none |
| stale time | 30s for sample read | operation owner measurement |
| garbage collection | 5m | memory profile evidence |
| refetch on focus | enabled for stale query | high-cost operation owner opt-out |
| retry | API policy callback | no page-local number |
| mutation retry | off unless keyed | explicit backend idempotency contract |
| cache persistence | off | offline requirement + storage threat model |
| invalidation | mutation result → registry namespace | broad invalidateQueries() without reason 금지 |
Cache data가 release/config/API schema version과 incompatible하면 reuse하지 않고 discard한다. cache migration을 선택하면 compatibility branch가 fixture와 rollback을 소유한다.
9.3 Route behavior
- route param과 search param은 application 호출 전에 runtime validation한다.
- unknown route는 API request 없이 not-found surface로 간다.
- session-required route는
AuthSessionPortstate를 UX hint로 사용한다. - backend authorization result가 최종 권한 판단이다.
- route-level lazy chunk는 release manifest의 chunk ID와 연결한다.
- route error element와 React error boundary의 owner를 중복하지 않는다.
- redirect는 최대 hop count를 test해 loop를 차단한다.
9.4 Storage behavior
- Web Storage 접근은
StoragePortadapter 안에서 try/catch한다. - unavailable, security exception, quota exceeded를 구분한다.
- allowed cache eviction 순서를 registry에 기록한다.
- user preference write 실패는 product flow를 중단하지 않고 memory fallback을 사용한다.
- mutation/idempotency record처럼 correctness에 영향을 주는 값은 storage fallback을 임의 적용하지 않는다.
- token, secret, raw API response, error body, PII는 default registry에 등록할 수 없다.
9.5 실시간 surface state
§9.1의 4-state 모델은 요청/응답 전용이라 스트림에 그대로 맞지 않는다. 아래 표가 실시간 구독의 상태이며 §9.1과 충돌하지 않도록 대응을 명시한다.
| State | 의미 | §9.1 대응 | UI requirement |
|---|---|---|---|
connecting |
최초 연결 시도 중, 수신 이벤트 0 | initial-loading |
안정 skeleton, focus 탈취 금지 |
live |
연결 유지, 이벤트 수신 중 | success |
최신 상태 표시 |
reconnecting |
끊김 후 backoff 재시도 중, 마지막 데이터 유지 | refreshing |
기존 내용 유지 + 은은한 표시 |
resumed-with-gap |
재연결했으나 resume cursor로 메운 구간에 공백 존재 | stale-degraded |
공백 사실 표시 + 수동 새로고침 |
disconnected |
재시도 상한 소진, terminal | terminal-error |
안전한 메시지 + registry action |
reconnecting을 terminal-error로 표시하면 사용자가 불필요하게 새로고침하고, disconnected를 refreshing으로 표시하면 영원히 오지 않는 데이터를 기다린다. 이 구분이 이 표의 존재 이유다.
9.6 전송 진행 surface state
| State | 의미 | §9.1 대응 | UI requirement |
|---|---|---|---|
transfer-preparing |
presign 획득·part 분할 중 | initial-loading |
취소 가능 표시 |
transfer-active |
byte 전송 중 | mutation-pending |
진행률 + 취소, 중복 시작 차단 |
transfer-paused |
사용자 중단 또는 네트워크 중단, 재개 가능 | stale-degraded |
재개 action |
transfer-failed |
재시도 소진 또는 무결성 불일치 | terminal-error |
registry action, part 상태 폐기 여부 명시 |
transfer-completed |
완료 및 검증됨 | success |
결과 표시 |
진행률 telemetry에는 원본 크기·파일명을 남기지 않고 size_bucket·duration_bucket만 남긴다(§5.8).
9.7 Service Worker 갱신 surface state
| State | 의미 | UI requirement |
|---|---|---|
sw-none |
등록 없음(기본) | 표시 없음 |
sw-active |
현재 release의 SW 활성 | 표시 없음 |
sw-update-pending |
새 SW가 설치됐고 활성화 대기 | 사용자 주도 적용 action. 자동 skipWaiting 금지 — 열린 탭이 release를 갈아타면 FE-OC-016 coherence가 깨진다 |
sw-update-failed |
등록·갱신 실패 | SW_REGISTRATION_FAILED, 기능 저하만, 제품 흐름 차단 금지 |
10. Rendering, Accessibility, and User Safety
10.1 Error boundary ownership
| Boundary | Catches | Does not catch | Recovery |
|---|---|---|---|
| boot shell | config/release/bootstrap failure | product route errors | config refetch, support, rollback signal |
| route boundary | lazy chunk/render failure for route | expected API result | route retry or controlled reload |
| feature boundary | component subtree render defect | normalized operational failure | component reset |
| async boundary | normalized query/mutation state | thrown render defect | registry action |
Operational failures는 normal state로 반환하고 render boundary에 throw하지 않는 것이 default다. programmer defect 또는 invariant breach만 render boundary가 잡는다.
10.2 Reload loop prevention
Controlled reload conditions:
- failure kind가
CHUNK_LOAD_FAILURE또는DEPLOY_MISMATCH - release manifest fetch 성공
- active release가 current build와 다름
CHUNK_RELOAD_GUARD가 current release pair에 대해 unset- guard를 먼저 기록한 후 reload
같은 release pair에서 두 번째 failure가 나면 auto reload를 중단하고 rollback/support surface를 보여준다.
10.3 Accessibility baseline
Planned requirements:
- keyboard로 모든 interactive action 접근
- visible focus indicator
- route change 후 deterministic focus target
- loading state의 적절한 live region, 반복 announcement 억제
- error message와 action의 programmatic association
- color만으로 state를 구분하지 않음
- modal focus trap과 restore
- axe critical/serious violation 0을 blocking default로 사용
- reduced-motion preference 존중
WCAG 적합성 자체는 실제 audit 없이 주장하지 않는다. automated axe 통과는 manual keyboard/screen-reader review를 대체하지 않는다.
11. Telemetry and Observability Contract
11.1 Required context
Allowed low-cardinality context:
app_version
build_id
release_id
config_schema_version
api_contract_version
route_id
operation_id
error_kind
http_status_group
attempt_count_bucket
duration_bucket
component_boundary
active_release_id
mismatch_kind
reason
queue_size_bucket
이 목록은 exhaustive default-deny allowlist다. §5.8 initial planned events의 requiredAttributes는 전부 이 목록 안에 있어야 하며, 새 event 나 attribute 를 등록할 때 이 목록과 §5.8 을 함께 갱신한다. 목록 밖 attribute 는 transport boundary 에서 제거된다.
Forbidden:
access_token
refresh_token
authorization_header
cookie
email
user_name
raw_user_id
raw_url
query_string
request_body
response_body
storage_value
stack_in_user_message
11.2 Delivery behavior
- telemetry send는 user request critical path를 block하지 않는다.
- queue는 bounded여야 하며 overflow 시 oldest-drop 또는 newest-drop 정책을 registry에 명시한다.
- telemetry failure를 telemetry로 재귀 전송하지 않는다.
- page hide 시
sendBeacon사용 여부는 adapter decision이며 delivery guarantee로 표현하지 않는다. - local/dev는 console-safe sink를 허용한다.
- production endpoint가 없거나 invalid하면 telemetry만 degrade하고 app은 계속 실행한다.
- security/audit delivery가 필요하면 best-effort product telemetry와 별도 contract를 만든다.
11.3 Trace correlation
- W3C
traceparent가 외부 auth/backend contract에서 허용되면 전파한다. - browser가 받은
requestId/traceId는 safe support reference로 내부 state에 보관할 수 있다. - raw trace header를 user에게 노출하지 않는다.
- new request retry는 같은 logical operation correlation을 유지하되 attempt를 구분한다.
- trace propagation 미지원 backend에서는 local operation ID로 degrade한다.
12. Release, Cache, Version, and Rollback Contract
12.1 Artifact set
한 release는 최소 다음 artifact를 가진다.
dist/index.html
dist/assets/<content-hash>.*
dist/config.json
dist/release-manifest.json
dist/config/runtime-config.schema.json
artifacts/release/build-manifest.json
artifacts/release/dependency-inventory.*
artifacts/release/checksums.txt
실제 path는 repository가 생기면 owner branch에서 확정한다. 현재는 expected artifact contract다.
12.2 Cache policy
| Surface | Default cache policy | Reason |
|---|---|---|
| hashed JS/CSS/font/image | long-lived immutable | content hash identity |
index.html |
no-cache / revalidate |
active entry point 교체 |
/config.json |
no-store 또는 URL에 explicit version |
deploy-specific public config |
release-manifest.json |
no-store or immediate revalidate |
mismatch detection |
| source map | public hosting disabled; secured artifact store | stack/source exposure boundary |
| service worker | default off | stale release complexity |
Header syntax은 hosting provider 확정 후 adapter runbook에 기록한다. 현재 문서는 policy만 소유한다.
12.3 Compatibility tuple
Frontend boot compatibility는 다음 tuple로 판정한다.
(buildId, configSchemaVersion, apiContractVersion, assetManifestHash, releaseId)
Rules:
- config schema major incompatibility → boot fail
- API contract incompatible → product route mount fail 또는 explicitly supported compatibility adapter
- asset manifest mismatch → controlled reload once
- release ID mismatch but all versions compatible → warning telemetry 후 continue 가능
- string lexical compare로 version compatibility를 판정하지 않음
12.4 Atomic deploy expectation
Preferred order:
- immutable asset upload
- release manifest upload
- runtime config upload
- asset reachability smoke
- active HTML pointer switch
- post-switch boot/e2e smoke
Provider가 이 order를 지원하지 않으면 equivalent atomic primitive와 rollback semantics를 decision row에 기록한다.
12.5 Rollback invariant
Rollback target MUST include a coherent set of:
- prior HTML
- prior asset manifest and assets
- compatible runtime config
- compatible API contract or backend compatibility window
- release manifest
HTML만 과거로 돌리고 runtime config를 최신에 남기는 rollback은 금지한다. cache purge가 필요한 provider라면 purge 완료가 아니라 실제 old/new reachability probe 결과로 recovery를 판정한다.
13. Supply-chain and Security Boundaries
13.1 Supply-chain minimums
| Control | Planned default | Blocking condition | Evidence artifact |
|---|---|---|---|
| package manager | pnpm + committed lockfile | lockfile drift | artifacts/quality/lockfile-check.txt |
| install | frozen lockfile | dependency resolution mutation | install log |
| dependency review | direct/transitive diff | unreviewed high-risk change | dependency diff report |
| vulnerability scan | severity policy owner branch | threshold violation without approved expiry | SARIF/JSON report |
| secret scan | source + built asset scan | credential pattern hit | scan report |
| license inventory | dependency license list | denied/unknown license unresolved | inventory |
| SBOM/inventory | tool selected by owner | missing release inventory | CycloneDX/SPDX or equivalent |
| provenance | CI build metadata | buildId/commit mismatch | build manifest |
Scanner name과 severity threshold는 repository/organization policy가 없어 현재 deferred다. 특정 도구를 사용했다고 주장하지 않는다.
13.2 Browser security boundary
- browser bundle은 public artifact로 간주한다.
- secret을 obfuscation으로 보호할 수 있다고 가정하지 않는다.
dangerouslySetInnerHTML은 default prohibited import/API rule 대상이다.- unavoidable HTML rendering은 sanitizer owner, allowlist, malicious fixture, CSP interaction evidence가 필요하다.
eval, dynamic code execution, untrusted script URL은 금지 default다.- CSP, HSTS, frame policy, referrer policy는 hosting/backend header owner와 frontend compatibility test가 공동 책임이다.
- CORS는 backend/browser enforcement이며 frontend에서 wildcard로 해결할 수 있다고 말하지 않는다.
- route guard는 authorization control이 아니다.
- client validation은 backend validation을 대체하지 않는다.
- source map은 production public path에 기본 배포하지 않는다.
13.3 Dependency update policy
- security update bot 선택은
deferred다. - update PR은 lockfile, unit/component/integration/e2e, build, bundle, security gate를 통과해야 한다.
- major update는
FE-D*impact check와 registry compatibility check를 요구한다. - suppression은 reason, owner, expiry, affected package, compensating control을 가진다.
- expiry가 지난 suppression은 gate failure다.
14. Measurable Non-functional Requirements
14.1 Measurement contexts
수치는 context와 함께만 판정한다.
| Context ID | Device/runtime | Network/cache | Route/data | Purpose |
|---|---|---|---|---|
FE-NFR-C01 |
Playwright Chromium, CI runner spec recorded | cold browser cache, throttling profile recorded | app shell + sample list fixture | repeatable lab baseline |
FE-NFR-C02 |
desktop Chromium/Firefox/WebKit matrix | normal CI network, mocked API | sample critical flow | functional compatibility |
FE-NFR-C03 |
production browser field data | real network, 28-day window | top route IDs | future field SLO; current unavailable |
FE-NFR-C04 |
build runner image + Node/pnpm versions recorded | N/A | production build | bundle reproducibility |
CI runner CPU와 throttling 값이 확정되지 않았으므로 command를 실행할 때 report metadata에 실제 값을 기록한다. context가 없는 숫자는 evidence로 인정하지 않는다.
14.2 Initial target matrix
| NFR ID | Metric | Context | Initial target | Current evidence |
|---|---|---|---|---|
FE-NFR-001 |
initial JS gzip | FE-NFR-C04 |
≤ 200 KiB | none |
FE-NFR-002 |
any lazy route chunk gzip | FE-NFR-C04 |
≤ 120 KiB | none |
FE-NFR-003 |
LCP lab | FE-NFR-C01 |
≤ 2.5s | none |
FE-NFR-004 |
CLS lab | FE-NFR-C01 |
≤ 0.10 | none |
FE-NFR-005 |
interaction latency lab | FE-NFR-C01 |
≤ 200ms for named interaction | none |
FE-NFR-006 |
boot config validation | deterministic mocked fetch | ≤ 500ms excluding network delay | none |
FE-NFR-007 |
API request total timeout | shared client | 10s default | none |
FE-NFR-008 |
automatic retry count | deterministic fake clock | ≤ 2 after initial | none |
FE-NFR-009 |
axe critical/serious | sample routes | 0 violations | none |
FE-NFR-010 |
telemetry blocking time | sink-failure fixture | product action not blocked | none |
FE-NFR-011 |
auth redirect loop | route graph test | navigation attempt당 automatic auth redirect ≤ 1, 동일 source→target pair 반복 0 | none |
FE-NFR-012 |
controlled reload | mismatch fixture | at most 1 per release pair/session | none |
FE-NFR-013 |
LCP field p75 | FE-NFR-C03 |
≤ 2.5s | none |
FE-NFR-014 |
CLS field p75 | FE-NFR-C03 |
≤ 0.10 | none |
FE-NFR-015 |
INP field p75 | FE-NFR-C03 |
≤ 200ms | none |
FE-NFR-016 |
realtime reconnect backoff cap | 결정론 fake clock | 재연결 간격 ≤ 30s, 재시도 상한 후 terminal 전이 | none |
FE-NFR-017 |
subscription leak | unmount fixture | unmount 후 열린 구독/연결 0 | none |
FE-NFR-018 |
upload part 재시도 | 결정론 fake clock | part당 재시도 ≤ 2 (FE-D015 상속), 전체 전송은 취소 가능 |
none |
FE-NFR-019 |
worker task timeout | worker fixture | 기본 30s 초과 시 terminate되고 결과를 기다리지 않음 | none |
FE-NFR-020 |
capability OFF 시 번들 증가 | FE-NFR-C04 |
6개 capability 전부 OFF일 때 initial JS gzip 증가 0 KiB | none |
Field Web Vitals는 consent/privacy boundary, route-ID aggregation, 28-day window, production release ID를 함께 기록해야 한다. minimum eligible sample threshold는 telemetry baseline을 얻은 뒤 owner가 확정할 deferred decision이므로, 그 전에는 FE-GATE-018을 PASS로 올릴 수 없다. lab result를 production percentile로 표현하지 않는다.
FE-NFR-020은 FE-NFR-001(initial JS gzip ≤ 200 KiB) 예산을 신규 capability가 잠식하지 않음을 수치로 방어하는 항목이다. capability를 켜면 번들이 늘어나는 것은 정상이며, 이 NFR이 막는 것은 끄고도 늘어나는 경우다.
14.3 Planned commands and expected assertions
아래 command는 repository가 생긴 뒤 package script로 제공할 contract다. 이 검토에서 실행되지 않았다.
| Command | Status | Expected assertion | Planned artifact |
|---|---|---|---|
pnpm install --frozen-lockfile |
PLANNED_NOT_EXECUTED |
manifest와 lockfile drift 없음 | artifacts/quality/install.txt |
pnpm lint |
PLANNED_NOT_EXECUTED |
lint error 0, forbidden imports 0 | artifacts/quality/lint.txt |
pnpm check:types |
PLANNED_NOT_EXECUTED |
checkJs diagnostic 0 |
artifacts/quality/check-types.txt |
pnpm test:runtime-schema |
PLANNED_NOT_EXECUTED |
invalid fixtures 전부 reject | artifacts/tests/runtime-schema.xml |
pnpm test:unit |
PLANNED_NOT_EXECUTED |
unit suite exit 0 | artifacts/tests/unit.xml |
pnpm test:component |
PLANNED_NOT_EXECUTED |
async/error/a11y component fixtures exit 0 | artifacts/tests/component.xml |
pnpm test:integration |
PLANNED_NOT_EXECUTED |
MSW API/failure matrix exit 0 | artifacts/tests/integration.xml |
pnpm test:e2e |
PLANNED_NOT_EXECUTED |
critical flows browser matrix exit 0 | artifacts/tests/e2e/ |
pnpm test:a11y |
PLANNED_NOT_EXECUTED |
critical/serious axe finding 0 | artifacts/tests/a11y.json |
pnpm review:a11y-manual |
PLANNED_NOT_EXECUTED |
sample route 별 keyboard/focus manual checklist 서명 완료 | artifacts/tests/a11y-manual/<route>.md |
pnpm build |
PLANNED_NOT_EXECUTED |
production build exit 0 + manifest present | artifacts/release/build-manifest.json |
pnpm check:bundle |
PLANNED_NOT_EXECUTED |
FE-NFR-001, FE-NFR-002 threshold 만족 |
artifacts/performance/bundle.json |
pnpm test:performance |
PLANNED_NOT_EXECUTED |
FE-NFR-003, FE-NFR-004, FE-NFR-005 context metadata + threshold result |
artifacts/performance/lab.json |
pnpm scan:security |
PLANNED_NOT_EXECUTED |
policy threshold 위반 없음 | artifacts/security/scan.sarif |
pnpm verify:release |
PLANNED_NOT_EXECUTED |
compatibility tuple coherent | artifacts/release/verification.json |
pnpm collect:web-vitals-evidence |
PLANNED_NOT_EXECUTED |
28-day context + p75 + eligible sample metadata 기록 | artifacts/performance/field-web-vitals.json |
pnpm verify:hosting-headers |
PLANNED_NOT_EXECUTED |
HTML/config/manifest/hashed-asset header policy 일치 + 선언된 security header 집합 일치 | artifacts/release/hosting-headers.json |
pnpm test:sample-removal |
PLANNED_NOT_EXECUTED |
sample subtree 제거 후 production build/smoke 성공 | artifacts/tests/sample-removal.xml |
pnpm drill:runbook -- FE-RB-001 |
PLANNED_NOT_EXECUTED |
boot config containment/recovery assertions 통과 | artifacts/runbooks/FE-RB-001/<release-id>/record.json |
pnpm drill:runbook -- FE-RB-002 |
PLANNED_NOT_EXECUTED |
chunk mismatch와 RELEASE_MANIFEST_FAILURE containment/recovery assertions 통과 |
artifacts/runbooks/FE-RB-002/<release-id>/record.json |
pnpm drill:runbook -- FE-RB-003 |
PLANNED_NOT_EXECUTED |
API degradation containment/recovery assertions 통과 | artifacts/runbooks/FE-RB-003/<release-id>/record.json |
pnpm drill:runbook -- FE-RB-004 |
PLANNED_NOT_EXECUTED |
telemetry degradation containment/recovery assertions 통과 | artifacts/runbooks/FE-RB-004/<release-id>/record.json |
pnpm drill:runbook -- FE-RB-005 |
PLANNED_NOT_EXECUTED |
rollback decision/recovery assertions 통과 | artifacts/runbooks/FE-RB-005/<release-id>/record.json |
Script 이름을 바꾸는 것은 허용되지만 acceptance gate와 artifact mapping을 동시에 갱신해야 한다.
15. Acceptance Gate Matrix
15.1 Gate ownership
현재 stable gate registry는 33개 row이며, 새 gate를 추가하거나 supersede할 때 이 수와 promotion formula를 함께 갱신한다.
FE-GATE-027~FE-GATE-032는 capability-scoped gate다. 대응 capability가 비활성이면 NOT_APPLICABLE을 취할 수 있으나, 그 상태는 FE-GATE-033이 PASS일 때만 유효하다(§18.1).
이 표가 gate 의 정의다.
Covered FE-OC열은 gate 와 계약의 대응 관계이지 계약 내용의 사본이 아니다. branch 는 이 표를 옮겨 적지 않는다 — gate ID 를 행 키로 쓰고 자기 control 만 적는다(예: raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract).
| Gate ID | Gate | Blocking scope | Covered FE-OC | Covered FE-NFR | Required fixtures | Pass condition | Evidence artifact | Current |
|---|---|---|---|---|---|---|---|---|
FE-GATE-001 |
manifest/lockfile | merge + release | FE-OC-003, FE-OC-018, FE-OC-020 |
— | lockfile drift | frozen install exit 0 | install log | FAIL_UNVERIFIED |
FE-GATE-002 |
lint | merge | FE-OC-002, FE-OC-003, FE-OC-019, FE-OC-020 |
— | forbidden API/import | error 0 | lint report | FAIL_UNVERIFIED |
FE-GATE-003 |
typecheck-equivalent | merge | FE-OC-002, FE-OC-003, FE-OC-007, FE-OC-020 |
— | JSDoc/checkJs negative fixture | production diagnostic 0; fixture fails as expected | check-types report | FAIL_UNVERIFIED |
FE-GATE-004 |
runtime schema | merge | FE-OC-004, FE-OC-006, FE-OC-007, FE-OC-008, FE-OC-023 |
FE-NFR-006 |
content-type/JSON/envelope/payload/config invalid matrix + deterministic valid-config timing fixture | every invalid fixture rejected with expected kind; valid boot config validation ≤ 500ms excluding mocked network delay | schema + timing report | FAIL_UNVERIFIED |
FE-GATE-005 |
unit | merge | FE-OC-006, FE-OC-009, FE-OC-012, FE-OC-013, FE-OC-014, FE-OC-022 |
FE-NFR-007, FE-NFR-008, FE-NFR-010 |
retry clock, mapper, all registries | exit 0 | unit XML | FAIL_UNVERIFIED |
FE-GATE-006 |
component | merge | FE-OC-005, FE-OC-011, FE-OC-015, FE-OC-019, FE-OC-024 |
FE-NFR-009 |
async states, render boundary, keyboard | exit 0 | component XML | FAIL_UNVERIFIED |
FE-GATE-007 |
integration | merge | FE-OC-006, FE-OC-007, FE-OC-008, FE-OC-009, FE-OC-010, FE-OC-012 |
FE-NFR-007, FE-NFR-008 |
MSW status/failure/auth-recovery taxonomy | all matrix and negative-fixture rows covered | integration XML | FAIL_UNVERIFIED |
FE-GATE-008 |
e2e | merge + release | FE-OC-004, FE-OC-005, FE-OC-009, FE-OC-010, FE-OC-011, FE-OC-015, FE-OC-016, FE-OC-024 |
FE-NFR-011, FE-NFR-012 |
boot, route, mutation, chunk mismatch, repeated guarded-route redirect pair | critical scenarios exit 0; navigation attempt당 automatic auth redirect ≤ 1이고 동일 source→target pair가 반복되지 않음 | Playwright report | FAIL_UNVERIFIED |
FE-GATE-009 |
accessibility | merge + release | FE-OC-019, FE-OC-020, FE-OC-024 |
FE-NFR-009 |
axe + manual checklist | automated threshold + signed manual review | a11y artifacts | FAIL_UNVERIFIED |
FE-GATE-010 |
architecture | merge | FE-OC-002, FE-OC-020 |
— | forbidden import fixtures including direct TanStack client import | allowed passes, forbidden fails | dependency report | FAIL_UNVERIFIED |
FE-GATE-011 |
build | merge + release | FE-OC-003, FE-OC-016, FE-OC-018 |
— | clean production build | exit 0 + expected artifacts | build manifest | FAIL_UNVERIFIED |
FE-GATE-012 |
bundle | release | FE-OC-018, FE-OC-021 |
FE-NFR-001, FE-NFR-002 |
app + lazy chunks | NFR thresholds pass | bundle report | FAIL_UNVERIFIED |
FE-GATE-013 |
security | merge + release | FE-OC-018, FE-OC-019, FE-OC-020 |
— | secret/vulnerability/license/dependency-review fixtures | policy pass | SARIF/inventory/dependency diff report | FAIL_UNVERIFIED |
FE-GATE-014 |
config compatibility | release | FE-OC-004, FE-OC-023 |
— | old/new config versions | supported passes, incompatible fails boot | compatibility report | FAIL_UNVERIFIED |
FE-GATE-015 |
release coherence | release | FE-OC-016, FE-OC-017, FE-OC-023 |
FE-NFR-012 |
mixed HTML/assets/config | mismatch detected, coherent set passes | release verification | FAIL_UNVERIFIED |
FE-GATE-016 |
rollback drill | production promotion | FE-OC-017 |
FE-NFR-012 |
prior release pair | rollback + smoke evidence | drill record | FAIL_UNVERIFIED |
FE-GATE-017 |
scoped diagram review | documentation readiness | FE-OC-002, FE-OC-016 |
— | overview dependency view + static asset/runtime-config delivery slice | reviewer score threshold satisfied for both scoped diagrams | reviewer report | PASS_SCOPED |
FE-GATE-018 |
production field Web Vitals | field readiness | FE-OC-021 |
FE-NFR-013, FE-NFR-014, FE-NFR-015 |
eligible route samples over recorded 28-day window | p75 targets pass and deferred minimum sample threshold is resolved | field Web Vitals report | FAIL_UNVERIFIED |
FE-GATE-019 |
hosting header policy (cache + security) | release | FE-OC-016, FE-OC-019 |
— | HTML/config/manifest/hashed asset responses + 선언된 security header 집합 | declared Cache-Control/content-type/security-header policy matches actual hosting | hosting header report | FAIL_UNVERIFIED |
FE-GATE-020 |
sample removal | merge + release | FE-OC-024 |
— | sample subtree removed in dedicated fixture | production build and smoke pass with no product import | sample-removal report | FAIL_UNVERIFIED |
FE-GATE-021 |
FE-RB-001 drill |
production promotion | FE-OC-025 |
— | boot config failure | containment, escalation, recovery assertions pass | FE-RB-001 record |
FAIL_UNVERIFIED |
FE-GATE-022 |
FE-RB-002 drill |
production promotion | FE-OC-025 |
FE-NFR-012 |
chunk/release mismatch + release manifest fetch/parse/schema failure | CHUNK_LOAD_FAILURE와 RELEASE_MANIFEST_FAILURE containment, escalation, recovery assertions pass |
FE-RB-002 record |
FAIL_UNVERIFIED |
FE-GATE-023 |
FE-RB-003 drill |
production promotion | FE-OC-025 |
FE-NFR-007, FE-NFR-008 |
API degradation | containment, escalation, recovery assertions pass | FE-RB-003 record |
FAIL_UNVERIFIED |
FE-GATE-024 |
FE-RB-004 drill |
production promotion | FE-OC-025 |
FE-NFR-010 |
telemetry degradation | containment, escalation, recovery assertions pass | FE-RB-004 record |
FAIL_UNVERIFIED |
FE-GATE-025 |
FE-RB-005 drill |
production promotion | FE-OC-025 |
— | blocking release defect | rollback decision, escalation, recovery assertions pass | FE-RB-005 record |
FAIL_UNVERIFIED |
FE-GATE-026 |
lab performance | release | FE-OC-021 |
FE-NFR-003, FE-NFR-004, FE-NFR-005 |
recorded runner/throttling/cache context + named interactions | every lab threshold passes and report contains reproducibility metadata | lab performance report | FAIL_UNVERIFIED |
FE-GATE-027 |
binary I-O & local store | merge | FE-OC-013, FE-OC-027 |
— | picker 취소·거부, quota 초과 fallback, OPFS 순차 write, Cache Storage 버전 파티션, object URL 해제 | 모든 fixture가 기대 kind로 처리되고 object URL 누수 0 | binary I-O report | FAIL_UNVERIFIED |
FE-GATE-028 |
cache tier & cross-tab | merge | FE-OC-012, FE-OC-028 |
— | 영속 캐시 version 파티션, 탭 A mutation → 탭 B 무효화, BroadcastChannel 부재 fallback | 불일치 version 캐시는 복원되지 않고 탭 간 무효화가 도달 | cache tier report | FAIL_UNVERIFIED |
FE-GATE-029 |
large object transfer | merge + release | FE-OC-019, FE-OC-029 |
FE-NFR-018 |
presign 만료, part 재시도 상한, stream 중단 후 재개, 무결성 불일치, credential 첨부 negative | 모든 fixture 통과 + 전송 요청에 session credential 0건 | transfer report | FAIL_UNVERIFIED |
FE-GATE-030 |
multi-protocol transport | merge | FE-OC-006, FE-OC-007, FE-OC-030 |
— | GraphQL 200 + errors[], gRPC status ↔ HTTP status, codec decode 실패, gateway fallback |
모든 protocol 실패가 기대 kind로 정규화 | protocol mapping report | FAIL_UNVERIFIED |
FE-GATE-031 |
realtime lifecycle | merge + release | FE-OC-011, FE-OC-031 |
FE-NFR-016, FE-NFR-017 |
결정론 fake clock backoff, resume gap 감지, unmount 후 열린 연결(SUBSCRIPTION_LEAKED fixture), 이벤트 스키마 거부, FE-RB-006 drill |
backoff가 cap을 넘지 않고 unmount 후 열린 연결 0, 미검증 이벤트 0건 도달 | realtime lifecycle report | FAIL_UNVERIFIED |
FE-GATE-032 |
background execution | merge + release | FE-OC-016, FE-OC-017, FE-OC-032 |
FE-NFR-019 |
SW 등록·갱신 UX, rollback 시 SW 되돌림, background sync keyed-only, worker timeout·terminate, FE-RB-007 drill |
모든 fixture 통과 + keyed 아닌 mutation replay 0건 | background execution report | FAIL_UNVERIFIED |
FE-GATE-033 |
capability default-off | merge + release | FE-OC-004, FE-OC-022, FE-OC-027, FE-OC-028, FE-OC-029, FE-OC-030, FE-OC-031, FE-OC-032 |
FE-NFR-020 |
기본 config로 production build, 각 capability ON 조합 build | 비활성 capability의 adapter 모듈이 어떤 chunk에도 없고 initial JS 증가 0 | capability bundle report | FAIL_UNVERIFIED |
15.2 Negative fixture requirement
Gate가 실제로 동작한다고 말하려면 최소 하나의 deliberately failing fixture가 필요하다.
| Gate | Negative fixture example |
|---|---|
| architecture | presentation imports adapters/http |
| checkJs | application port called with wrong shape |
| runtime schema | success envelope without data |
| retry | POST without idempotency key receives 503 |
| storage | token key registration attempt |
| telemetry | event includes raw URL/query |
| release | HTML build A + asset manifest B |
| reload guard | second chunk failure in same release pair |
| lab performance | context metadata missing 또는 one named threshold exceeded |
| binary I-O | quota 초과인데 UPLOAD_PART_STATE가 memory로 fallback |
| cache tier | release/config version 불일치 캐시를 복원해 사용 |
| large object transfer | transfer 요청에 session credential 헤더가 첨부 |
| multi-protocol | 200 OK + errors[]를 success로 반환 |
| realtime lifecycle | unmount 후에도 구독이 살아 있음 / 미검증 프레임이 application 도달 |
| background execution | idempotency: none mutation이 background sync로 replay |
| capability default-off | flag OFF인데 adapter가 initial chunk에 포함 |
Negative fixture를 실행하지 않고 rule 존재만 확인한 결과는 locally-verified 증거로 부족하다.
15.3 Promotion rule
MERGE_READY = FE-GATE-001, FE-GATE-002, FE-GATE-003, FE-GATE-004, FE-GATE-005, FE-GATE-006,
FE-GATE-007, FE-GATE-008, FE-GATE-009, FE-GATE-010, FE-GATE-011, FE-GATE-013,
FE-GATE-020, FE-GATE-033 PASS
AND FE-GATE-027, FE-GATE-028, FE-GATE-030 각각 PASS 또는 유효한 NOT_APPLICABLE
RELEASE_READY = MERGE_READY AND FE-GATE-012, FE-GATE-014, FE-GATE-015, FE-GATE-019, FE-GATE-026 PASS
AND FE-GATE-029, FE-GATE-031, FE-GATE-032 각각 PASS 또는 유효한 NOT_APPLICABLE
PROD_PROMOTION_READY = RELEASE_READY AND FE-GATE-016, FE-GATE-021, FE-GATE-022, FE-GATE-023,
FE-GATE-024, FE-GATE-025 PASS
FIELD_SLO_READY = PROD_PROMOTION_READY AND FE-GATE-018 PASS
DOCUMENTATION_READY = FE-GATE-017 PASS_SCOPED AND evidence ledger updated
PROJECT_READY = all applicable blocking gates PASS
FE-GATE-033은 NOT_APPLICABLE을 취할 수 없으므로 항상 MERGE_READY에 무조건 포함된다. capability를 하나도 쓰지 않는 프로젝트도 "쓰지 않는다"를 증명해야 한다.
현재는 PROJECT_READY = false, 즉 NOT_READY다.
16. Operational Runbooks
Runbook은 provider-specific console command를 현재 발명하지 않는다. 공통 trigger, diagnosis evidence, mitigation invariant, recovery assertion을 고정하고 provider command는 release branch가 hosting 확정 후 채운다.
아래 시간·rate window는 모두 implementation/telemetry evidence가 없는 planned conditional default이며 measured SLO가 아니다. 각 runbook의 first drill 결과와 hosting/backend baseline이 생기면 owner가 유지·변경한다.
16.1 FE-RB-001 — Boot config failure
| Field | Planned contract |
|---|---|
| Primary owner | feature-frontend-operational-runbook-contract |
| Technical escalation | feature-frontend-env-runtime-config-contract → feature-frontend-release-cache-rollback-contract |
| Activation condition | initial boot config validation 실패 후 bounded refetch 1회도 실패 |
| Conditional window | detection 즉시 containment; owner triage 시작 목표 5분 |
| Evidence path | artifacts/runbooks/FE-RB-001/<release-id>/ |
Trigger
- boot shell에
BOOT_CONFIG_FAILURE - config fetch non-2xx, JSON parse failure, schema incompatibility
Immediate containment
- product routes mount를 중단한다.
- safe support reference와 build/config version만 표시한다.
- automatic refetch는 최대 1회로 제한한다.
Diagnosis evidence
- current
buildId,releaseId,configSchemaVersion - runtime config HTTP status와 content-type
- release manifest compatibility tuple
- config publish timestamp는 진단용이며 compatibility identity로 쓰지 않음
Mitigation options
- If config artifact만 잘못됨 → current build와 호환되는 config republish.
- If new config schema가 old build와 incompatible → coherent prior release rollback.
- If endpoint outage → provider restore 또는 approved build-time fallback release.
Escalation
- config owner가 schema/publish 원인을 분류하지 못하거나 coherent republish가 불가능하면 release owner에게 rollback decision을 넘긴다.
- auth/API/product owner에게는 boot이 성공한 뒤 별도 downstream failure가 확인될 때만 확대한다.
Recovery assertions
- clean session boot 성공
- product root mount
- config validation artifact pass
- repeated boot error telemetry 없음
Evidence
artifacts/runbooks/FE-RB-001/<release-id>/ planned.
16.2 FE-RB-002 — Chunk load / release manifest / deploy mismatch
| Field | Planned contract |
|---|---|
| Primary owner | feature-frontend-operational-runbook-contract |
| Technical escalation | feature-frontend-release-cache-rollback-contract → hosting/CDN owner |
| Activation condition | RELEASE_MANIFEST_FAILURE, chunk failure 후 manifest mismatch·unreachable asset 확인, 또는 controlled reload 1회 실패 |
| Conditional window | detection 즉시 reload guard; release owner triage 시작 목표 5분 |
| Evidence path | artifacts/runbooks/FE-RB-002/<release-id>/ |
Trigger
CHUNK_LOAD_FAILURERELEASE_MANIFEST_FAILURE- asset 404 or integrity mismatch
- release manifest fetch/parse/schema validation failure
- release manifest active ID differs from loaded build
Immediate containment
- current user input이 있으면 destructive reload 전에 경고한다.
- release manifest를
no-store로 한 번 조회한다. - manifest fetch/parse/schema가 실패하면 release mismatch를 추정해 reload하지 않고 update/support shell로 격리한다.
- manifest가 valid하고 active release mismatch가 확인된 경우에만 reload guard를 먼저 기록하고 한 번만 reload한다.
Diagnosis evidence
- loaded build ID
- active release ID
- release manifest fetch status, content-type, parse/schema validation outcome; raw manifest 제외
- requested chunk ID, raw URL 제외
- asset manifest hash
- HTML/config/asset cache headers
Mitigation options
- If active release가 새 버전이고 assets reachable → one reload.
- If asset set incomplete → active pointer를 prior coherent release로 rollback.
- If release manifest artifact가 missing/malformed/incompatible → coherent manifest를 republish하거나 prior coherent release로 rollback.
- If CDN propagation 중 → active switch를 되돌리고 reachability probe 재실행.
Escalation
- asset set incomplete 또는 active pointer incoherent이면 release owner가 rollback 여부를 결정한다.
- origin은 정상이나 edge가 불일치하면 hosting/CDN owner에게 header·propagation evidence와 함께 넘긴다.
Recovery assertions
- entry와 lazy route asset 모두 2xx
- release manifest fetch·parse·schema validation과 release tuple coherence pass
- second auto reload 없음
- release coherence gate pass
- route e2e pass
Evidence
artifacts/runbooks/FE-RB-002/<release-id>/ planned.
16.3 FE-RB-003 — Backend API degradation
| Field | Planned contract |
|---|---|
| Primary owner | feature-frontend-operational-runbook-contract |
| Technical escalation | feature-api-client-response-envelope-contract → backend operation owner → release compatibility owner |
| Activation condition | terminal network/timeout/429/5xx rate가 configured threshold를 rolling 5분 동안 초과하거나 schema mismatch 1건 발생 |
| Conditional window | rate threshold 값은 baseline 후 확정; 최초 분류 목표 10분 |
| Evidence path | artifacts/runbooks/FE-RB-003/<release-id>/ |
Trigger
- network/timeout/502/503/504 terminal rate 증가
429지속- schema/envelope mismatch 발생
Triage split
| Signal | Likely class | First action |
|---|---|---|
| network across all operations | network/CORS/DNS/provider | browser + backend reachability 확인 |
| 429 only | capacity/rate policy | Retry-After와 request burst 확인 |
| 5xx only | backend failure | requestId/traceId로 backend owner 전달 |
| schema mismatch after release | compatibility | frontend/backend release tuple 확인 |
| one operation only | endpoint contract | operation ID fixture 대조 |
Containment
- retry cap을 runtime에서 임의 확대하지 않는다.
- safe cached data가 있으면 stale-degraded로 제공한다.
- mutation은 idempotency contract 없이는 재시도하지 않는다.
- schema mismatch는 retry하지 않고 compatibility rollback을 검토한다.
Escalation
- network/429/5xx는
operationId, request/trace reference, attempt count를 backend operation owner에게 넘긴다. - release 직후 schema mismatch면 frontend/backend release owners가 tuple을 대조하고 어느 쪽을 rollback할지 공동 결정한다.
Recovery assertions
- terminal failure rate가 baseline window로 복귀
- retry amplification 없음
- sample critical read/write e2e pass
- schema fixtures pass
Evidence
artifacts/runbooks/FE-RB-003/<release-id>/ planned.
16.4 FE-RB-004 — Telemetry sink failure
| Field | Planned contract |
|---|---|
| Primary owner | feature-frontend-operational-runbook-contract |
| Technical escalation | feature-frontend-observability-logging-trace-contract → telemetry platform owner |
| Activation condition | adapter init 실패 또는 sink failure/queue overflow가 rolling 5분 window에서 발생 |
| Conditional window | product flow 즉시 격리; platform triage 시작 목표 15분 |
| Evidence path | artifacts/runbooks/FE-RB-004/<release-id>/ |
Trigger
- sink non-2xx/network failure
- queue overflow/drop counter 증가
- telemetry adapter initialization failure
Containment
- product flow를 계속 수행한다.
- bounded queue 이상 적재하지 않는다.
- telemetry failure를 동일 sink로 재귀 보고하지 않는다.
- console fallback은 safe fields에 한정한다.
Diagnosis evidence
- endpoint classification, raw endpoint 제외
- queue size bucket
- dropped event count
- build/release ID
- redaction test result
Mitigation
- sink restore
- telemetry runtime flag disable
- queue policy 조정은 owner decision + memory test 후만
Escalation
- client redaction/queue defect면 observability owner가 우선 수정한다.
- client contract가 정상이고 sink/ingest가 실패하면 safe endpoint classification과 drop counters만 telemetry platform owner에게 전달한다.
Recovery assertions
- product e2e unaffected
- delivery self-check event 성공
- queue drains within planned bound
- forbidden attribute scan pass
Evidence
artifacts/runbooks/FE-RB-004/<release-id>/ planned.
16.5 FE-RB-005 — Release rollback
| Field | Planned contract |
|---|---|
| Primary owner | feature-frontend-operational-runbook-contract |
| Technical escalation | feature-frontend-release-cache-rollback-contract → release approver/hosting owner |
| Activation condition | release-blocking boot/chunk/render/API/security defect가 확인되고 forward fix가 incident window 안에 안전하다고 증명되지 않음 |
| Conditional window | blocking defect 확인 즉시 decision; provider-dependent recovery target은 hosting 확정 전 TBD |
| Evidence path | artifacts/runbooks/FE-RB-005/<release-id>/ |
Trigger
- boot/config incompatibility
- widespread chunk mismatch
- critical render/API compatibility defect
- security gate post-release finding
Preconditions
- prior immutable release exists
- prior runtime config and API compatibility known
- rollback actor and audit record owner identified
Procedure invariant
- target release tuple 선택
- prior assets reachability 확인
- prior runtime config compatibility 확인
- active pointer atomic switch
- provider-specific cache action 수행
- boot + route + API critical smoke
- telemetry/reload-loop 확인
- rollback record 저장
MUST NOT
- source rebuild를 rollback으로 부름
- HTML만 이전 버전으로 교체
- config/API compatibility 확인 없이 pointer 변경
- smoke 없이 incident close
Escalation
- release owner가 target tuple과 evidence를 준비하고 named release approver가 pointer switch를 승인한다.
- atomic switch나 cache invalidation이 provider primitive에서 실패하면 hosting owner에게 즉시 확대한다.
Recovery assertions
FE-GATE-014,FE-GATE-015pass- critical e2e pass
- no repeated
DEPLOY_MISMATCH - incident timeline에 release IDs 기록
Evidence
artifacts/runbooks/FE-RB-005/<release-id>/ planned.
17. Evidence Ledger
17.1 Evidence records
| Evidence ID | Artifact / observation | Grade | Supports | Does not prove |
|---|---|---|---|---|
FE-EV-001 |
본 project note | documented-only |
contract scope, IDs, defaults | code existence, test pass |
FE-EV-002 |
raw/project-notes/ca-skeleton-operational-contract | documented-only reference |
backend sibling의 operational contract pattern | frontend implementation |
FE-EV-003 |
raw/official-docs/vite-build-tool-official | source reference | Vite decision research | chosen config implemented |
FE-EV-004 |
raw/official-docs/react-ui-library-official | source reference | React decision research | component tree exists |
FE-EV-005 |
raw/official-docs/tailwind-css-utility-first-official | source reference | styling decision research | Tailwind configured |
FE-EV-006 |
raw/official-docs/tanstack-query-server-state-official | source reference | query state decision research | cache policy implemented |
FE-EV-007 |
raw/official-docs/zod-runtime-schema-validation-official | source reference | runtime validation decision research | schema/tests exist |
FE-EV-008 |
raw/official-docs/react-router-official | source reference | routing decision research | route registry exists |
FE-EV-009 |
§0.2의 exact rg --files + manifest/lock/Vite/src/main regex search |
observed read-only check | current wiki workspace에서 해당 entry artifact pattern 미발견 | 전체 source/test/CI/deploy 부재 또는 remote/other workspace 부재 |
FE-EV-010 |
overview draw.io + docs/superpowers/specs/2026-07-18-ca-skeleton-frontend-operational-contract-review/diagram-review.md |
documented-only, reviewer PASS 100/100 scoped |
Clean Architecture dependency ownership view가 §4.2~§4.4와 정합 | source code, import-rule 구현, runtime topology |
FE-EV-011 |
deployment draw.io + docs/superpowers/specs/2026-07-18-ca-skeleton-frontend-operational-contract-review/diagram-review.md |
documented-only, reviewer PASS 100/100 scoped |
static asset와 /config.json delivery slice가 declared boundary와 정합 |
§12 전체 release/rollback topology, 실제 hosting·deploy |
FE-EV-012 |
test/CI evidence | UNVERIFIED |
dedicated search/command가 기록되지 않았다는 경계 | artifact 부재 또는 gate pass/fail |
FE-EV-013 |
release/deploy evidence | UNVERIFIED |
dedicated search/command가 기록되지 않았다는 경계 | artifact 부재, rollback 또는 runtime behavior |
17.2 Evidence promotion protocol
To mark actually-implemented:
- repository URL/path
- commit SHA
- source path
- matching
FE-OC-*andFE-D*
To mark locally-verified:
- all above
- exact command
- tool/runtime version
- exit code
- machine-readable artifact path
- negative fixture result where applicable
To mark prod-verified:
- all above
- release ID
- environment
- measurement window
- dashboard/log/incident evidence
- rollback or recovery evidence where relevant
18. Binary Readiness Scorecard
18.1 Formula
PASS_STATES = {PASS, PASS_SCOPED}
NOT_APPLICABLE = capability-scoped gate 가, 대응 capability flag 가 OFF 이고
FE-GATE-033 이 그 adapter 의 번들 부재를 증명했을 때만 취할 수 있는 상태
READY iff every blocking row Current is in PASS_STATES or is a valid NOT_APPLICABLE
otherwise NOT_READY
PASS_SCOPED는 Blocking question과 Required evidence가 명시적으로 같은 제한 범위를 물을 때만 허용한다. 점수 평균으로 blocking failure를 상쇄하지 않는다.
NOT_APPLICABLE은 다음을 MUST 지킨다.
FE-GATE-027~FE-GATE-032만 취할 수 있다.FE-GATE-033자신은 취할 수 없다.FE-GATE-033이 PASS가 아니면 모든NOT_APPLICABLE은 무효이며FAIL_UNVERIFIED로 강등된다.- "안 쓴다"는 주장은 선언이 아니라 번들에 그 adapter가 없다는 증거로만 성립한다.
18.2 Current scorecard
| Readiness ID | Blocking question | Required evidence | Current | Reason |
|---|---|---|---|---|
FE-RDY-001 |
implementation repository가 식별됐는가 | repo URL/path + commit | FAIL |
entry artifact pattern 미발견; repo location은 UNVERIFIED |
FE-RDY-002 |
package manifest와 frozen lockfile이 있는가 | manifest + lockfile | FAIL |
evidence 없음 |
FE-RDY-003 |
architecture port ownership이 코드로 강제되는가 | dependency test | FAIL |
implementation evidence 없음 |
FE-RDY-004 |
overview dependency view가 reviewer gate를 통과했는가 | reviewer report | PASS_SCOPED |
reviewer 100/100; 구현 evidence와 별개 |
FE-RDY-005 |
deployment의 static asset/runtime-config delivery slice가 reviewer gate를 통과했는가 | reviewer report | PASS_SCOPED |
reviewer 100/100; §12 전체·실제 deploy mapping은 UNVERIFIED |
FE-RDY-006 |
runtime config boot gate가 검증됐는가 | schema + boot tests | FAIL |
test evidence UNVERIFIED |
FE-RDY-007 |
failure taxonomy가 test matrix로 강제되는가 | integration artifacts | FAIL |
test evidence UNVERIFIED |
FE-RDY-008 |
auth boundary가 token lifecycle을 침범하지 않는가 | port/import tests | FAIL |
implementation evidence 없음 |
FE-RDY-009 |
9 registry가 single owner로 구현됐는가 | registry snapshots | FAIL |
implementation evidence 없음 |
FE-RDY-010 |
lint/checkJs/runtime-schema/unit/component/integration/e2e/a11y가 통과했는가 | CI artifacts | FAIL |
CI evidence UNVERIFIED |
FE-RDY-011 |
build/bundle/security gate가 통과했는가 | release artifacts | FAIL |
build evidence UNVERIFIED |
FE-RDY-012 |
lab·field NFR context와 측정값이 있는가 | lab + field reports | FAIL |
target만 존재; FE-GATE-018, FE-GATE-026은 FAIL_UNVERIFIED |
FE-RDY-013 |
release compatibility tuple이 검증됐는가 | release verification | FAIL |
release evidence UNVERIFIED |
FE-RDY-014 |
rollback drill이 수행됐는가 | drill record | FAIL |
deploy/drill evidence UNVERIFIED |
FE-RDY-015 |
runbook이 실제 hosting command와 evidence path를 가지는가 | provider runbook | FAIL |
provider 미정 |
FE-RDY-016 |
evidence ledger에 과장 없는 grade가 유지되는가 | ledger review | PASS |
현재 문서 경계 명시 |
FE-RDY-017 |
비활성 capability가 번들에서 실제로 부재한가 | capability bundle report | FAIL |
build evidence UNVERIFIED |
Current verdict: NOT_READY
Repository identity와 implementation/test/CI/deploy evidence 또는 blocking gate가 미검증이면 verdict는 유지된다. scoped diagram PASS는 이를 상쇄하지 않는다. 문서 분량이나 decision row 수로 readiness를 승격하지 않는다.
19. Risks and Open Questions
19.1 Risk register
| Risk ID | Risk | Owner | Trigger | Mitigation | Resolution condition | Status |
|---|---|---|---|---|---|---|
FE-RISK-001 |
remote implementation repo가 따로 존재해 문서가 실제 stack과 drift | project owner | repo URL 발견 | inventory 후 decision/contract map 재검토 | repo commit과 ledger 연결 | open |
FE-RISK-002 |
runtime config와 HTML publish가 atomic하지 않음 | release owner | hosting 선택 | coherent release pointer 또는 env rebuild fallback | mismatch drill pass | open |
FE-RISK-003 |
pnpm이 target CI/org 표준과 충돌 | toolchain owner | CI platform 확정 | FE-D001 재검토 |
frozen install gate pass | open |
FE-RISK-004 |
JavaScript checkJs coverage가 complex API를 놓침 | toolchain/schema owners | recurring runtime defects | TypeScript 또는 generated types 비교 | negative fixtures + defect trend 기준 충족 | open |
FE-RISK-005 |
auth route guard가 security control로 오해됨 | auth/routing owners | guarded route 구현 | backend authz requirement 문서·test | e2e에서 403 처리 확인 | open |
FE-RISK-006 |
retry가 backend overload를 증폭 | API owner | 429/5xx spike | cap/jitter/Retry-After + telemetry | load/degradation test pass | open |
FE-RISK-007 |
cache persistence가 PII 또는 stale schema를 남김 | query/storage owners | offline persistence opt-in | classification/version/TTL/migration gate | threat model + compatibility tests | open |
FE-RISK-008 |
telemetry failure가 memory growth 유발 | telemetry owner | sink outage | bounded queue/drop policy | soak test pass | open |
FE-RISK-009 |
chunk auto reload가 user input 손실 | release/presentation owners | lazy chunk failure | dirty-state guard + one reload cap | e2e recovery pass | open |
FE-RISK-010 |
bundle threshold가 실제 device UX와 무관 | performance owner | first measurement | context/field data로 threshold revisit | decision update with evidence | open |
FE-RISK-011 |
supply-chain scanner policy가 미정이라 gate가 형식적 | security owner | repo bootstrap | scanner/severity/suppression decision | SARIF gate pass | open |
FE-RISK-012 |
draw.io와 text contract의 component/edge drift | architecture owner | diagram 또는 FE-D 변경 | reviewer + contract ID annotation in caption | review report resolves all edges | open |
19.2 Open questions
| Question ID | Question | Owner | Decision trigger | Required evidence | Resolution condition |
|---|---|---|---|---|---|
FE-Q-001 |
실제 repo 위치와 ownership은? | project owner | implementation handoff | URL/path/commit | ledger update |
FE-Q-002 |
target Node/pnpm version은? | toolchain owner | repo creation | CI runner/org standard | manifest engines + fresh clone pass |
FE-Q-003 |
static hosting provider와 atomic deploy primitive는? | release owner | first deploy | provider docs/config | FE-D023 confirmed |
FE-Q-004 |
runtime config endpoint를 hosting이 지원하는가? | config/release owners | hosting choice | staging publish experiment | FE-D012 or FE-D013 final |
FE-Q-005 |
backend envelope/OpenAPI source는 어디인가? | API owner | first integration | versioned schema/fixture | runtime schema generated or mapped |
FE-Q-006 |
auth integration adapter는 어떤 owner가 제공하는가? | auth owner | guarded route | session interface + lifecycle doc | port contract test |
FE-Q-007 |
browser support matrix는? | product owner | first release | product analytics/requirement | CI browser matrix fixed |
FE-Q-008 |
telemetry sink와 consent policy는? | telemetry/privacy owners | production telemetry | data inventory + endpoint | redaction and delivery tests |
FE-Q-009 |
service worker/offline이 필요한가? | product/release owners | offline requirement | UX/update design | FE-D019 retained or superseded |
FE-Q-010 |
vulnerability/license blocking threshold는? | security owner | CI setup | organization policy | security gate configured |
8.0 실행계획
Project contract v2의 branch handoff SSOT.
Dependencies는 stable WI ID만 사용하고Applies Decisions는 revision 1에 pin한다.
| Work Item ID | branch slug | 완료 조건 (측정가능) | Applies Decisions | Dependencies | Status |
|---|---|---|---|---|---|
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001 |
feature-frontend-project-bootstrap-toolchain-contract |
manifest·engines·pnpm lock·checkJs scripts와 frozen install evidence가 존재한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TOOLCHAIN-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-LANGUAGE-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BUILD-001@1 |
- | planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002 |
feature-frontend-clean-architecture-layering-contract |
directory 책임·port owner·allowed import matrix가 문서와 fixture로 고정된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PORT-OWNERSHIP-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-COMPOSITION-ROOT-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-003 |
feature-frontend-architecture-enforcement-lint-contract |
allowed fixture는 통과하고 forbidden fixture는 실패하며 lint report가 생성된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-017 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004 |
feature-frontend-env-runtime-config-contract |
build/runtime/secret registry와 boot-invalid matrix가 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RUNTIME-CONFIG-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005 |
feature-api-client-response-envelope-contract |
API registry와 timeout·abort·retry·idempotency deterministic tests가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TIMEOUT-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-RETRY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-IDEMPOTENCY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006 |
feature-runtime-schema-validation-contract |
content-type·JSON·envelope·payload invalid fixture가 기대 failure kind로 정규화된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007 |
feature-frontend-error-classification-boundary-contract |
normalization matrix와 raw body·stack leakage negative test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-008 |
feature-frontend-auth-session-integration-contract |
AuthSessionPort·bounded 401 replay와 token lifecycle import 금지가 test로 고정된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-AUTH-BOUNDARY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PORT-OWNERSHIP-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-009 |
feature-routing-navigation-guard-contract |
registry route·param validation·404·redirect-loop·session UX test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ROUTING-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-AUTH-BOUNDARY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-008, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-010 |
feature-server-state-caching-contract |
QueryCachePort와 TanStack adapter의 invalidation·stale test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SERVER-STATE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011 |
feature-frontend-storage-registry-contract |
namespace·version·classification·quota fallback test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-012 |
feature-frontend-observability-logging-trace-contract |
telemetry registry·redaction·bounded queue·sink failure test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TELEMETRY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-013 |
feature-async-ui-state-contract |
required와 non-blocking state matrix component test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-UI-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SERVER-STATE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-010 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-014 |
feature-boundary-mapper-viewmodel-contract |
raw DTO direct use가 차단되고 mapper negative fixture가 실패한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-015 |
feature-frontend-render-recovery-boundary-contract |
boot·route·feature·async boundary ownership과 recovery fixture가 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-UI-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-013 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-016 |
feature-sample-feature-slice-contract-fixture |
full contract slice와 sample removal smoke test가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SAMPLE-FIXTURE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-009, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-010 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-017 |
feature-frontend-test-taxonomy-contract |
gate·fixture·artifact mapping과 test level별 최소 1개 test가 존재한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-018 |
feature-tailwind-design-token-styling-contract |
theme token·arbitrary value policy·sample UI가 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-STYLING-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-019 |
feature-accessibility-baseline-contract |
sample route에서 axe·keyboard·focus evidence가 남는다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-STYLING-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-013 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020 |
feature-frontend-build-bundle-supply-chain-contract |
frozen build·inventory·scan·bundle report가 CI artifact로 생성된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BUILD-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-017 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-021 |
feature-frontend-browser-security-boundary-contract |
CSP·header·secret·storage·telemetry browser-boundary fixture가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-AUTH-BOUNDARY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TELEMETRY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-008, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-012 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-022 |
feature-frontend-contract-registry-governance |
8개 registry snapshot·schema validation·single-owner check가 통과한다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-023 |
feature-frontend-contract-compatibility-governance |
version tuple·additive/breaking fixture·migration/rollback rule가 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CONFIG-FALLBACK-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-022, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-024 |
feature-frontend-release-cache-rollback-contract |
release tuple·cache header·mixed fixture failure·rollback drill이 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CACHE-POLICY-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-OFFLINE-CACHE-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-023 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-025 |
feature-web-vitals-performance-budget-contract |
context metadata와 lab·bundle·28-day field report가 생성된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-BUILD-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-016 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-026 |
feature-frontend-operational-runbook-contract |
5개 drill의 trigger·window·escalation·evidence assertion이 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TELEMETRY-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-024, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-012, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-004 |
planned |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-027 |
feature-frontend-ci-quality-gates-contract |
blocking gate가 분리되고 dependency graph와 artifact retention이 검증된다 | DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TEST-STACK-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-SUPPLY-CHAIN-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-DEPLOYMENT-001@1 |
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-017, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-020, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-024, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-025, WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-026 |
planned |
20. Branch Decomposition / Execution Plan
Legacy reference (v1). 아래 표는 기존 FE-OC ownership·priority 설명을 보존한다. branch handoff ID·decision pin·dependency의 SSOT는 위 Work Item Registry다.
Branch는 project-wide contract를 상세 implementation-ready spec으로 내린다. Primary contract IDs는 single owner만 가지며 Contributes to는 acceptance fixture·adapter·gate 협업만 뜻한다. FE-OC-001과 FE-OC-026의 primary owner는 이 project hub다. 아래 27개 branch-note는 2026-07-18 /branch scaffolding으로 생성되어 §21.2 Cluster에 연결됐다. 파일 존재는 implementation evidence가 아니며, 각 row의 mechanism·decision·test가 채워지기 전까지 상태는 계속 planned다.
| Branch slug | Primary contract IDs | Contributes to | Measurable completion | Priority | Dependency |
|---|---|---|---|---|---|
feature-frontend-project-bootstrap-toolchain-contract |
FE-OC-003 |
FE-OC-018, FE-OC-020 |
manifest/engines/pnpm lock/checkJs scripts + frozen install evidence | P1 | — |
feature-frontend-clean-architecture-layering-contract |
FE-OC-002 |
FE-OC-004, FE-OC-011, FE-OC-020 |
directory responsibility + port owner + allowed import matrix | P1 | feature-frontend-project-bootstrap-toolchain-contract |
feature-frontend-architecture-enforcement-lint-contract |
— | FE-OC-002, FE-OC-020 |
allowed fixture pass, forbidden fixture fail, report emitted | P1 | feature-frontend-clean-architecture-layering-contract, feature-frontend-test-taxonomy-contract |
feature-frontend-env-runtime-config-contract |
FE-OC-004 |
FE-OC-016, FE-OC-023 |
build/runtime/secret registry + boot invalid matrix | P1 | feature-frontend-project-bootstrap-toolchain-contract |
feature-api-client-response-envelope-contract |
FE-OC-006, FE-OC-009 |
FE-OC-007, FE-OC-008, FE-OC-010, FE-OC-012, FE-OC-023 |
API operation registry + timeout/abort/retry/idempotency deterministic tests | P1 | feature-frontend-env-runtime-config-contract, feature-frontend-clean-architecture-layering-contract |
feature-runtime-schema-validation-contract |
FE-OC-007 |
FE-OC-008, FE-OC-023 |
content-type/JSON/envelope/payload invalid fixtures map to expected kinds | P1 | feature-api-client-response-envelope-contract |
feature-frontend-error-classification-boundary-contract |
FE-OC-008 |
FE-OC-011, FE-OC-015, FE-OC-020 |
total normalization matrix + raw body/stack leakage negative tests | P1 | feature-api-client-response-envelope-contract, feature-runtime-schema-validation-contract |
feature-frontend-auth-session-integration-contract |
FE-OC-010 |
FE-OC-005, FE-OC-006, FE-OC-019 |
AuthSessionPort + bounded 401 state/replay + no token lifecycle import tests | P1 | feature-frontend-clean-architecture-layering-contract |
feature-routing-navigation-guard-contract |
FE-OC-005 |
FE-OC-010, FE-OC-015, FE-OC-024 |
registry routes, param validation, 404, redirect-loop, session UX tests | P2 | feature-frontend-auth-session-integration-contract, feature-frontend-error-classification-boundary-contract |
feature-server-state-caching-contract |
FE-OC-012 |
FE-OC-011, FE-OC-022, FE-OC-024 |
application-owned QueryCachePort + TanStack adapter/invalidation/stale tests | P2 | feature-api-client-response-envelope-contract |
feature-frontend-storage-registry-contract |
FE-OC-013 |
FE-OC-022, FE-OC-023 |
namespace/version/classification/quota fallback tests | P2 | feature-frontend-clean-architecture-layering-contract |
feature-frontend-observability-logging-trace-contract |
FE-OC-014 |
FE-OC-008, FE-OC-021, FE-OC-025 |
telemetry registry, redaction, bounded queue, sink failure tests | P2 | feature-frontend-env-runtime-config-contract |
feature-async-ui-state-contract |
FE-OC-011 |
FE-OC-015, FE-OC-020, FE-OC-024 |
required + non-blocking state matrix component tests | P2 | feature-frontend-error-classification-boundary-contract, feature-server-state-caching-contract |
feature-boundary-mapper-viewmodel-contract |
— | FE-OC-007, FE-OC-024 |
raw DTO direct use prohibited; mapper negative fixture | P2 | feature-runtime-schema-validation-contract |
feature-frontend-render-recovery-boundary-contract |
FE-OC-015 |
FE-OC-005, FE-OC-011, FE-OC-025 |
boot/route/feature/async boundary ownership + recovery fixtures | P2 | feature-frontend-error-classification-boundary-contract, feature-async-ui-state-contract |
feature-sample-feature-slice-contract-fixture |
FE-OC-024 |
FE-OC-005, FE-OC-006, FE-OC-007, FE-OC-008, FE-OC-011, FE-OC-012, FE-OC-020, FE-OC-021 |
full contract slice + sample removal smoke | P2 | feature-api-client-response-envelope-contract, feature-runtime-schema-validation-contract, feature-frontend-error-classification-boundary-contract, feature-routing-navigation-guard-contract, feature-server-state-caching-contract |
feature-frontend-test-taxonomy-contract |
FE-OC-020 |
FE-OC-002, FE-OC-003, FE-OC-007, FE-OC-008, FE-OC-019, FE-OC-021, FE-OC-024, FE-OC-025 |
gate/fixture/artifact mapping + one test per level | P1 | feature-frontend-project-bootstrap-toolchain-contract |
feature-tailwind-design-token-styling-contract |
— | FE-OC-011, FE-OC-019, FE-OC-021 |
theme tokens + arbitrary value policy + sample UI | P3 | feature-frontend-project-bootstrap-toolchain-contract |
feature-accessibility-baseline-contract |
— | FE-OC-019, FE-OC-020, FE-OC-021, FE-OC-024 |
axe + keyboard/focus manual evidence for sample routes | P3 | feature-async-ui-state-contract |
feature-frontend-build-bundle-supply-chain-contract |
FE-OC-018 |
FE-OC-003, FE-OC-016, FE-OC-019, FE-OC-020, FE-OC-021 |
frozen build, inventory, scan, bundle report | P3 | feature-frontend-project-bootstrap-toolchain-contract, feature-frontend-test-taxonomy-contract |
feature-frontend-browser-security-boundary-contract |
FE-OC-019 |
FE-OC-010, FE-OC-013, FE-OC-014, FE-OC-018, FE-OC-020 |
CSP/header/secret/storage/telemetry browser-boundary fixtures | P3 | feature-frontend-auth-session-integration-contract, feature-frontend-storage-registry-contract, feature-frontend-observability-logging-trace-contract |
feature-frontend-contract-registry-governance |
FE-OC-022 |
FE-OC-004, FE-OC-005, FE-OC-006, FE-OC-008, FE-OC-012, FE-OC-013, FE-OC-014, FE-OC-016, FE-OC-020, FE-OC-023 |
8 registry snapshots, schema validation, single-owner checks | P2 | feature-frontend-project-bootstrap-toolchain-contract, feature-frontend-clean-architecture-layering-contract |
feature-frontend-contract-compatibility-governance |
FE-OC-023 |
FE-OC-004, FE-OC-006, FE-OC-007, FE-OC-012, FE-OC-013, FE-OC-016, FE-OC-017 |
version tuple matrix + additive/breaking fixtures + migration/rollback rule | P3 | feature-frontend-contract-registry-governance, feature-runtime-schema-validation-contract, feature-frontend-storage-registry-contract |
feature-frontend-release-cache-rollback-contract |
FE-OC-016, FE-OC-017 |
FE-OC-004, FE-OC-015, FE-OC-021, FE-OC-023, FE-OC-025 |
release tuple, headers, mixed fixture fail, rollback drill | P3 | feature-frontend-build-bundle-supply-chain-contract, feature-frontend-env-runtime-config-contract, feature-frontend-contract-compatibility-governance |
feature-web-vitals-performance-budget-contract |
FE-OC-021 |
FE-OC-016, FE-OC-020 |
context metadata + lab/bundle/28-day field reports | P3 | feature-frontend-build-bundle-supply-chain-contract, feature-sample-feature-slice-contract-fixture |
feature-frontend-operational-runbook-contract |
FE-OC-025 |
FE-OC-004, FE-OC-006, FE-OC-014, FE-OC-016, FE-OC-017 |
five drills with trigger/window/escalation/evidence assertions | P3 | feature-frontend-release-cache-rollback-contract, feature-api-client-response-envelope-contract, feature-frontend-observability-logging-trace-contract, feature-frontend-env-runtime-config-contract |
feature-frontend-ci-quality-gates-contract |
— | FE-OC-020, FE-OC-021, FE-OC-022, FE-OC-023, FE-OC-024, FE-OC-025 |
separate blocking gates, dependency graph, artifact retention | P3 | feature-frontend-test-taxonomy-contract, feature-frontend-build-bundle-supply-chain-contract, feature-frontend-release-cache-rollback-contract, feature-web-vitals-performance-budget-contract, feature-frontend-operational-runbook-contract |
Branch creation workflow:
/branch <slug>
/branch-spec <slug> <existing evidence URLs if needed>
/depth <slug>
/coverage <slug>
Branch completion MUST update this table, Cluster, evidence ledger, and readiness scorecard. planned row를 단순히 branch file 생성만으로 actually-implemented로 올리지 않는다.
21. 묶음
가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
FE-GATE-018@1 |
raw/branch-notes/feature-web-vitals-performance-budget-contract | p75 목표 미달이거나 표본 임계가 미해결이면 field readiness 를 MUST 차단 | import 참조로 적용 |
FE-GATE-026@1 |
raw/branch-notes/feature-web-vitals-performance-budget-contract | lab threshold 미달이거나 재현 메타데이터가 없으면 release 를 MUST 차단 | import 참조로 적용 |
FE-OC-002@1 |
raw/branch-notes/feature-frontend-clean-architecture-layering-contract | domain <- application <- presentation 의존 방향과 application-owned output port를 MUST 지킴 |
import 참조로 적용 |
FE-OC-003@1 |
raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract | package manager, engine, lockfile, source language, checkJs command를 한 곳에서 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-005@1 |
raw/branch-notes/feature-routing-navigation-guard-contract | route ID/path/params/access/loading/error owner는 route registry 하나여야 함 | import 참조로 적용 |
FE-OC-006@1 |
raw/branch-notes/feature-api-client-response-envelope-contract | 모든 HTTP는 shared client를 MUST 통과하고 timeout·abort·response parsing을 page에서 구현하면 안 됨 | import 참조로 적용 |
FE-OC-007@1 |
raw/branch-notes/feature-runtime-schema-validation-contract | JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 | import 참조로 적용 |
FE-OC-008@1 |
raw/branch-notes/feature-frontend-error-classification-boundary-contract | 모든 failure는 stable frontend error kind로 MUST 정규화하고 raw body·stack을 UI에 노출하면 안 됨 | import 참조로 적용 |
FE-OC-009@1 |
raw/branch-notes/feature-api-client-response-envelope-contract | retry는 safe/idempotent request에 한정하고 cap·jitter·Retry-After를 MUST 적용 |
import 참조로 적용 |
FE-OC-010@1 |
raw/branch-notes/feature-frontend-auth-session-integration-contract | skeleton은 session state를 소비하되 token lifecycle을 MUST 소유하지 않음 | import 참조로 적용 |
FE-OC-011@1 |
raw/branch-notes/feature-async-ui-state-contract | async surface는 initial-loading, success, empty, terminal-error를 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-014@1 |
raw/branch-notes/feature-frontend-observability-logging-trace-contract | telemetry는 best-effort이며 render·API success를 차단하면 안 되고 PII·token을 전송하면 안 됨 | import 참조로 적용 |
FE-OC-015@1 |
raw/branch-notes/feature-frontend-render-recovery-boundary-contract | expected operational error와 render defect를 MUST 분리하고 reload loop를 금지 | 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 참조로 적용 |
FE-OC-018@1 |
raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract | frozen lockfile, dependency review, secret scan, SBOM 또는 dependency inventory를 release gate에 MUST 포함 | import 참조로 적용 |
FE-OC-019@1 |
raw/branch-notes/feature-frontend-browser-security-boundary-contract | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | import 참조로 적용 |
FE-OC-020@1 |
raw/branch-notes/feature-frontend-test-taxonomy-contract | gate 종류별 책임·fixture·artifact를 분리하고 실패를 warning으로 낮추면 안 됨 | import 참조로 적용 |
FE-OC-021@1 |
raw/branch-notes/feature-web-vitals-performance-budget-contract | NFR은 device/network/cache/build context와 함께 MUST 측정 | import 참조로 적용 |
FE-OC-022@1 |
raw/branch-notes/feature-frontend-contract-registry-governance | 9개 registry는 single primary owner와 compatibility impact를 MUST 기록 | import 참조로 적용 |
FE-OC-023@1 |
raw/branch-notes/feature-frontend-contract-compatibility-governance | API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 | import 참조로 적용 |
FE-OC-024@1 |
raw/branch-notes/feature-sample-feature-slice-contract-fixture | sample은 contract fixture이며 production feature가 의존하면 안 됨 | import 참조로 적용 |
FE-OC-025@1 |
raw/branch-notes/feature-frontend-operational-runbook-contract | boot, chunk mismatch, API degradation, telemetry failure, rollback, realtime 연결, background 실행 runbook을 MUST 유지 | import 참조로 적용 |
- raw/official-docs/owasp-content-security-policy-cheat-sheet
- raw/official-docs/react-router-official
- raw/official-docs/react-ui-library-official
- raw/official-docs/tailwind-css-utility-first-official
- raw/official-docs/tanstack-query-server-state-official
- raw/official-docs/vite-build-tool-official
- raw/official-docs/zod-runtime-schema-validation-official
21.1 부모·형제 문서 맥락
- Backend sibling operational contract: raw/project-notes/ca-skeleton-operational-contract
- Auth lifecycle boundary: raw/project-notes/keycloak-patterns-overview
본 project-note는 raw/project-notes/ root이므로 upward link 면제다.
21.2 브랜치
- raw/branch-notes/feature-accessibility-baseline-contract
- raw/branch-notes/feature-api-client-response-envelope-contract
- raw/branch-notes/feature-async-ui-state-contract
- raw/branch-notes/feature-boundary-mapper-viewmodel-contract
- raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract
- raw/branch-notes/feature-frontend-auth-session-integration-contract
- raw/branch-notes/feature-frontend-browser-security-boundary-contract
- raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract
- raw/branch-notes/feature-frontend-ci-quality-gates-contract
- raw/branch-notes/feature-frontend-clean-architecture-layering-contract
- raw/branch-notes/feature-frontend-contract-compatibility-governance
- raw/branch-notes/feature-frontend-contract-registry-governance
- raw/branch-notes/feature-frontend-env-runtime-config-contract
- raw/branch-notes/feature-frontend-error-classification-boundary-contract
- raw/branch-notes/feature-frontend-observability-logging-trace-contract
- raw/branch-notes/feature-frontend-operational-runbook-contract
- raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract
- raw/branch-notes/feature-frontend-release-cache-rollback-contract
- raw/branch-notes/feature-frontend-render-recovery-boundary-contract
- raw/branch-notes/feature-frontend-storage-registry-contract
- raw/branch-notes/feature-frontend-test-taxonomy-contract
- raw/branch-notes/feature-routing-navigation-guard-contract
- raw/branch-notes/feature-runtime-schema-validation-contract
- raw/branch-notes/feature-sample-feature-slice-contract-fixture
- raw/branch-notes/feature-server-state-caching-contract
- raw/branch-notes/feature-tailwind-design-token-styling-contract
- raw/branch-notes/feature-web-vitals-performance-budget-contract
generated reverse view는 child branch의 v2 contract migration 후 채운다. 아래 수기 목록은 그 전까지 legacy navigation으로 보존한다.
- raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract — project bootstrap·toolchain contract
- raw/branch-notes/feature-frontend-clean-architecture-layering-contract — Clean Architecture layer·port ownership contract
- raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract — architecture dependency lint contract
- raw/branch-notes/feature-frontend-env-runtime-config-contract — build/runtime environment config contract
- raw/branch-notes/feature-api-client-response-envelope-contract — shared API client·response envelope contract
- raw/branch-notes/feature-runtime-schema-validation-contract — runtime schema validation contract
- raw/branch-notes/feature-frontend-error-classification-boundary-contract — normalized failure classification contract
- raw/branch-notes/feature-frontend-auth-session-integration-contract — external auth session integration boundary
- raw/branch-notes/feature-routing-navigation-guard-contract — route registry·navigation guard contract
- raw/branch-notes/feature-server-state-caching-contract — server-state query cache contract
- raw/branch-notes/feature-frontend-storage-registry-contract — browser storage registry contract
- raw/branch-notes/feature-frontend-observability-logging-trace-contract — frontend telemetry·logging·trace contract
- raw/branch-notes/feature-async-ui-state-contract — async UI state contract
- raw/branch-notes/feature-boundary-mapper-viewmodel-contract — boundary mapper·view-model contract
- raw/branch-notes/feature-frontend-render-recovery-boundary-contract — render failure recovery boundary
- raw/branch-notes/feature-sample-feature-slice-contract-fixture — removable sample feature contract fixture
- raw/branch-notes/feature-frontend-test-taxonomy-contract — frontend test taxonomy contract
- raw/branch-notes/feature-tailwind-design-token-styling-contract — Tailwind design-token styling contract
- raw/branch-notes/feature-accessibility-baseline-contract — accessibility baseline contract
- raw/branch-notes/feature-frontend-build-bundle-supply-chain-contract — build·bundle·supply-chain contract
- raw/branch-notes/feature-frontend-browser-security-boundary-contract — browser security boundary contract
- raw/branch-notes/feature-frontend-contract-registry-governance — eight-registry governance contract
- raw/branch-notes/feature-frontend-contract-compatibility-governance — contract compatibility governance
- raw/branch-notes/feature-frontend-release-cache-rollback-contract — release·cache·rollback contract
- raw/branch-notes/feature-web-vitals-performance-budget-contract — Web Vitals·performance budget contract
- raw/branch-notes/feature-frontend-operational-runbook-contract — frontend operational runbook contract
- raw/branch-notes/feature-frontend-ci-quality-gates-contract — CI quality-gate orchestration contract
21.3 근거 자료
- raw/official-docs/vite-build-tool-official — build tool/config decision input
- raw/official-docs/react-ui-library-official — UI composition decision input
- raw/official-docs/tailwind-css-utility-first-official — styling decision input
- raw/official-docs/tanstack-query-server-state-official — server-state/cache decision input
- raw/official-docs/zod-runtime-schema-validation-official — runtime schema decision input
- raw/official-docs/react-router-official — route decision input
21.4 Diagrams
raw/diagrams/ca-skeleton-frontend/architecture-overview-2026-07-18.drawio— active, dependency ownership scope reviewer PASS 100/100raw/diagrams/ca-skeleton-frontend/architecture-deployment-2026-07-18.drawio— active, static asset/runtime-config delivery scope reviewer PASS 100/100
21.5 오류·면접·블로그 글감·파생 문서
- Errors: 아직 없음
- Interview prep: 아직 없음
- Blog topics / job-posting tie-ins: 아직 없음
- Derived canonical: 아직 없음
Canonical 또는 derived 문서는 implementation evidence와 promotion gate를 통과하기 전 생성하지 않는다.
22. External Answer Boundary
22.1 현재 답할 수 있는 것
- frontend operational contract의 목표와 scope
FE-D*에서 검토한 선택과 조건부 defaultFE-OC-*의 owner·failure·acceptance 구조- 왜 port를 application이 소유하고 adapter가 구현하도록 설계했는지
- 왜 build/runtime/secret config를 분리했는지
- 왜 retry에 cap, jitter, idempotency 조건을 둔 설계인지
- 두 architecture diagram의 scoped reviewer PASS와 그 범위; implementation·§12 전체 deploy/rollback evidence와는 분리한 설명
22.2 설계라고 명시해야 답할 수 있는 것
- planned folder/file/class name
- pnpm/Vitest/RTL/MSW/Playwright/axe toolchain
- timeout, retry, bundle, performance threshold
- release/rollback sequence
- telemetry and storage policy
표현 예:
현재 구현 증거는 없고, 문서상 기본값으로 설계했다.
repository 생성 후 <gate/artifact>로 검증할 예정이다.
22.3 현재 답하면 안 되는 것
- frontend를 구현·운영했다는 주장
- pnpm install/build/test를 실행했다는 주장
- bundle 200 KiB를 달성했다는 주장
- LCP/CLS/interaction target을 측정했다는 주장
- WCAG 적합성을 확보했다는 주장
- retry/rollback이 운영 장애에서 효과가 있었다는 주장
- auth token refresh를 구현했다는 주장
- diagram review가 실제 implementation·hosting·§12 전체 release/rollback을 증명한다는 주장
22.4 Derived output gate
면접·포트폴리오·블로그 산출물은 다음을 모두 만족한 canonical에서만 파생한다.
- source canonical status가
reviewed이상 - 구현 주장은
actually-implemented이상 evidence 보유 - 측정 주장은
locally-verified또는prod-verifiedevidence 보유 - readiness scorecard의 관련 gate PASS
- 이 §의 금지 표현 위반 없음
23. 아키텍처 검토 체크리스트
23.1 Document structure
- project overview와 evidence boundary가 있음
- stable
FE-D*decision register가 있음 - stable
FE-OC-*contract index가 있음 - application-owned port와 composition root가 명시됨
- route/API-operation/env/storage/error/query/telemetry/release 8개 registry owner가 있음
- failure taxonomy와 retry/fallback/UX/telemetry가 있음
- build/runtime/secret config 구분이 있음
- NFR context와 planned command가 있음
- acceptance gate와 evidence artifact가 있음
- runbook 5종이 있음
- binary readiness가
NOT_READY로 계산됨 - risks/questions에 owner·trigger·resolution이 있음
- branch가 contract ID에 매핑됨
- Cluster와 external answer boundary가 있음
23.2 Diagram review
- overview
.drawio파일이 존재하고 frontmatter에 등록됨 - deployment
.drawio파일이 존재하고 frontmatter에 등록됨 - overview diagram이 rules/diagram-standards reviewer gate 통과 — 100/100
- deployment diagram이 rules/diagram-standards reviewer gate 통과 — 100/100
- overview component label과 dependency ownership view가 §4.2~§4.4 scope와 일치
- overview dependency edge가 scoped §4.3 matrix와 일치
- deployment static asset·
/config.jsondelivery slice가 declared boundary와 일치 - deployment diagram으로 §12 전체 release/rollback topology 또는 실제 hosting을 검증
- reviewer report가
FE-EV-010,FE-EV-011에 연결됨
23.3 Implementation review
- repository URL/path/commit 확인
- manifest + lockfile 확인
- composition root 확인
- negative architecture fixture 확인
- config boot failure fixture 확인
- failure taxonomy coverage 확인
- all acceptance artifacts 확인
- release/rollback drill 확인
24. Diagram and Contract Change Management
24.1 Diagram lifecycle
- architecture 변경 시 새 날짜 파일을 만들거나 동일 파일 변경 사유를 version control에 남긴다.
- 폐기 diagram은 삭제보다
raw/diagrams/ca-skeleton-frontend/archived/이동을 우선한다. - frontmatter
diagrams에는 active file만 둔다. architecture_review.reviewed_at은 reviewer gate 통과 뒤에만 채운다.- draw.io는 static architecture/deployment용이고 sequence는 본문 Mermaid를 사용한다.
24.2 Drift checks
Planned checks:
CONTRACT_STABLE_ID_RE='FE-D[0-9]{3}|FE-(SC|OC|NFR|GATE|RB|EV|RDY|RISK|Q)-[0-9]{3}|FE-NFR-C[0-9]{2}|FE-REG-[A-Z]+(-[A-Z]+)*'
rg --pcre2 -o "$CONTRACT_STABLE_ID_RE" raw/project-notes/ca-skeleton-frontend-operational-contract.md | sort -u
test -z "$(comm -23 <(rg --pcre2 -o "$CONTRACT_STABLE_ID_RE" raw/project-notes/ca-skeleton-frontend-operational-contract.md | sort -u) <(rg --pcre2 -n '^\| `FE-|^### 16\.[0-9]+ `FE-RB-' raw/project-notes/ca-skeleton-frontend-operational-contract.md | rg --pcre2 -o "$CONTRACT_STABLE_ID_RE" | sort -u))"
rg -n 'application.*adapters|presentation.*adapters' <implementation-repo>/src <implementation-repo>/tests
rg -n 'architecture-(overview|deployment)-2026-07-18.drawio' raw/project-notes/ca-skeleton-frontend-operational-contract.md
두 번째 command는 reference set에서 definition set을 뺀 결과가 empty인지 검사한다. 세 번째 command는 repository path가 없어 실행 대상이 아직 없다.
25. Next Steps
P0 — Evidence and architecture
- 실제 frontend repository 위치와 owner 확인
FE-EV-009범위를 repo/commit evidence로 갱신- overview/deployment scoped diagram reviewer 결과 반영
- future diagram 변경 시 §4와 scoped delivery boundary drift 재검토
P1 — Bootstrap and blocking contracts
feature-frontend-project-bootstrap-toolchain-contract생성·설계·depth gatefeature-frontend-clean-architecture-layering-contract생성feature-frontend-test-taxonomy-contract생성·negative fixture taxonomy 확정feature-frontend-architecture-enforcement-lint-contract생성feature-frontend-env-runtime-config-contract생성feature-api-client-response-envelope-contract생성feature-runtime-schema-validation-contract생성feature-frontend-error-classification-boundary-contract생성feature-frontend-auth-session-integration-contract생성
P2 — State, UX, telemetry, fixture
- route/query/storage/telemetry registry 구현 branch 전개
- async state와 mapper boundary 전개
- sample feature contract fixture 구현
P3 — Release readiness
- build/bundle/supply-chain gate 구현
- accessibility와 performance context 측정
- release/cache/rollback contract 구현
- CI gate dependency와 artifact retention 확정
- staging rollback drill 수행
Promotion
- 모든 implementation claim에 repo/commit/path 연결
- 모든 locally-verified claim에 command/exit/artifact 연결
- readiness blocking rows PASS 후
status재검토 - canonical
wiki/projects/승급은 별도 ingest review에서 수행
26. Verification Status Summary
| Area | Grade | Evidence |
|---|---|---|
| operational contract text | documented-only |
this file |
| technology decision sources | documented-only |
§21.3 existing raw sources |
| architecture diagrams | documented-only, scoped reviewer PASS 100/100 each |
dependency ownership view + static asset/runtime-config delivery slice; implementation/§12 full topology UNVERIFIED |
| implementation | planned |
entry artifact pattern search만 미발견; repo location UNVERIFIED |
| tests / CI | planned |
dedicated search/command 미기록, UNVERIFIED |
| NFR measurement | planned |
target/context only |
| release / rollback | planned |
policy/runbook only; dedicated deploy evidence UNVERIFIED |
| production operation | planned |
release evidence UNVERIFIED |
최종 현재 판정은 NOT_READY다. diagram review는 통과했지만 repository, test, deploy, release evidence가 채워질 때까지 이 판정을 유지한다.