Files
llm-wiki/raw/branch-notes/feature-frontend-error-classification-boundary-contract.md
T

35 KiB
Raw Blame History

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label, contract_packet_sha256, imports
title source_type status id kind project work_item inherits refines overrides depends_on contract_packet branch parent_branch related_projects governing_docs tags created target_merge status_label contract_packet_sha256 imports
branch / feature-frontend-error-classification-boundary-contract branch-note raw BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007 project-work-item ca-skeleton-frontend-operational-contract WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006
1 feature-frontend-error-classification-boundary-contract
ca-skeleton-frontend
ca-skeleton
raw/project-notes/ca-skeleton-frontend-operational-contract.md
branch
ca-skeleton
frontend
error-handling
integration
javascript
api-contract
2026-07-18 in-progress 24279f92059756981b403bc43da12c4b65488a08cc137f39a2277e0ae83dfdc7
FE-OC-006@1
FE-OC-007@1
FE-OC-009@1
FE-OC-010@1
FE-OC-011@1
FE-OC-013@1
FE-OC-014@1
FE-OC-015@1
FE-OC-016@1
FE-OC-022@1
FLOW-FE-RESP-001@1
FLOW-FE-RESP-002@1
FLOW-FE-RESP-003@1
FLOW-FE-RESP-004@1
FLOW-FE-RESP-005@1
FLOW-FE-RESP-006@1
FLOW-FE-RESP-007@1

branch: feature-frontend-error-classification-boundary-contract

Layer: raw/branch-notes/ — 단일 브랜치의 TODO·결정·진행 기록. 머지/종료 후 verified 결과는 /ingestwiki/projects/에 추출한다.

부모 (필수)

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: normalization matrix와 raw body·stack leakage negative test가 통과한다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1 boundary runtime validation은 Zod schema로 수행한다 validation failure signal을 stable frontend error kind로 정규화한다 raw/project-notes/ca-skeleton-frontend-operational-contract

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status
D1 모든 failure를 total function으로 단일 kind에 정규화한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D2 normalized failure는 safe field만 보존한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D3 FE-REG-ERROR를 error UX의 single-owner registry로 사용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D4 project trigger-to-kind matrix를 구현 계약으로 사용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D5 user copy는 userMessageKey로 간접화한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D6 recovery action을 closed vocabulary로 제한한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D7 defaultRetryable은 분류 힌트로만 사용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D8 Zod validation failure를 stage별 kind로 매핑한다 local raw/official-docs/zod-runtime-schema-validation-official.md#ZOD-VALID-C4, raw/official-docs/zod-runtime-schema-validation-official.md#ZOD-VALID-C5 proposed

선언한 예외

Override ID Overrides Reason Approval Status

없음.

목표

이 브랜치는 project-wide 계약 FE-OC-008("모든 failure 는 stable frontend error kind 로 MUST 정규화하고 raw body·stack 을 UI 에 노출하면 안 됨")을 구현 착수 가능한 상세 명세로 내린다. 핵심은 두 불변식이다. (1) Total normalization — HTTP response·adapter exception·browser exception 어느 경로든 정확히 하나의 안정 error kind(hub §5.6 의 26-kind enum)로 정규화되고, 어떤 named branch 와도 일치하지 않으면 catch-all UNKNOWN_FAILURE 로 폐기되며, 정규화되지 않은 throw 가 presentation 으로 통과하는 경로는 없다(hub §8.2 total-function 문단). (2) Redaction boundary — normalized failure 는 §8.1 의 안전 필드 집합만 담고 raw body·token·authorization header·full URL/query·stack·storage value 는 절대 포함하지 않는다. 이 브랜치는 error 계약 registry FE-REG-ERROR(src/contracts/errors.js)의 single owner 이며(hub §5.1), 그 산출물을 세 계약에 기여한다 — FE-OC-011(async terminal-error state 가 registry action 을 소비), FE-OC-015(operational failure 를 normal state 로 반환해 render boundary 로 throw 하지 않는 분리 신호 제공), FE-OC-020(negative fixture 카탈로그). 모든 진술은 코드가 없으므로 planned 등급이다.

  • 이슈:
  • PR:

