- REGISTRY-001 Summary 문자열 4곳 (additive, revision 은 1 유지). registry-governance 는 본문 서술 12곳의 '8개'도 함께 9개로 갱신 - OFFLINE-CACHE-001 pin @1->@2 와 Summary·적용점 (behavior-change) - DELEG-FE-007~011 delegate 5곳 접수 완료 — 미접수 위임 0건 - runtime-schema-validation 이 FLOW-FE-EVENT-003/004 소유를 명시 - env-runtime-config 가 FE-REG-CAPABILITY registry 와 FE-GATE-033 gate owner 를 취득하고 claim 2건 추가 - 신규 6개 노트의 delegation pin 을 기존 @1 형식으로 정규화
305 lines
25 KiB
Markdown
305 lines
25 KiB
Markdown
---
|
||
title: branch / feature-frontend-storage-registry-contract
|
||
source_type: branch-note
|
||
status: raw
|
||
id: BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011
|
||
kind: project-work-item
|
||
project: ca-skeleton-frontend-operational-contract
|
||
work_item: WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-011
|
||
inherits: [DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1]
|
||
refines: []
|
||
overrides: []
|
||
depends_on: [WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002]
|
||
contract_packet: 1
|
||
branch: feature-frontend-storage-registry-contract
|
||
parent_branch:
|
||
related_projects: [ca-skeleton-frontend, ca-skeleton]
|
||
governing_docs: [raw/project-notes/ca-skeleton-frontend-operational-contract.md]
|
||
tags: [branch, ca-skeleton, frontend, persistence, security, javascript]
|
||
created: 2026-07-18
|
||
target_merge:
|
||
status_label: in-progress
|
||
contract_packet_sha256: aa55f276dab66670f66f2424f059e394925f5f1c84ec23381fe506064f4823a1
|
||
imports: [FE-GATE-005@1, FE-OC-002@1, FE-OC-010@1, FE-OC-019@1, FE-OC-023@1]
|
||
accepts_delegations: [DELEG-FE-009@1]
|
||
---
|
||
|
||
# branch: feature-frontend-storage-registry-contract
|
||
|
||
> Layer: `raw/branch-notes/` — 단일 브랜치의 TODO·결정·진행 기록. 현재는 `/branch-spec` 로 채운 `planned` 명세 단계다 (frontend repository 미생성).
|
||
|
||
<!-- section-id: branch-parent -->
|
||
## 부모 (필수)
|
||
|
||
- [[raw/project-notes/ca-skeleton-frontend-operational-contract]]
|
||
|
||
<!-- GENERATED: branch-contract:start -->
|
||
<!-- section-id: branch-contract-packet -->
|
||
## 브랜치 계약 패킷
|
||
|
||
- **생성 시 프로젝트 개정**: `1`
|
||
- **패킷 스키마**: `contract_packet: 1`
|
||
- **완료 조건**: namespace·version·classification·quota fallback test가 통과한다
|
||
|
||
<!-- section-id: inherited-project-decisions -->
|
||
### 상속한 프로젝트 결정
|
||
|
||
| Decision Ref | Project Summary | Branch Application | Source |
|
||
|---|---|---|---|
|
||
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1` | route, API operation, env, storage, error, query, telemetry, release token, capability를 9개 registry로 관리한다 | FE-REG-STORAGE namespace·version·classification schema에 적용한다 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
|
||
|
||
<!-- section-id: branch-local-decisions -->
|
||
### 브랜치 지역 결정
|
||
|
||
| Decision ID | Decision | Relation | Supporting Claims | Status |
|
||
|---|---|---|---|---|
|
||
| D1 | storage key를 FE-REG-STORAGE와 versioned namespace로 관리한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
| D2 | storage item classification을 필수로 둔다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
| D3 | schemaVersion mismatch를 migration 또는 discard로 처리한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
| D4 | application-owned StoragePort와 storage adapter를 사용한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
| D5 | quotaFallback을 registry field로 관리한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
| D6 | token·secret·PII·raw payload 저장을 거부한다 | `local` | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `proposed` |
|
||
|
||
<!-- section-id: declared-overrides -->
|
||
### 선언한 예외
|
||
|
||
| Override ID | Overrides | Reason | Approval | Status |
|
||
|---|---|---|---|---|
|
||
|
||
없음.
|
||
<!-- GENERATED: branch-contract:end -->
|
||
|
||
<!-- section-id: branch-goal -->
|
||
## 목표
|
||
|
||
이 브랜치는 project-wide 계약 `FE-OC-013` (browser storage key 는 namespace·version·classification 을 MUST 보유하고 token/secret 저장을 금지) 를, 다음 구현자가 되묻지 않고 `src/contracts/storage-keys.js` 와 `adapters/storage` 를 작성할 수 있는 implementation-ready 명세로 내린다. `FE-REG-STORAGE` 는 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-D018` 이 규정한 9개 registry 중 하나이며 본 브랜치가 single owner 다. 최소 스키마는 §5.5, 런타임 동작은 §9.4, 브라우저 보안 불변식(번들·storage = 공개물, secret 저장 금지)은 §13.2, quota/unavailable 실패 정규화는 §8.2 에 근거한다. 아직 frontend repository 가 없으므로 본 브랜치의 모든 항목은 `planned` 등급이다.
|
||
|
||
- 이슈: TODO (아직 없음)
|
||
- PR: TODO (아직 없음)
|
||
|
||
<!-- section-id: branch-scope -->
|
||
## 범위
|
||
|
||
### 포함 범위
|
||
|
||
- `FE-REG-STORAGE` registry 스키마 정의 및 single-owner 소유 (§5.5): `logicalName` / `physicalKey` (`<app>:<scope>:v<schema>:<name>`) / `backend` / `classification` / `schemaVersion` / `ttl` / `migration` / `quotaFallback` 필드 계약.
|
||
- 구조화된 physical key 규약(namespace + schema version 내장) + raw literal key 금지 강제.
|
||
- classification 3분류(`public-preference` / `opaque-cache` / `sensitive-forbidden`) + sensitive 저장 금지 불변식.
|
||
- `schemaVersion` + previous-version migration-or-discard 규약.
|
||
- 단일 application 소유 `StoragePort` + `adapters/storage` 어댑터 boundary, try/catch 로 unavailable / security / quota 구분.
|
||
- quota fallback 정책(`memory` / `no-persist` / `feature-disable`) + correctness-critical 값의 fallback 금지.
|
||
- storage 관련 negative fixture: token key 등록 시도 실패(§15.2), quota-exceeded → memory fallback, 미등록 raw key 사용 금지.
|
||
|
||
### 제외 범위
|
||
|
||
> 의도적으로 제외 — 다른 owner 브랜치가 소유. CLAUDE.md §15.5 R3(OUT_OF_BRANCH_SCOPE) 준수.
|
||
|
||
- Token / refresh token / auth session material 의 lifecycle·저장 위치 — 외부 auth owner + [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] (`FE-OC-010`) 소유. 본 registry 는 이를 `sensitive-forbidden` 으로 *거부* 만 한다.
|
||
- CSP / header / secret-scan 등 브라우저 보안 경계 전반 — [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] (`FE-OC-019`) 소유. 본 브랜치는 storage 관련 fixture 만 기여.
|
||
- Query cache 의 in-memory 정책·persistence 활성화 — [[raw/branch-notes/feature-server-state-caching-contract]] (`FE-OC-012`) 소유. 본 registry 는 opt-in persistence 가 요구하는 storage key 계약만 제공.
|
||
- 8-registry governance 전반의 single-owner / compatibility 추적 메커니즘 — [[raw/branch-notes/feature-frontend-contract-registry-governance]] (`FE-OC-022`) 소유. 본 브랜치는 storage registry 스냅샷 1개를 기여.
|
||
- storage schema 의 breaking-change migration / version-bump 판정 규약 — [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] (`FE-OC-023`) 소유. 본 브랜치는 `schemaVersion` 필드와 discard 기본값만 정의.
|
||
- `STORAGE_UNAVAILABLE` / `STORAGE_QUOTA_EXCEEDED` error kind enum 정의 — [[raw/branch-notes/feature-frontend-error-classification-boundary-contract]] (`FE-OC-008`) 소유. 본 브랜치는 adapter 실패 → 해당 kind 매핑만.
|
||
|
||
## 근거 (필수, 최소 1개+)
|
||
|
||
> 본 브랜치는 project-decision-heavy — 외부 storage best-practice 인용 없이 hub 계약(SSOT)에 근거한다. 아카이브된 6개 frontend official-doc(vite/react-ui/tailwind/tanstack-query/zod/react-router) 중 browser storage 를 다루는 것은 없음(확인 완료).
|
||
|
||
| Source | 정당화하는 결정 |
|
||
|---|---|
|
||
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | 본 브랜치 SSOT. `FE-OC-013` + `FE-D018` + §5.5 / §9.4 / §13.2 / §8.2 / §5.1 이 D1–D6 전부의 근거 (project decision). |
|
||
| [[raw/official-docs/react-ui-library-official]] | 시드된 일반 frontend UI-composition source (hub §21.3, `FE-D004` React 선택 근거 `REACT-UI-C1`). **storage 전용 결정을 직접 정당화하지 않음** — 본 브랜치 grounding 은 위 hub 계약이다. |
|
||
|
||
## TODO
|
||
|
||
각 항목 옆 증거 등급 표기. frontend repository 미생성이므로 전부 `planned` / `needs-confirmation`.
|
||
|
||
- [ ] `src/contracts/storage-keys.js` 에 `FE-REG-STORAGE` 스키마 + 초기 행(COLOR_SCHEME / CHUNK_RELOAD_GUARD / QUERY_PERSISTENCE / AUTH_TOKEN) 정의 — 등급: `planned`
|
||
- [ ] physical key 빌더 `<app>:<scope>:v<schema>:<name>` + raw literal 금지 lint/test — 등급: `planned`
|
||
- [ ] classification enforcement + `sensitive-forbidden` 등록 거부 negative fixture(token key 등록 시도) — 등급: `planned`
|
||
- [ ] `schemaVersion` + migration-or-discard 경로 및 previous-version fixture — 등급: `planned`
|
||
- [ ] `StoragePort` + `adapters/storage` try/catch 어댑터, unavailable / security / quota 분기 매핑 — 등급: `planned`
|
||
- [ ] quota fallback 정책 test(`memory` / `no-persist` / `feature-disable`) + correctness-critical no-fallback assertion — 등급: `planned`
|
||
- [ ] 구현 repository·검증 evidence 식별 — 등급: `needs-confirmation`
|
||
|
||
## 진행 중 메모
|
||
|
||
- `/branch-spec` fill 완료 (2026-07-19). 모든 근거는 hub 계약(FE-OC-013 / FE-D018 / §5.5 / §9.4 / §13.2 / §8.2). 외부 storage best-practice 인용 없음 — project-decision 중심 브랜치.
|
||
|
||
## 결정 사항
|
||
|
||
> Decision Evidence Map 의 prose mirror. 각 근거는 hub 계약을 가리킨다(외부 source 없음).
|
||
|
||
- **D1**: 모든 storage 항목은 `FE-REG-STORAGE` registry 에만 등록하고 physical key 는 `<app>:<scope>:v<schema>:<name>` 구조를 MUST 가진다(raw `localStorage` literal 금지). 검토한 대안: code-generation SSOT 로 key 생성. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §5.5 · §5.1.
|
||
- **D2**: 각 항목은 classification(`public-preference` / `opaque-cache` / `sensitive-forbidden`)을 MUST 명시하며 분류 불명 항목은 등록 거부한다. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §5.5.
|
||
- **D3**: 각 항목은 `schemaVersion` 을 MUST 가지며 incompatible change 시 증가, previous version 을 읽으면 migration 또는 discard(기본 discard). 검토한 대안: 무버전 + 항상 discard. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 · §9.2.
|
||
- **D4**: 모든 Web Storage 접근은 application 소유 `StoragePort` + `adapters/storage` 어댑터를 통해서만 하고 try/catch 로 unavailable / security / quota 를 구분한다. 검토한 대안: 컴포넌트 직접 `localStorage` 접근. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §9.4 · §4.4 · `FE-D010`(port ownership).
|
||
- **D5**: `quotaFallback` 은 필수 필드(`memory` / `no-persist` / `feature-disable`)이며 quota 초과 시 허용된 cache 를 registry 명시 순서로 evict 후 memory fallback, 단 correctness-critical(mutation / idempotency record) 값은 fallback 금지·terminal 처리한다. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 · §9.4 · §8.2.
|
||
- **D6**: token / secret / PII / raw API response / error body 는 default registry 에 등록 불가(`sensitive-forbidden`)이며 브라우저 번들·storage 를 공개물로 간주한다. 근거: [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §9.4 · §13.2. 공동 집행: [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] (`FE-OC-019`); token lifecycle 은 [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] (`FE-OC-010`) 외부 소유.
|
||
|
||
## 결정-근거 매핑
|
||
|
||
> `선택 조건` = hub 결정이 `accepted-documented-only`(`FE-D018`) 이므로 대부분 불변식을 고정. 분기 있는 것만 대안 조건 명시. Supporting Claims 는 hub 계약을 가리킨다(project-decision-heavy 브랜치 — 외부 doc 없음).
|
||
|
||
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|
||
|---|---|---|---|---|---|
|
||
| D1 | storage 항목은 `FE-REG-STORAGE` 에만 등록, physical key `<app>:<scope>:v<schema>:<name>` 구조 필수, raw literal 금지 (`FE-OC-013`) | skeleton storage 는 항상 registry 경유; 대안(code-generation SSOT 로 key 생성)은 `FE-D018` revisit trigger(code generation SSOT 채택) 발생 시에만 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §5.5 · §5.1 | `project-decision` | `<app>` literal 값과 `<scope>` 분류 체계(feature별 vs flat) 미확정 — 구현 시 결정 |
|
||
| D2 | 각 항목 classification 3분류 MUST 명시; 분류 불명 → 등록 거부 | 모든 항목 분류 강제(안전 기본); 분기 없음 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §5.5 | `project-decision` | `opaque-cache` vs `public-preference` 경계 판정 기준 문서화 필요 |
|
||
| D3 | `schemaVersion` 필수 + incompatible 시 증가, previous version 은 migration 또는 discard | 기본 discard; migration 선택 시 fixture·rollback 은 compatibility-governance(`FE-OC-023`)로 위임 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 · §9.2 | `project-decision` | migration 필요 항목 발생 시 `FE-OC-023` 과 계약 조율 필요 |
|
||
| D4 | 단일 application 소유 `StoragePort` + `adapters/storage` try/catch, unavailable / security / quota 분기 구분 | Clean Arch layering(`FE-OC-002`) 하에 port-owned 항상; 직접 `localStorage` 접근 금지 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §9.4 · §4.4 · `FE-D010` | `project-decision` | private-mode / 정책 차단의 SecurityError 세부 분기 미검증 |
|
||
| D5 | `quotaFallback` 필수(`memory` / `no-persist` / `feature-disable`); quota 초과 시 evict→memory, correctness-critical 값 fallback 금지 | preference write 실패 → memory fallback 무중단; mutation / idempotency 등 correctness-critical → fallback 없이 terminal | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 · §9.4 · §8.2 | `project-decision` | eviction 순서(어떤 cache 먼저)의 registry 표기 형식 미정 |
|
||
| D6 | token / secret / PII / raw response / error body = `sensitive-forbidden`, default registry 등록 불가, storage = 공개물 | skeleton default 는 항상 금지; auth owner 가 storage 사용 필요 시 별도 threat model + owner evidence(§6.1) — 본 브랜치 범위 밖 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §9.4 · §13.2 · §5.4 | `project-decision` | 공동 집행 경계(browser-security `FE-OC-019` / auth `FE-OC-010`) fixture 중복·누락 조율 |
|
||
|
||
## 구현 가이드
|
||
|
||
> `planned` blueprint — frontend repository 미생성. 경로는 hub §4.6 Planned directory blueprint + §5.1 registry owner map 에서 도출(grounded)되나, 코드는 아직 없으므로 전체가 `planned`. CLAUDE.md §15.5 R1(Trace)·R2(UNSUPPORTED_IMPL_DECISION)·R3(OUT_OF_BRANCH_SCOPE) 준수.
|
||
|
||
### 1. `FE-REG-STORAGE` registry schema (`src/contracts/storage-keys.js`)
|
||
|
||
> **Trace**: D1, D2, D3, D5 → [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · `FE-D018` · §5.5 · §5.1.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**:
|
||
> - physical key 의 `<app>` literal 값(예: `ca`)과 `<scope>` 분류 체계(feature-prefix vs flat namespace) — §5.5 는 *형식*만 규정하고 구체 값을 권고하지 않음. trade-off: 짧은 prefix = 충돌 위험, 긴 prefix = key 길이 증가.
|
||
> - registry 를 JS object literal vs factory 함수로 표현 — hub 미권고. trade-off: object = 단순, factory = 등록 시 검증 강제 용이.
|
||
> - `schemaVersion` 표기(정수 vs semver) — §5.5 는 increment 만 규정. trade-off: 정수 = 단순 비교, semver = additive/breaking 구분.
|
||
|
||
**필드 계약(8-field 스키마)과 초기 4행의 owner 는 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 다** — 이전 판은 두 표를 1:1 로 옮겨 적고 있었고("전부 §5.5 grounded" · "§5.5 planned rows 그대로" 라고 스스로 밝힌 그대로), 그러면 §5.5 가 필드를 추가할 때 이 사본이 조용히 낡는다. 요약 한 줄: storage key 는 `logicalName`·`physicalKey`·`backend`·`classification`·`schemaVersion`·`ttl`·`migration`·`quotaFallback` 8필드를 가지고, 초기 행은 색상 테마·chunk reload guard·query persistence(비활성)·auth token(금지) 4개다.
|
||
|
||
본 브랜치가 소유하는 것은 그 위의 **강제 방법**이다 — 아래 enforcement point, key-name deny 패턴, quota fallback 사다리.
|
||
|
||
### 2. `StoragePort` boundary + adapter failure mapping (`application/ports` + `adapters/storage`)
|
||
|
||
> **Trace**: D4, D5 → [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §9.4 · §4.4 · §8.2 · `FE-D010`.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**:
|
||
> - `StoragePort` method 시그니처(예: `get(logicalName)` / `set(logicalName, value)` / `remove(logicalName)`)의 정확한 이름·인자 — §9.4 는 boundary 원칙만 규정. trade-off: 좁은 API = 안전, 넓은 API = 유연.
|
||
> - **OUT_OF_BRANCH_SCOPE**: `STORAGE_UNAVAILABLE` / `STORAGE_QUOTA_EXCEEDED` **kind enum 정의**는 [[raw/branch-notes/feature-frontend-error-classification-boundary-contract]] (`FE-OC-008`) 소유(§5.6). 본 § 는 adapter 실패 → 해당 kind *매핑*만 명세한다.
|
||
|
||
어댑터 실패 매핑 (§8.2 · §9.4 grounded):
|
||
|
||
| adapter 조건 | normalized kind | fallback |
|
||
|---|---|---|
|
||
| Storage API 부재 / `SecurityError`(private mode·정책 차단) | `STORAGE_UNAVAILABLE` | memory-only (§8.2) |
|
||
| `setItem` quota 초과 | `STORAGE_QUOTA_EXCEEDED` | 허용 cache evict → memory-only (§8.2) |
|
||
|
||
### 3. Classification enforcement + `sensitive-forbidden` invariant
|
||
|
||
> **Trace**: D2, D6 → [[raw/project-notes/ca-skeleton-frontend-operational-contract]] `FE-OC-013` · §5.5 · §9.4 · §13.2 · §15.2 · §6.1.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**:
|
||
> - 거부 강제 지점(build-time lint vs runtime registry assert vs 둘 다) — hub 미권고. trade-off: lint = 조기 차단, runtime = 동적 등록도 방어.
|
||
> - 금지 key 이름 패턴(정규식/glob) 구체 — §6.1 은 이름 목록(`SECRET`/`PASSWORD`/`PRIVATE_KEY`/`TOKEN`)만 제시. trade-off: 넓은 패턴 = 오탐, 좁은 패턴 = 누락.
|
||
> - **OUT_OF_BRANCH_SCOPE**: CSP / secret-scan / `dangerouslySetInnerHTML` 등 브라우저 보안 경계 전반은 [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] (`FE-OC-019`) 소유(§13.2). 본 § 는 storage 등록 거부만.
|
||
|
||
강제 규약:
|
||
- `classification: sensitive-forbidden` 항목은 등록 자체를 거부(§5.5 · §9.4).
|
||
- key 이름에 `SECRET` / `PASSWORD` / `PRIVATE_KEY` / `TOKEN` 포함 시 거부(§6.1 정책을 storage 에 적용).
|
||
- negative fixture: `token key registration attempt` → 반드시 실패(§15.2).
|
||
|
||
### 4. Quota fallback + correctness-critical policy
|
||
|
||
> **Trace**: D5 → [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §5.5 · §9.4 · §8.2.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**:
|
||
> - eviction 순서 표기 형식(registry 필드 vs 별도 목록)과 `feature-disable` 시 UX notice 형식 — §5.5·§9.4 는 "허용 순서를 registry 에 기록"만 요구, 형식 미권고. trade-off.
|
||
|
||
값 등급별 fallback (§9.4 · §5.5 · §8.2 grounded):
|
||
|
||
| value class | quota / unavailable 시 동작 |
|
||
|---|---|
|
||
| `public-preference` (예: `COLOR_SCHEME`) | memory fallback, silent — product flow 중단 없음 |
|
||
| `opaque-cache` (예: `CHUNK_RELOAD_GUARD`) | 허용 cache evict 후 memory; guard 손실 허용 |
|
||
| correctness-critical (mutation / idempotency record) | fallback 없음 → terminal; 임의 storage fallback 금지 |
|
||
|
||
## 엣지·실패·의존
|
||
|
||
- **실패·엣지 경로**:
|
||
- Storage API 부재 / `SecurityError`(private mode·정책 차단) → `STORAGE_UNAVAILABLE`, memory-only, 대개 silent (§8.2).
|
||
- `setItem` quota 초과 → `STORAGE_QUOTA_EXCEEDED`, 허용 cache evict 후 memory, feature 영향 시 non-blocking notice (§8.2).
|
||
- previous `schemaVersion` 데이터 read → migration 또는 discard; discard 시 기본값 재생성 (D3 · §9.2).
|
||
- `sensitive-forbidden` 값 등록 시도 → 등록 거부(negative fixture, §15.2).
|
||
- correctness-critical 값의 storage 실패 → fallback 금지, terminal 처리 (D5 · §9.4).
|
||
- **다른 계약 의존**:
|
||
- [[raw/branch-notes/feature-frontend-clean-architecture-layering-contract]] (`FE-OC-002`) — `StoragePort` 를 application 이 소유하고 adapter 가 구현하는 layering·port 규약에 의존(§20 Dependency). 이 계약이 바뀌면 port 위치·주입 방식 영향.
|
||
- [[raw/branch-notes/feature-frontend-error-classification-boundary-contract]] (`FE-OC-008`) — `STORAGE_UNAVAILABLE` / `STORAGE_QUOTA_EXCEEDED` kind 정의를 consume; 본 브랜치는 매핑만.
|
||
- [[raw/branch-notes/feature-frontend-contract-registry-governance]] (`FE-OC-022`) — 8-registry single-owner·compatibility governance 에 storage snapshot 기여.
|
||
- [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] (`FE-OC-023`) — schema breaking-change migration·version-bump 판정 위임.
|
||
- [[raw/branch-notes/feature-sample-feature-slice-contract-fixture]] (`FE-OC-024`) — sample slice 가 storage key 계약을 fixture 로 사용.
|
||
- [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] (`FE-OC-010`) — token lifecycle 외부 소유; 본 registry 는 token 저장 거부만.
|
||
- [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] (`FE-OC-019`) — secret·storage 브라우저 경계 fixture 공동.
|
||
|
||
## 검증해야 할 주장
|
||
|
||
> hub 계약은 근거지만 내 프로젝트에서의 동작을 자동 보장하지 않는다. frontend repository 미생성이므로 전부 `needs-confirmation`. 검증 아티팩트는 §20 Measurable completion(namespace/version/classification/quota fallback tests) + §15.2 negative fixture 에서 도출.
|
||
|
||
| Claim | Why uncertain | How to verify | Status |
|
||
|---|---|---|---|
|
||
| physical key 규약이 실제 코드에서 raw literal 사용을 0건으로 만든다 | repo·lint 규칙 미구현 | namespace/registry lint + "raw localStorage key literal" negative fixture (§5.1·§15.2) | `needs-confirmation` |
|
||
| token key 등록 시도가 반드시 실패한다 | 강제 지점(build vs runtime) 미구현 | "token key registration attempt" negative fixture (§15.2) | `needs-confirmation` |
|
||
| `schemaVersion` mismatch 시 migration-or-discard 가 결정적으로 동작 | migration 경로 미작성 | previous-version fixture + discard/default 재생성 test | `needs-confirmation` |
|
||
| quota 초과 시 preference = memory fallback, correctness-critical = no fallback | 브라우저 quota 동작 환경차 | quota fallback 결정적 test(mock quota) + correctness-critical no-fallback assertion | `needs-confirmation` |
|
||
| classification 3분류가 모든 항목에 강제된다 | registry validation 미구현 | 미분류 항목 등록 거부 unit test (FE-GATE-005 registries) | `needs-confirmation` |
|
||
|
||
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
|
||
|
||
| 관심사 | 상태 | owner | 심각도 | 근거 |
|
||
|---|---|---|---|---|
|
||
|
||
## 마주친 문제
|
||
|
||
- 없음 — `/branch-spec` fill 단계 (구현 전).
|
||
|
||
## 묶음 (이 branch에서 파생된 자료)
|
||
|
||
<!-- GENERATED: received-delegations:start -->
|
||
### 수신한 위임
|
||
|
||
| Delegation Ref | From | Concern | Status |
|
||
|---|---|---|---|
|
||
| `DELEG-FE-009@1` | [[raw/branch-notes/feature-frontend-cache-tier-cross-tab-invalidation-contract]] | `fe.deleg.persistent-cache-key` | accepted |
|
||
<!-- GENERATED: received-delegations:end -->
|
||
|
||
<!-- GENERATED: project-contract-imports:start -->
|
||
## 가져온 프로젝트 계약
|
||
|
||
| Ref | Owner | 요약 | Branch 적용 |
|
||
|---|---|---|---|
|
||
| `FE-GATE-005@1` | [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] | unit 레벨이 실패하면 merge 를 MUST 차단하고 warning 으로 낮추면 안 됨 | 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-010@1` | [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] | skeleton은 session state를 소비하되 token lifecycle을 MUST 소유하지 않음 | import 참조로 적용 |
|
||
| `FE-OC-019@1` | [[raw/branch-notes/feature-frontend-browser-security-boundary-contract]] | browser bundle에 secret을 넣지 않고 untrusted HTML injection을 기본 금지 | import 참조로 적용 |
|
||
| `FE-OC-023@1` | [[raw/branch-notes/feature-frontend-contract-compatibility-governance]] | API/config/storage/release schema의 breaking change는 migration 또는 version bump 없이 배포하면 안 됨 | import 참조로 적용 |
|
||
<!-- GENERATED: project-contract-imports:end -->
|
||
|
||
### Sub-branches (세부 작업)
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
### 오류 기록 (이 branch 작업 중 발생)
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
### 면접 준비 (이 작업에서 나올 수 있는 면접 질문)
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
### 강의 (이 작업을 위해 학습한 강의)
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
### job-posting tie-ins (이 작업에서 파생된 글감)
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
## 관련 일일 노트
|
||
|
||
- 없음 — scaffolding 단계
|
||
|
||
## 완료 후 정리
|
||
|
||
- PR 링크: TODO
|
||
- 리뷰 메모: TODO
|
||
- 머지 결과 / 배포 환경: TODO
|
||
- **wiki 추출 대상**: 없음 — 전부 `planned` (frontend repository 미생성)
|
||
- **추출하지 않을 항목**: D1–D6 전체 — 구현·검증 evidence 확보 전까지 추출 금지
|