범위

포함 범위

  • Total normalization function — response/adapter/browser exception → 26-kind 중 정확히 하나, 최종 catch-all UNKNOWN_FAILURE, presentation 으로의 un-normalized throw 금지 (hub §8.2, §5.6). 등급 planned.
    • 이 총함수가 곧 응답 처리 순서의 마지막 단계이며 그 stage 의 owner 는 본 branch 다 — hub §2.1.4 Flow Stage Registry FLOW-FE-RESP-008@1(application model 또는 실패 신호 → 정규화된 결과 반환; 총함수이므로 미매핑 예외는 UNKNOWN_FAILURE 로 귀결하고 throw 를 presentation 으로 통과시키지 않는다). 이 단계의 Invariants 를 바꾸려면 본 branch 가 revision 을 올려야 한다. stage 1~7 은 남의 소유라 imports 로만 pin 한다.
  • FE-REG-ERROR registry (src/contracts/errors.js) — kind/defaultRetryable/severity/userMessageKey/action/telemetryEvent/redaction 7-field row 를 26 kind 에 대해 소유 (hub §5.6, §5.1 owner map). 등급 planned.
  • Trigger → kind 매핑 매트릭스 — hub §8.2 의 트리거(network/timeout/abort/content-type/JSON/envelope/schema/HTTP status class/chunk/boot/release/storage/render/telemetry/query-cache/unknown) → kind 총함수 매핑 구현 명세 (hub §8.2, §8.5). 등급 planned.
  • Normalized failure safe-shape + redaction projection — §8.1 필드 allowlist 만 통과, 나머지 drop (hub §8.1, §7.1 "raw response body 를 log 금지"). 이게 "raw body/stack 미노출" 절반. 등급 planned.
  • action closed vocabulary 매핑 — 각 kind → retry/reauth/navigate/reload-once/contact-support/none 중 하나 + allowed-when/MUST-NOT 제약 (hub §8.4). 등급 planned.
  • Negative fixtures + total-normalization matrix test + raw-body/stack leakage negative test — §20 Measurable completion 의 두 산출물 (hub §8.5). 등급 planned.

제외 범위

의도적 제외. 각 항목은 소유 브랜치를 명시(§15.5 R3 OUT_OF_BRANCH_SCOPE 방지). 아래 sibling 링크는 hook quirk 회피를 위해 FE-OC-### 계약 ID 로만 짝지음.

근거 (필수, 최소 1개+)

Source 정당화하는 결정
raw/project-notes/ca-skeleton-frontend-operational-contract §8 Frontend Failure Taxonomy(§8.1 shape·§8.2 matrix·§8.3 retry order·§8.4 action·§8.5 fixture) + §5.6 error registry + §5.1 FE-REG-ERROR owner map — FE-OC-008 의 project-decision SSOT. D1·D2·D3·D4·D5·D6·D7 근거.
raw/official-docs/zod-runtime-schema-validation-official FE-D007(boundary runtime validation = Zod). .parse() 실패 시 granular ZodError throw(ZOD-VALID-C4.safeParse() discriminated union(ZOD-VALID-C5) 가 SCHEMA_MISMATCH/ENVELOPE_MISMATCH 매핑의 소비 대상 신호. D8 근거. 단 validator 소유는 sibling(FE-OC-007).

TODO

각 항목 옆에 증거 등급 표기. 현재 frontend 코드가 없으므로 전부 planned.

  • FE-REG-ERROR registry src/contracts/errors.js — 26-kind × 7-field row 정의 (D3/D4/D5/D6) — 등급: planned
  • adapters/http total normalization function — dispatch 순서 + catch-all + safe-shape projection (D1/D2/D4/D7/D8) — 등급: planned
  • Trigger → kind 매핑 매트릭스 구현 (D4) — 등급: planned
  • Redaction / safe-shape projection — 필드 allowlist + drop rule (D2/D5) — 등급: planned
  • Total-normalization matrix test + raw-body/stack leakage negative test + §8.5 8종 negative fixture (D1/D2/D4) — 등급: planned

진행 중 메모

없음 — /branch-spec 자동 채움 단계. 코드 미착수.

결정 사항

아래 8개 결정은 Decision Evidence Map 의 prose mirror. 근거는 대부분 hub 의 project decision(§8/§5.6)이며, D8 만 외부 official-doc(Zod)이 병행 근거.

  • 2026-07-19: 모든 failure 를 total function 으로 단일 kind 정규화 / 이유: presentation 이 raw exception·status 로 분기하면 계약이 깨지고 leakage 발생 / 검토한 대안: page 별 ad hoc try/catch(hub §5.1 FE-REG-ERROR "raw status/message 로 UI 분기" = ad hoc failure) — 배포 0회 throwaway 에서만 / 근거: hub §8.2 total-function 문단, §5.6.
  • 2026-07-19: normalized failure 는 §8.1 safe 필드 집합만; raw body·token·header·URL·stack·storage value drop / 이유: FE-OC-008 의 "raw body/stack 미노출" 강제 / 검토한 대안: 전체 error object 전달 후 UI 에서 마스킹 — 유출 위험으로 기각 / 근거: hub §8.1, §7.1.
  • 2026-07-19: FE-REG-ERROR 를 error kind → 기본 UX 의 단일 owner registry 로 고정 / 이유: kind/action/userMessageKey/redaction 을 code 전역에서 재정의하면 single-owner 계약 위반 / 검토한 대안: 각 adapter 가 로컬 enum 소유 — governance 붕괴로 기각 / 근거: hub §5.6, §5.1.
  • 2026-07-19: hub §8.2 trigger→kind 매핑(31-row / 고유 kind 26종)을 구현 매트릭스로 채택 / 이유: 트리거별 정규화 결과를 명세로 고정해야 total 성 검증 가능 / 검토한 대안: 상위 status class 만 매핑하고 나머지는 generic — negative fixture 통과 불가로 기각 / 근거: hub §8.2, §8.5.
  • 2026-07-19: user copy 는 userMessageKey 간접화, severity(telemetry routing)와 분리, raw backend message 금지 / 이유: 다국어·문안 변경·PII 유출 방지 / 검토한 대안: backend error.message 직접 표시 — §5.6 금지 / 근거: hub §5.6.
  • 2026-07-19: action 은 6개 closed vocabulary 로 제한 / 이유: 무한 spinner·history loop·반복 reload 같은 UX anti-pattern 을 계약으로 차단 / 검토한 대안: 자유 문자열 action — §8.4 제약 강제 불가로 기각 / 근거: hub §8.4, §5.6.
  • 2026-07-19: defaultRetryable 은 분류 힌트일 뿐 재시도 결정이 아님 / 이유: 재시도 루프는 api-client 소유(method/idempotency/cap 조합), 분류는 요청을 발행하지 않음 / 검토한 대안: 분류 계층이 retryable=true 를 보고 직접 재시도 — safe/idempotency 조건 무시로 storm 위험, 기각 / 근거: hub §5.6(defaultRetryable override 가능), §8.3, §8.2 note.
  • 2026-07-19: schema/envelope invalid 는 runtime-schema-validation 의 ZodError 를 소비해 SCHEMA_MISMATCH/ENVELOPE_MISMATCH 로 매핑, safe issue-path count + schema ID 만 보존 / 이유: validator 소유는 sibling, 분류는 결과 계약만 소비 / 검토한 대안: 분류 계층에서 zod schema 직접 실행 — 소유 경계 위반, 기각 / 근거: Zod ZOD-VALID-C4/ZOD-VALID-C5, hub §8.2·§5.6.

결정-근거 매핑

Supporting Claims 는 hook quirk 회피를 위해 FE-D### 를 hub 경로에만 붙인다(sibling branch 링크 근처에 두지 않는다).

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 모든 failure(response·adapter·browser exception)를 total function 으로 정확히 하나의 26-kind 로 정규화; 불일치·mapper 실패 시 catch-all UNKNOWN_FAILURE; un-normalized throw 의 presentation 통과 금지 (FE-OC-008) client SPA 가 공유 backend 계약을 소비하고 배포·라우트가 존재하는 한 이 default 유지 / ad hoc page-local try/catch 는 route 1개·외부 API 0개·배포 0회 throwaway prototype 일 때만(hub §0.4 escape) raw/project-notes/ca-skeleton-frontend-operational-contract.md §8.2 total-function 문단·§5.6 enum project-decision 총함수성은 exhaustive matrix test 로만 증명 가능(§8.5) — 미구현 시 mapper 누락 경로가 leak
D2 normalized failure 는 §8.1 safe 필드(kind/code/httpStatus?/retryable/operationId/attemptCount/requestId?/traceId?/userMessageKey/action/causeClass)만 담고 raw body·token·authorization header·full URL/query·stack·storage value 는 drop (FE-OC-008) 모든 kind·모든 경로에서 불변(FE-OC-008 이 무조건 강제) / 예외 없음 — 예외 필요 시 FE-OC-008 자체 변경 절차(hub §3.3) ...frontend-operational-contract.md §8.1 shape·§7.1 "raw response body 를 log 금지"·§8.2 telemetry 열 project-decision leakage 는 negative test(직렬화 후 금지 필드 부재 assert)로만 확인 — 이게 FE-OC-008 minimum evidence
D3 FE-REG-ERROR(src/contracts/errors.js)를 error kind→기본 UX 의 single-owner registry 로 고정; kind/defaultRetryable/severity/userMessageKey/action/telemetryEvent/redaction 7-field 8-registry governance(hub FE-D018)가 유효한 한 registry-first / code generation SSOT 채택 시 재검토 ...frontend-operational-contract.md §5.6·§5.1(FE-REG-ERROR owner=this branch, ad hoc=raw status/message 분기); ...frontend-operational-contract.md FE-D018 project-decision registry snapshot·single-owner scan 강제는 FE-OC-022 sibling 소유 — 본 브랜치는 스키마·row 만
D4 hub §8.2 trigger→kind 매핑(31-row / 고유 kind 26종)을 구현 매트릭스로 채택; 각 트리거는 정확히 하나의 kind, §8.5 8종 negative fixture 로 검증 backend 가 structured JSON envelope + 표준 HTTP status 를 제공하는 한 유지 / backend protocol 이 근본적으로 다르면(hub 가정 C 무효) 매트릭스 재도출 ...frontend-operational-contract.md §8.2 matrix·§8.5 fixtures project-decision 일부 row 는 sibling 이 실패 신호를 생성해야 성립(schema→FE-OC-007, status/retry→FE-OC-009) — 그 계약 shape 미확정 시 매핑 재조정
D5 user copy 는 userMessageKey 간접화, severity(telemetry routing hint)와 분리, raw backend error.message 표시 금지 다국어/문안 거버넌스가 존재하는 한 항상 keyed / 대안 없음 — raw message 표시는 §5.6 이 금지 ...frontend-operational-contract.md §5.6(userMessageKey·severity rule) project-decision message key → 실제 copy 카탈로그 소유(i18n)는 본 브랜치 밖 — 미정 시 key 계약만 고정
D6 각 kind 는 6개 closed action(retry/reauth/navigate/reload-once/contact-support/none) 중 하나로 매핑, §8.4 allowed-when/MUST-NOT 제약 준수 UX 계약이 유지되는 한 closed set / product 가 새 recovery 모드를 요구하면 §8.4 확장 후 registry 갱신 ...frontend-operational-contract.md §8.4 vocabulary·§5.6 action field project-decision action 의 실제 UI 실행은 async-ui(FE-OC-011)·render-recovery(FE-OC-015) 소유 — 본 브랜치는 kind→action 계약만
D7 defaultRetryable 은 분류 힌트일 뿐 재시도 결정·루프가 아님; 분류 계층은 어떤 요청도 발행하지 않음, request context override 가능 재시도 정책이 api-client(FE-OC-009) 소유인 한 힌트-only / 대안(분류가 직접 재시도)은 method+idempotency+cap 조건을 통합 소유하도록 scope 병합 시에만 ...frontend-operational-contract.md §5.6(defaultRetryable override 가능)·§8.3 retry decision order·§8.2 note("retryable=true 는 필요조건이지 충분조건 아님") project-decision (delegated boundary) 힌트와 실제 정책이 어긋나면(backend retryable=true 지만 unsafe mutation) storm — 통합 테스트로 경계 검증 필요
D8 content-type/JSON/envelope/payload invalid 는 runtime-schema-validation 이 낸 ZodError 를 소비해 CONTENT_TYPE_MISMATCH/MALFORMED_JSON/ENVELOPE_MISMATCH/SCHEMA_MISMATCH 로 매핑, schema ID + safe issue-path count 만 보존 FE-D007(Zod boundary validation)이 유효한 한 소비-매핑 / bundle budget·generated schema pipeline 이 대체안을 요구하면 재검토(hub FE-D007 revisit) raw/official-docs/zod-runtime-schema-validation-official.md#ZOD-VALID-C4, #ZOD-VALID-C5; ...frontend-operational-contract.md FE-D007·§8.2 해당 row·§5.6 official-vendor-doc + project-decision ZodError → 어느 kind(envelope vs payload)인지는 sibling 이 어느 단계에서 던졌는지에 의존 — 처리 순서(§7.3 4~6단계) 계약 미확정 시 매핑 모호

구현 가이드

planned blueprint. 경로는 hub §4.6 Planned directory blueprint + §5.1 owner map 에서 유도되므로 grounded 하지만 repository 생성 시 바뀔 수 있어 전체 planned. sibling 링크가 필요한 detail 은 §범위 Out of scope 로 위임했고 여기 남기지 않는다(R3).

1. FE-REG-ERROR 계약 registry (src/contracts/errors.js)

Trace: D3 + D4 + D5 + D6 / FE-OC-008·FE-REG-ERROR·hub §5.6·§8.2·§8.4. 26-kind enum(hub §5.6) 각각에 대해 7-field row.

  • UNSUPPORTED_IMPL_DECISION: code 필드 포맷(§8.1 은 code 존재만 명시, 포맷 미규정) → <KIND> 접미 없는 안정 문자열 상수 채택. trade-off: kind 와 1:1 이면 code 잉여지만, backend error.code(§7.3)와 대응시키려면 별 축이 필요 — 초기엔 kind 파생 상수로 두고 backend code 매핑표는 추후.
  • UNSUPPORTED_IMPL_DECISION: userMessageKey 명명 스킴(§5.6 은 "key" 만 요구, 규칙 미규정) → error.<kind_snake>.message 제안(planned). trade-off: i18n 카탈로그 소유 밖이므로 key 계약만 고정, 실제 문안은 미정.
Field 규칙(hub §5.6) 이 브랜치 명세
kind frontend stable enum §5.6 26-kind enum 그대로, rename 금지
defaultRetryable request context override 가능 boolean 기본값; 실제 재시도는 D7 대로 미실행
severity telemetry routing hint, user copy 분리 enum(예: low/warn/error) — telemetry 소비, D5 대로 copy 와 분리
userMessageKey raw backend message 금지 key 상수(UNSUPPORTED_IMPL_DECISION 스킴)
action 6-value closed set D6 vocabulary 중 하나
telemetryEvent registry event 매핑 FE-REG-TELEMETRY event 참조(소유는 FE-OC-014, 여기선 참조만)
redaction cause/body/header drop rule D2 safe-shape 와 일치하는 drop rule id

2. Total normalization 함수 (adapters/http error mapper)

Trace: D1 + D2 + D4 + D7 + D8 / FE-OC-008·hub §8.2·§8.1·§7.3(처리 순서 4~8단계). adapters/http 가 "envelope/schema/error mapping" 을 소유(hub §4.2).

  • UNSUPPORTED_IMPL_DECISION: 정규화 함수 파일/심볼명(hub 는 adapters/http/ 폴더와 src/contracts/errors.js registry 만 grounding, 함수명 미규정) → adapters/http/normalize-failure.js 단일 export 제안. trade-off: 이름은 임의지만 "단일 진입 + adapters/http 내부" 두 제약만 지키면 계약 동등.
  • UNSUPPORTED_IMPL_DECISION: dispatch 메커니즘(§8.2 는 총함수·catch-all 만 요구, switch vs lookup table 미규정) → 트리거 판별 → kind lookup 순서 dispatch 제안. trade-off: lookup table 은 registry 대조가 쉽고 switch 는 분기 명시적 — 총함수성만 test 로 보장하면 무관.
  • UNSUPPORTED_IMPL_DECISION: causeClass internal allowlist 실제 값(§8.1 "internal allowlist only" 만, 목록 미열거) → 초기 allowlist(예: network/parse/schema/auth/http-status/browser-storage/render/unknown) 제안(planned). trade-off: allowlist 밖 값은 unknown 으로 접어 leak 방지, 세분화는 telemetry 요구에 따라 확장.

처리 순서(§7.3 4~8단계 하류에서 호출됨, 요청 발행 없음):

input = { transportOutcome | thrownValue, requestContext }
1. aborted(navigation/user/superseded) 이면 REQUEST_ABORTED
2. network-level opaque 실패면 NETWORK_UNREACHABLE / timeout 이면 REQUEST_TIMEOUT
3. content-type/JSON/envelope/payload 실패 신호(sibling 생성)면 D8 매핑
4. HTTP status class 면 §8.2 status row 매핑(auth/authz/not-found/conflict/validation/rate/server/generic)
5. chunk/boot/release/deploy/storage/render/telemetry/query-cache 트리거면 해당 kind
6. 위 어디에도 안 맞거나 mapper 자체 throw 면 UNKNOWN_FAILURE(catch-all)
7. 매핑 결과를 §3 safe-shape 로 projection 후 반환 (raw value 폐기)

3. Trigger → kind 매핑 매트릭스

Trace: D4 + D8 / hub §8.2 (31-row / 고유 kind 26종 — row 기준으로 세면 같은 kind 로 매핑되는 status row 5개가 누락된다)·§8.5. 아래는 hub §8.2 를 이 브랜치의 in-scope(=여기서 정규화 산출) 관점으로 재기술한 것이며, "생성 소유"가 sibling 인 트리거는 소비만 표시(값 재정의 아님).

  • UNSUPPORTED_IMPL_DECISION: 없음 — 모든 row 는 hub §8.2 가 trigger·kind·retry·fallback·UX·telemetry 를 직접 grounding.
트리거 그룹(§8.2) 산출 kind 생성 소유 본 브랜치 역할
network opaque / total timeout / abort NETWORK_UNREACHABLE·REQUEST_TIMEOUT·REQUEST_ABORTED api-client transport(FE-OC-006) 소비→정규화
content-type/JSON/envelope/payload invalid CONTENT_TYPE_MISMATCH·MALFORMED_JSON·ENVELOPE_MISMATCH·SCHEMA_MISMATCH schema-validation(FE-OC-007) 소비→정규화(D8)
401/403/404/409/422/other-4xx/429/5xx AUTH_REQUIRED·FORBIDDEN·NOT_FOUND·CONFLICT·VALIDATION_REJECTED·UNKNOWN_CLIENT_FAILURE·RATE_LIMITED·SERVER_FAILURE api-client status(FE-OC-006) 소비→정규화, defaultRetryable 힌트만(D7)
auth attach/recovery adapter 실패 AUTH_INTEGRATION_FAILURE auth/api-client(FE-OC-010) 소비→정규화
chunk/boot/release/deploy CHUNK_LOAD_FAILURE·BOOT_CONFIG_FAILURE·RELEASE_MANIFEST_FAILURE·DEPLOY_MISMATCH bootstrap/release(FE-OC-015/FE-OC-016) 소비→정규화
storage unavailable/quota STORAGE_UNAVAILABLE·STORAGE_QUOTA_EXCEEDED storage(FE-OC-013) 소비→정규화
render throw / telemetry fail / query-cache fail / unknown RENDER_FAILURE·TELEMETRY_FAILURE·QUERY_CACHE_FAILURE·UNKNOWN_FAILURE 각 owner / catch-all 소비→정규화, 최종 catch-all 소유

4. Redaction & safe-shape projection

Trace: D2 + D5 / hub §8.1·§7.1·§8.2 telemetry 열. 정규화 함수 마지막 단계(§2 step 7).

  • UNSUPPORTED_IMPL_DECISION: projection 구현 방식(§8.1 은 필드 집합만, allowlist-copy vs blocklist-delete 미규정) → allowlist-copy(안전 필드만 새 객체로 복사) 제안. trade-off: blocklist-delete 는 신규 raw 필드 추가 시 leak 위험 — allowlist 가 fail-closed 이므로 채택.
  • 통과 허용(allowlist): §8.1 필드 집합 그대로.
  • 항상 drop: raw response body, token, authorization header, full URL/query, stack, storage value(§8.1) + backend raw error.message(D5, §5.6).
  • telemetry projection: §8.2 telemetry 열의 kind별 safe 항목만(예: status group·attempts·elapsed bucket·schema ID·safe issue-path count) — raw URL·body·principal·token 금지. 실제 전송은 FE-OC-014 소유(여기선 payload 계약만).

5. test 카탈로그 (§20 Measurable completion)

Trace: D1 + D2 + D4 / hub §8.5·§20("total normalization matrix + raw body/stack leakage negative tests"). FE-OC-020 기여.

  • UNSUPPORTED_IMPL_DECISION: test 파일 경로·러너별 배치(hub §4.6 은 tests/unit|component|... 폴더만) → tests/unit/error-classification/* 배치 제안. trade-off: 경로 임의, "unit 레벨 + registry/mapper 대상" 계약만 유지.
Fixture(§8.5) 기대 정규화 결과
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 실패 RELEASE_MANIFEST_FAILURE
QueryCachePort adapter throw / invalid result QUERY_CACHE_FAILURE
unregistered 418/기타 unmapped 4xx UNKNOWN_CLIENT_FAILURE
thrown non-Error / symbol / mapper exception UNKNOWN_FAILURE
총함수 matrix test(추가) 26-kind 전체 트리거 exhaustive → 정확히 1 kind
leakage negative test(추가) 정규화 결과 직렬화 후 body/token/header/URL/stack/storage value 부재 assert

엣지·실패·의존

  • 실패·엣지 경로:
    • Mapper 자체 throw → 최종 catch-all 이 raw value 폐기 후 UNKNOWN_FAILURE 반환(§8.2 total-function 문단). 정규화 실패로 인한 un-normalized throw 는 계약상 존재 불가.
    • Unmapped 4xx(예: 418) → UNKNOWN_CLIENT_FAILURE; unmapped thrown value(non-Error/symbol) → UNKNOWN_FAILURE(§8.5).
    • 이미 정규화된 failure 재진입 → 재정규화는 idempotent 여야 함(같은 kind 유지) — Claims To Verify 로 승격.
    • registry 미등록 kind 사용 → registry 가 closed enum 이므로 컴파일/lint 단계 차단이 이상적(강제는 FE-OC-022 governance sibling).
    • defaultRetryable=true 이지만 unsafe mutation → 분류는 힌트만 노출, 재시도 미실행(D7). 실제 안전성은 api-client 가 method/idempotency/cap 으로 최종 판단.
  • 다른 계약 의존(hook quirk 회피: sibling 링크는 FE-OC-### 로만 짝지음):

검증해야 할 주장

Claim Why uncertain How to verify Status
정규화가 진짜 total 이다 — 어떤 경로도 un-normalized 로 presentation 도달 안 함 코드 미존재, mapper 누락 분기 가능 exhaustive trigger matrix test + mapper-throws fixture → UNKNOWN_FAILURE (§8.5) needs-confirmation
normalized failure 에 raw body/stack/token/header/URL/storage value 가 유출되지 않는다 allowlist projection 미구현 leakage negative test — 결과 직렬화 후 금지 필드 부재 assert (FE-OC-008 minimum evidence) needs-confirmation
26-kind 각각 정확히 1 registry row + closed action 1개를 갖는다 registry 미작성 registry snapshot test + action ∈ 6-set 검증 needs-confirmation
분류 계층은 어떤 요청도 발행하지 않는다(재시도는 api-client 소유) 힌트/정책 경계가 코드로 미분리 분류 함수 단위 test 에서 fetch/network mock 호출 0회 assert needs-confirmation
ZodError → envelope vs payload kind 매핑이 처리 순서와 정합 sibling 처리 단계 계약 미확정 schema-invalid fixture(envelope-level, payload-level 각각) → ENVELOPE_MISMATCH/SCHEMA_MISMATCH needs-confirmation
재정규화가 idempotent 하다(이미 정규화된 failure 재진입 시 동일 kind) 재진입 경로 미설계 정규화 결과를 재입력 → 동일 kind assert planned

관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)

/coverage가 채우는 생성물이며 손으로 유지하지 않는다.

관심사 상태 owner 심각도 근거
TODO — /coverage 실행 전 missing (없음) 미평가 TODO

마주친 문제

없음 — scaffolding 단계

묶음 (이 branch에서 파생된 자료)

가져온 흐름 단계

Stage Ref Order Owner Input Action Output
FLOW-FE-RESP-001@1 1 raw/branch-notes/feature-api-client-response-envelope-contract HTTP 요청 transport 완료 대기 raw Response
FLOW-FE-RESP-002@1 2 raw/branch-notes/feature-api-client-response-envelope-contract raw Response content-type 기대값 검사 본문 판독 가능 Response
FLOW-FE-RESP-003@1 3 raw/branch-notes/feature-api-client-response-envelope-contract 본문 판독 가능 Response JSON parse unvalidated JSON
FLOW-FE-RESP-004@1 4 raw/branch-notes/feature-runtime-schema-validation-contract unvalidated JSON envelope 공유 스키마 검증 discriminated envelope
FLOW-FE-RESP-005@1 5 raw/branch-notes/feature-runtime-schema-validation-contract discriminated envelope success/failure 분기 검증 분기 확정 envelope
FLOW-FE-RESP-006@1 6 raw/branch-notes/feature-runtime-schema-validation-contract 분기 확정 envelope payload per-operation 스키마 검증 검증된 payload(deep clone)
FLOW-FE-RESP-007@1 7 raw/branch-notes/feature-boundary-mapper-viewmodel-contract 검증된 payload DTO → application model 매핑 application model

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용
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-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-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-022@1 raw/branch-notes/feature-frontend-contract-registry-governance 8개 registry는 single primary owner와 compatibility impact를 MUST 기록 import 참조로 적용

Sub-branches (세부 작업)

없음 — scaffolding 단계

오류 기록 (이 branch 작업 중 발생)

없음 — scaffolding 단계

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

없음 — scaffolding 단계

강의 (이 작업을 위해 학습한 강의)

없음 — scaffolding 단계

job-posting tie-ins (이 작업에서 파생된 글감)

없음 — scaffolding 단계

관련 일일 노트

없음 — scaffolding 단계

완료 후 정리

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