Files
llm-wiki/raw/branch-notes/feature-frontend-observability-logging-trace-contract.md
DongHyeonka d6dfda64ab docs(branch): 기존 7개 노트를 개정 결정·신규 위임에 정합
- 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 형식으로 정규화
2026-07-28 14:40:38 +09:00

43 KiB
Raw Permalink 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-observability-logging-trace-contract branch-note raw BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-012 project-work-item ca-skeleton-frontend-operational-contract WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-012
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
1 feature-frontend-observability-logging-trace-contract
ca-skeleton-frontend
ca-skeleton
raw/project-notes/ca-skeleton-frontend-operational-contract.md
branch
ca-skeleton
frontend
observability
error-handling
javascript
2026-07-18 in-progress e79f4a8ea9b3ea9f54126cdb47a1228194322b9fa883ca499d546f9ffa607e63
FE-OC-008@1
FE-OC-015@1
FE-OC-021@1
FE-OC-025@1

branch: feature-frontend-observability-logging-trace-contract

Layer: raw/branch-notes/ — 단일 브랜치의 TODO·결정·진행 기록. /branch-spec 로 hub 계약을 구현-준비 spec 으로 내렸다. 프론트엔드 코드가 아직 없으므로 모든 구현 주장은 planned 이며 코드 evidence 는 repository 생성 후 채운다.

부모 (필수)

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: telemetry registry·redaction·bounded queue·sink failure test가 통과한다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-TELEMETRY-001@1 telemetry는 best-effort queue와 redaction을 사용하며 sink failure가 UI를 실패시키지 않는다 TelemetryPort·queue·redaction·degradation 계약에 적용한다 raw/project-notes/ca-skeleton-frontend-operational-contract
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-REGISTRY-001@1 route, API operation, env, storage, error, query, telemetry, release token, capability를 9개 registry로 관리한다 hub §5.8이 정의한 FE-REG-TELEMETRY 스키마·초기 event를 코드 registry로 구현한다 raw/project-notes/ca-skeleton-frontend-operational-contract

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status
D1 telemetry를 best-effort non-blocking 경로로 격리한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D2 low-cardinality allowlist와 forbidden attribute redaction을 강제한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D3 bounded queue와 비재귀 drop reporting을 사용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D4 FE-REG-TELEMETRY를 event schema의 single SSOT로 사용한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D5 backend 지원 여부에 따라 trace correlation을 전파하거나 local ID로 강등한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D6 delivery transport를 adapter-owned degradation 경로로 둔다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D7 terminal failure telemetry를 bounded safe event로 제한한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed
D8 TELEMETRY_ENABLED를 composition-root kill-switch로 소비한다 local raw/project-notes/ca-skeleton-frontend-operational-contract proposed

선언한 예외

Override ID Overrides Reason Approval Status

없음.

목표

이 브랜치는 project-wide contract FE-OC-014 (telemetry 는 best-effort 이며 render·API success 를 차단하면 안 되고 PII·token 을 전송하면 안 됨) 와 그 owner decision raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 (telemetry = best-effort queue + redaction, sink failure 는 UI 를 실패시키지 않음) 를 구현자가 되묻지 않아도 코드를 쓸 수 있는 수준의 spec 으로 내린다. 핵심 불변식은 운영 격리 (operational isolation) — telemetry 실패가 사용자 경험(render/API critical path)과 완전히 분리된다는 것이다. 동시에 이 브랜치는 FE-REG-TELEMETRY registry (§5.8 event/attribute/redaction) 의 single owner 로서 hub §5.8 이 정의한 최소 스키마와 초기 event 집합을 코드 registry 로 구현하고 emit 지점을 확정하며, FE-OC-008 (실패→telemetry rule), FE-OC-021 (low-cardinality 성능 attribute), FE-OC-025 (FE-RB-004 telemetry sink failure runbook) 에 telemetry 기여 edge 를 제공한다. 등급: 전 항목 planned (repository 부재).

  • 이슈: 없음 (repository 미생성)
  • PR: 없음

범위

포함 범위

  • Best-effort 전달 불변식 — telemetry send 가 render·API critical path 를 절대 block 하지 않음, sink/queue/adapter-init 실패가 UI 를 실패시키지 않음 (FE-OC-014, raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2).
  • FE-REG-TELEMETRY registry 파일 소유 — registry 스키마와 초기 5 event 의 정의 는 hub §5.8 소유이고, 본 브랜치는 그 registry 를 코드로 구현하고 emit 지점을 확정한다(§5.8, §5.1). 자유 문자열 event 금지.
  • Redaction — low-cardinality allowlist context 만 전송, forbidden attribute(token·email·raw URL/query/body·storage value·stack) 전송 금지 (§11.1, §5.8).
  • Bounded queue + overflow 정책 + 비재귀 — bounded queue, overflow drop 정책 registry 명시, telemetry 실패를 동일 sink 로 재귀 보고하지 않음 (§11.2, §16.4).
  • Delivery degradation — local/dev console-safe sink, prod endpoint 부재/invalid 시 telemetry 만 degrade 하고 app 계속 실행 (§11.2, §16.4).
  • TELEMETRY_ENABLED kill-switch 소비 — runtime flag(default false)가 off 일 때 telemetry 전체를 무력화하는 소비 측 의미와 그 단일 적용 지점 확정, FE-RB-004 mitigation "telemetry runtime flag disable" 의 실행 가능성 보장 (§5.4, §16.4). key 선언·schema 검증 자체는 FE-OC-004 소유.
  • Trace correlation (telemetry 관점) — W3C traceparent 가 backend contract 상 허용될 때만 전파, 미지원 시 local operation ID 로 degrade, retry 는 같은 logical operation correlation 유지하되 attempt 구분 (§11.3, §8.1).
  • 기여 edgeFE-OC-008 실패→telemetry rule column, FE-OC-021 duration/attempt bucket 제공, FE-OC-025 FE-RB-004 recovery assertion.

제외 범위

의도적으로 제외 — 다른 owner 브랜치/외부 계약이 소유. 본 브랜치는 telemetry 관점의 consume/기여만 한다.

  • Error kind 정규화 taxonomy 자체FE-OC-008 owner (frontend-error-classification-boundary branch). 본 브랜치는 error_kind 를 소비만 하고 정의하지 않음.
  • Render error boundary 소유·복구FE-OC-015 owner (frontend-render-recovery-boundary branch). 본 브랜치는 boundary-catch 신호를 consume 해 ui.render.failed 를 emit 만 함.
  • Web Vitals 측정·NFR 리포트FE-OC-021 owner (raw/branch-notes/feature-web-vitals-performance-budget-contract). 본 브랜치는 low-cardinality attribute bucket 만 공급.
  • FE-RB-004 runbook 1차 소유FE-OC-025 owner (frontend-operational-runbook branch). 본 브랜치는 technical escalation 이며 diagnosis evidence field 만 공급.
  • Telemetry endpoint 의 CSP connect-src·bundle 내 secret 금지 강제FE-OC-019 owner (frontend-browser-security-boundary branch).
  • Runtime config 로딩·검증FE-OC-004 owner (frontend-env-runtime-config branch). 본 브랜치는 endpoint 값을 consume 만 함(의존, §엣지·실패·의존).
  • Token lifecycle — 외부 Keycloak / raw/branch-notes/feature-frontend-auth-session-integration-contract (FE-OC-010). telemetry 는 token 을 절대 전송하지 않음.

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

Source 정당화하는 결정
raw/project-notes/ca-skeleton-frontend-operational-contract 본 브랜치의 거의 모든 결정의 SSOT — FE-D021(§3.2), FE-OC-014(§2.1), telemetry 계약(§11), FE-REG-TELEMETRY(§5.8/§5.1), 실패 matrix telemetry column(§8.2), FE-RB-004(§16.4), TELEMETRY_ENABLED runtime key(§5.4) + boot sequence(§6.3)/config validation(§6.4)/composition root(§4.5). D1~D8 전부 이 hub 의 project decision 을 인용한다.
raw/official-docs/react-ui-library-official REACT-UI-C1 — presentation 이 React component 로 구성됨(버튼~페이지). ui.render.failed event 의 emit point 가 React component boundary catch 라는 D4 event catalog 항목을 간접 뒷받침. boundary 자체의 소유는 render-recovery branch(FE-OC-015)에 위임.

참고: §11.3 trace correlation 이 언급하는 W3C traceparent (Trace Context) 는 실제 표준이나 raw/official-docs/ 에 아직 아카이브되지 않았다. 따라서 사실로 인용하지 않고 hub §11.3 의 project decision(허용될 때만 전파)만 근거로 쓴다. 표준 자체를 근거로 삼아야 할 결정이 생기면 wiki-source-summarizer 로 먼저 아카이브한다.

TODO

각 항목 옆 증거 등급. repository 부재 → 전부 planned / needs-confirmation.

  • FE-REG-TELEMETRY registry (src/contracts/telemetry.js): hub §5.8 의 7-field 스키마와 초기 5 event 를 코드로 구현 + emit 지점 배선 — 등급: planned
  • Redaction 강제 (allowlist projection) + forbidden-attribute scan test — 등급: planned
  • Bounded queue + overflow drop 정책 + queue drain/memory test — 등급: planned
  • Sink failure / degradation test (endpoint invalid → telemetry 만 degrade, app 계속) — 등급: planned
  • Trace correlation 전파 + retry attempt 구분 test — 등급: planned
  • TelemetryPort (application) + telemetry adapter + composition-root wiring — 등급: planned
  • TELEMETRY_ENABLED=false → no-op port 주입 + zero-network/zero-queue 회귀 test (FE-RB-004 mitigation 재현) — 등급: planned
  • 구현 repository 및 검증 evidence 식별 — 등급: needs-confirmation

진행 중 메모

  • /branch-spec 로 hub §2/§3/§5/§8/§11/§16 을 내려 D1~D7 을 확정. 모든 grounding 은 hub project decision(FE-D021 중심) — 외부 official-doc 은 react-ui(간접)만 관여. web research 0건(hub 가 충분).
  • 2026-07-20 loop-back fill: coverage 감사에서 TELEMETRY_ENABLED kill-switch 소비 측 메커니즘이 미결정(MISSING_CONCERN)으로 드러나 D8 + 구현 가이드 7 을 추가했다. hub §5.4 는 key 를 선언하고 §16.4 는 그 disable 을 mitigation lever 로 요구 하지만 소비 형태는 미명시 — 사용자 소유 브랜치가 없어 본 브랜치가 소비 owner 다(FE-OC-004 는 key 선언·schema 검증만 소유). 같은 pass 에서 telemetry.delivery.dropped 의 전달 채널(비재귀 구체화)과 route_id/operation_id producer 의존을 명시했다.
  • 운영 격리(operational isolation)가 이 브랜치의 축: telemetry 는 관찰 목적이며 절대 UX 를 볼모로 잡지 않는다. 그래서 delivery guarantee 를 주장하지 않고 best-effort 로 못 박는다.

결정 사항

아래 Decision Evidence Map 의 prose mirror. 각 결정의 근거는 hub project decision.

  • 2026-07-18: Telemetry = best-effort, non-blocking — render/API critical path 를 차단하지 않고 sink failure 가 UI 를 실패시키지 않는다. 대안(delivery-guaranteed audit channel)은 regulated audit event 가 필요할 때만 별도 계약으로 분리. 근거: raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2.
  • 2026-07-18: Redaction 우선 — low-cardinality allowlist context 만 전송, token/PII/raw payload 는 forbidden. 근거: hub §11.1, §5.8.
  • 2026-07-18: Bounded queue + 비재귀 — overflow drop 정책을 registry 에 명시, telemetry 실패를 동일 sink 로 재귀 전송하지 않음. 근거: hub §11.2, §16.4.
  • 2026-07-18: FE-REG-TELEMETRY single SSOT — 자유 문자열 event 금지, 초기 5 event 고정. 근거: hub §5.8, §5.1, FE-D018.
  • 2026-07-18: Trace correlation 은 조건부 전파 — backend contract 가 허용할 때만 traceparent 전파, 아니면 local operation ID 로 degrade. 근거: hub §11.3, §8.1.
  • 2026-07-18: Delivery transport 는 adapter-owned·degradable — dev console sink, prod endpoint invalid 시 telemetry 만 degrade. 근거: hub §11.2, §4.2, §16.4.
  • 2026-07-18: 실패→telemetry 매핑은 bounded·safe (FE-OC-008 기여) — terminal 실패당 safe field 만으로 최대 1 event, abort 는 error event 미발생, TELEMETRY_FAILURE 재귀 금지. 근거: hub §8.2, §8.1.
  • 2026-07-20: TELEMETRY_ENABLED 는 composition-root 단일 지점의 kill-switch — flag 가 false(hub 기본값)면 real adapter 를 아예 구성하지 않고 no-op TelemetryPort 를 주입한다. queue·redaction·sink·counter 가 전혀 생성되지 않으므로 disable 은 "전송 억제"가 아니라 "경로 부재"다. flag 는 boot-time runtime config 이므로 in-session flip 은 없고, 다음 boot 에 반영된다. 근거: hub §5.4(TELEMETRY_ENABLED runtime·required·default false), §16.4 Mitigation("telemetry runtime flag disable"), §6.3 boot sequence, §4.5 composition root.

결정-근거 매핑

모든 Supporting Claim 은 hub project decision. [[...operational-contract]] (project link) 옆의 FE-D###·§n 은 consistency hook 상 project 링크로 안전하게 검증된다.

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 Telemetry 는 best-effort — render·API critical path 를 block 하지 않고 sink failure 가 UI 를 실패시키지 않는다 (FE-OC-014) product telemetry 는 best-effort default 유지. regulated audit event 처럼 delivery guarantee 가 필요하면 best-effort 와 분리된 별도 audit channel 계약 신설 (FE-D021 revisit trigger) raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2 project-decision repository 부재 — telemetry throw 가 render/API success 를 깨지 않음을 증명하는 non-blocking test 필요
D2 Redaction — low-cardinality allowlist context 만 전송, forbidden attribute(token·email·raw URL/query/body·storage value·stack) 전송 금지 allowlist 가 invariant(accepted-documented-only). 신규 attribute 는 registry 추가 전 low-cardinality + non-PII 검토 통과 시에만 허용; 실패하면 forbidden 분류 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.1 §5.8 project-decision redaction 은 caller 가 아니라 transport boundary(adapter)에서 강제해야 함 — forbidden-attribute scan test 로 leakage 0 증명 필요
D3 Bounded queue + overflow drop 정책 registry 명시 + telemetry 실패 비재귀 보고 queue 는 항상 bounded. drop 방향(oldest vs newest)은 event class 별 registry 선언값 — 미선언 시 기본 oldest-drop (§구현 가이드 4 의 UNSUPPORTED_IMPL_DECISION) raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2 §16.4 project-decision queue 상한 크기 미확정 — memory/queue drain test 로 bound 내 drain 증명 필요
D4 FE-REG-TELEMETRY 가 event/attribute/redaction 의 single SSOT; 자유 문자열 event 금지; 초기 5 event(app.boot.failed·api.request.failed·ui.render.failed·release.mismatch.detected·telemetry.delivery.dropped) 고정 registry-owned 유지. code generation SSOT 채택이 FE-D018 revisit trigger. ui.render.failed trigger 는 React boundary catch (REACT-UI-C1 이 presentation=React 구성을 뒷받침) raw/project-notes/ca-skeleton-frontend-operational-contract FE-D018 §5.8 §5.1; raw/official-docs/react-ui-library-official REACT-UI-C1 project-decision registry schema validation test(자유 문자열 event reject) 필요; event 별 required attribute 가 실제 발생 지점에서 수집 가능한지 미검증
D5 Trace correlation — W3C traceparent 는 backend contract 허용 시에만 전파, requestId/traceId 는 safe internal reference 로 보관, raw trace header user 미노출, 미지원 backend 는 local operation ID 로 degrade, retry 는 같은 logical operation correlation 유지하되 attempt 구분 backend contract 가 traceparent 지원 → 전파; 미지원 → local operation ID 로 degrade raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.3 §8.1 conditional-default 전파는 backend contract 의존(외부); W3C Trace Context 표준 미아카이브 → 표준 세부는 사실 인용 불가; retry 간 correlation(같은 op, distinct attempt) test 필요
D6 Delivery transport 는 adapter-owned·degradable — local/dev console-safe sink, prod endpoint 부재/invalid 면 telemetry 만 degrade 하고 app 계속, page-hide sendBeacon 은 adapter decision 이며 delivery guarantee 아님 local/dev → console sink; prod → endpoint sink; page-hide sendBeacon 은 optional(no guarantee) raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2 §4.2 §16.4 project-decision endpoint invalid boot path 가 telemetry 만 degrade(app 계속)함을 증명하는 sink-failure test 필요
D7 실패→telemetry 매핑은 bounded·safe (FE-OC-008 기여) — §8.2 각 terminal normalized failure 는 safe field(status group·attempt bucket·route ID)만으로 최대 1 event, abort 는 error event 미발생, TELEMETRY_FAILURE 는 재귀 금지 normalized error taxonomy 는 error-classification branch(FE-OC-008) 소유 — 본 브랜치는 그 kind 를 consume 해 telemetry rule column 만 구현. taxonomy 가 바뀌면 매핑 갱신 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §8.2 §8.1 project-decision error_kind registry 소유는 error-classification boundary branch(FE-OC-008) — 그 registry 미확정 시 매핑 draft 상태
D8 TELEMETRY_ENABLED kill-switch 는 composition root 단일 지점에서 소비 — false(hub default)면 real adapter 미구성 + no-op TelemetryPort 주입(queue·redaction·sink·counter 모두 미생성), true 면 D6 delivery ladder 진입. flag 는 boot-time 값이므로 in-session flip 없음(다음 boot 반영), 따라서 flip 시 stranded queue 문제가 정의상 발생하지 않음. FE-RB-004 mitigation "telemetry runtime flag disable" 은 이 경로로 실행된다 flag false → no-op(관측 0, 부작용 0); true → 정상 경로. call-site 조건 분기(if (telemetry))나 port null 주입은 채택하지 않음 — hub §4.2 상 presentation/use-case 는 TelemetryPort 만 참조하므로 disable 이 call site 로 새면 안 됨 raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §5.4 §16.4 §6.3 §4.5 §11.2 project-decision no-op vs 미구성의 구현 형태 는 hub 미명시(구현 가이드 7 의 UNSUPPORTED_IMPL_DECISION); flag off 상태에서도 product e2e 가 동일해야 함을 증명하는 both-state test 필요

구현 가이드

planned blueprint (프론트엔드 코드 부재). 경로는 hub §4.6 Planned directory blueprint + §5.1 registry owner map 에서 도출된 planned anchor 이며 repository 생성 시 변경될 수 있다. 3-rule (R1 Trace 필수 / R2 UNSUPPORTED_IMPL_DECISION / R3 no OUT_OF_BRANCH_SCOPE) 준수.

1. TelemetryPort + adapter + composition-root wiring

Trace: D1 + D6 · FE-OC-014 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §4.2 §4.6

  • UNSUPPORTED_IMPL_DECISION: port method 표면(record(event) 단일 vs record+flush+shutdown) 과 파일명은 hub 미명시 → 최소 표면(record only)을 초기 default 로 제안. trade-off: 최소 표면은 오용 여지가 적으나 page-hide flush 를 adapter 내부로 숨겨야 함.
요소 Planned 경로 책임 MUST NOT
TelemetryPort (application-owned interface) src/application/ports/ use-case/presentation 이 부르는 telemetry 계약 정의 구현·browser transport·UX 결정
telemetry adapter src/adapters/telemetry/ queue·redaction·sink 구현, port 구현 navigation/UX 결정 (hub §4.2)
composition root src/bootstrap/composition-root.js runtime config(TELEMETRY_ENABLED + endpoint)로 real adapter 또는 no-op port 를 생성·주입 (kill-switch 단일 지점 — 7 참조) business rule, call-site 조건 분기
  • presentation/use-case 는 TelemetryPort 만 참조하고 transport 를 직접 부르지 않는다 (hub §4.2 presentation MUST NOT own telemetry transport).
  • adapter 는 endpoint 값을 runtime config 에서 주입받는다 (config 로딩은 env-runtime-config branch 소유 — §엣지·실패·의존).

2. FE-REG-TELEMETRY registry

Trace: D4 · FE-REG-TELEMETRY · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D018 §5.8 §5.1

  • UNSUPPORTED_IMPL_DECISION: 없음 — 스키마 필드와 초기 event 집합은 hub §5.8 을 그대로 채택(신규 제안 아님).

Planned 경로: src/contracts/telemetry.js (single owner: 본 브랜치, hub §5.1).

registry 최소 스키마(7-field)의 owner 는 raw/project-notes/ca-skeleton-frontend-operational-contract §5.8 이다 — "§5.8 그대로" 라고 스스로 밝혔듯 복제였으므로 걷어낸다. 요약 한 줄: event 는 eventName·trigger·requiredAttributes·optionalAttributes·forbiddenAttributes·sampling·delivery 를 모두 갖고, required attribute 는 low-cardinality 만 허용한다.

초기 5 event 의 정의(trigger + required attributes)는 raw/project-notes/ca-skeleton-frontend-operational-contract §5.8 소유다. 본 절은 그 event 를 어디서 emit 하는가 만 정한다 — 정의를 옮겨 적으면 hub 가 attribute 를 바꿀 때 이 표가 조용히 낡는다(실제로 attempt_countattempt_count_bucket rename 을 놓쳤었다).

Event 본 브랜치의 emit 지점
app.boot.failed boot config/release validation 실패 경로
api.request.failed API client 의 terminal normalized failure 반환 직전
ui.render.failed render recovery boundary 의 catch 핸들러
release.mismatch.detected release check 가 mismatch 를 확정한 지점
telemetry.delivery.dropped 본 브랜치 sink adapter 의 queue drop 경로
  • 자유 문자열 event 전송 금지 (hub §5.1 ad hoc use failure). registry 미등록 event 는 build/test 에서 reject.

3. Redaction 강제

Trace: D2 · FE-OC-014 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.1 §5.8

  • 해소됨(2026-07-21) — 근거 있는 결정: redaction 메커니즘은 hub 가 정한다. raw/project-notes/ca-skeleton-frontend-operational-contract §11.1 이 "이 목록은 exhaustive default-deny allowlist다 … 목록 밖 attribute 는 transport boundary 에서 제거된다" 로 메커니즘(default-deny allowlist projection)과 강제 지점(transport boundary)을 모두 명시했다. 본 브랜치가 고른 trade-off 가 아니므로 UNSUPPORTED_IMPL_DECISION 라벨을 뗀다.
  • 허용/금지 attribute 어휘의 owner 는 raw/project-notes/ca-skeleton-frontend-operational-contract §11.1 이며 exhaustive default-deny allowlist 다. 목록을 여기에 옮겨 적지 않는다 — 옮겨 적은 사본이 hub 보다 짧으면 본 절 §2 가 선언한 event(release.mismatch.detectedactive_release_id·mismatch_kind, telemetry.delivery.droppedreason·queue_size_bucket)가 transport boundary 에서 전부 제거되어 계약이 자기모순에 빠진다.
  • 본 브랜치가 소유하는 것은 강제 방법 이다: redaction 은 adapter 의 transport boundary 에서 수행하고 caller 를 신뢰하지 않는다. forbidden-attribute scan test 가 emit payload 를 검사해 위반 시 실패(§검증).

4. Bounded queue + overflow + degradation ladder + 비재귀

Trace: D3 + D6 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.2 §16.4

  • UNSUPPORTED_IMPL_DECISION: (a) queue 상한 크기, (b) 기본 drop 방향(oldest vs newest), (c) page-hide sendBeacon 사용 여부는 hub 미명시 → 초기 default 로 oldest-drop + 유한 상한(초기 제안값, memory test 로 확정) 제안, sendBeacon 은 adapter 내부 optional. trade-off: oldest-drop 은 최신 event 를 보존하나 boot 초기 event 를 잃을 수 있음.
단계 동작 근거
정상 bounded queue 적재 → sink flush §11.2
overflow drop 정책(registry 선언; 기본 oldest-drop) 적용 + telemetry.delivery.dropped self-metric 1건 §11.2, §5.8
sink non-2xx/network 실패 product flow 계속, console-safe fallback(safe field 한정), 동일 sink 재귀 보고 금지 §16.4 Containment
adapter init 실패 telemetry 만 degrade, app 계속 §11.2
prod endpoint 부재/invalid telemetry 만 degrade, app 계속 §11.2
  • telemetry failure 를 telemetry 로 재귀 전송하지 않는다 (hub §11.2). telemetry.delivery.dropped 는 self-metric 이며 sink 실패의 원인 event 를 다시 sink 로 보내지 않는다.

telemetry.delivery.dropped 자체의 전달 채널 (비재귀 불변식의 구체화):

UNSUPPORTED_IMPL_DECISION: hub §5.8 은 telemetry.delivery.dropped 의 event shape 만 정의하고 그 event 자신이 어느 채널로 나가는지는 명시하지 않는다. hub §16.4 Diagnosis evidence 가 요구하는 산출물이 event stream 이 아니라 "dropped event count"·"queue size bucket" 이라는 점에 근거해, 아래 counter-우선 채널을 초기 default 로 제안한다. trade-off: counter 는 drop 폭주 시에도 자기 증폭이 없고 §16.4 evidence 형태와 1:1 이지만, 개별 drop 의 시점 분포(timeline)를 잃는다.

  • self-metric 은 동일 bounded queue 에 재적재(re-enqueue)하지 않는다 — full/dead queue 로 되돌리는 것은 정의상 순환이며 overflow 를 가속한다.
  • 대신 adapter 내부의 in-process 단조 counter(key = reason × queue_size_bucket, hub §5.8 required attribute 와 동형)로 집계하고, hub §16.4 Containment 의 console-safe fallback(safe field 한정)으로 즉시 관측 가능하게 한다.
  • 이 counter 는 FE-RB-004 diagnosis evidence 의 dropped event count 로 그대로 공급된다(§6 기여 edge).
  • sink 가 회복되어 정상 flush 가 성공한 이후에 한해, 누적 counter 를 aggregated event 1건으로 승격 전송하는 것은 adapter 의 optional 결정이다 — 실패 중인 sink 로는 시도하지 않으며 delivery guarantee 로 표현하지 않는다 (hub §11.2).
  • counter 자체는 sink 실패로 소실되지 않아야 하므로 queue 와 독립된 lifetime 을 가진다(document lifetime 한정, 영속화 없음 — 영속화는 storage registry owner 영역).

5. Trace correlation

Trace: D5 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §11.3 §8.1

  • UNSUPPORTED_IMPL_DECISION: local operation ID 포맷(예: operationId#attempt)은 hub 미명시 → 사용자 선택. trade-off: 짧은 포맷은 로그 가독성↑ 이나 충돌 회피를 위해 request-scoped uniqueness 보장 로직 필요.
  • W3C traceparent 는 외부 auth/backend contract 가 허용할 때만 전파 (hub §11.3).
  • backend 응답의 requestId/traceId (envelope meta, §7.3)는 safe support reference 로 내부 state 보관 가능, user 에 raw 노출 금지.
  • normalized failure shape(§8.1)의 requestId/traceId 는 optional — 존재 시 telemetry attribute 로 승격하지 않고 내부 correlation 에만 사용.
  • retry(new request)는 같은 logical operation correlation 유지하되 attempt 로 구분 (hub §11.3, §7.2 attempt).
  • trace propagation 미지원 backend 는 local operation ID 로 degrade.

6. 기여 edge (contribution, ownership 은 위임)

Trace: D7 · FE-OC-008 / FE-OC-021 / FE-OC-025 기여 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §8.2 §16.4

  • UNSUPPORTED_IMPL_DECISION: 없음 — 아래는 hub 계약 인용이며 각 owner 브랜치에 위임(R3). 본 절은 telemetry 기여 edge 만 명세.
기여 대상 본 브랜치가 제공하는 telemetry edge Owner (위임)
FE-OC-008 실패 taxonomy §8.2 Telemetry rule column 구현 — terminal 실패당 safe field 만으로 최대 1 event, abort 는 error event 미발생, raw URL/body 금지 error-classification boundary branch
FE-OC-021 NFR duration_bucket·attempt_count_bucket 등 low-cardinality attribute 공급(측정·리포트는 미소유) web-vitals-performance-budget branch
FE-OC-025 runbook FE-RB-004 diagnosis evidence field(endpoint classification·queue size bucket·dropped count·build/release ID·redaction test result) + recovery assertion 공급, 및 Mitigation "telemetry runtime flag disable" 의 실행 경로(D8, 구현 가이드 7) 보장 frontend-operational-runbook branch

7. TELEMETRY_ENABLED kill-switch 소비

Trace: D8 (+ D1 non-blocking / D6 degradation ladder) · FE-OC-014 · raw/project-notes/ca-skeleton-frontend-operational-contract FE-D021 §5.4 §16.4 §6.3 §4.5 §11.2

  • UNSUPPORTED_IMPL_DECISION: hub §5.4 는 TELEMETRY_ENABLED 를 required runtime key(default false)로 선언하고 §16.4 는 그 disable 을 mitigation lever요구하지만, 소비 형태(real adapter 미구성 + no-op port 주입 vs port 자체를 optional/null 로 두고 call site 에서 분기)는 명시하지 않는다 → no-op port 주입 을 초기 default 로 제안. trade-off: no-op 은 disable 경로를 composition root 한 곳에 가두고 call site 를 flag-무지 상태로 유지하나(hub §4.2 의 "presentation 은 TelemetryPort 만 참조" 와 정합), no-op 객체가 항상 존재하므로 "telemetry 가 꺼져 있다"는 사실이 호출자에게 보이지 않는다(관측은 boot-time config snapshot 으로만 확인 가능).

flag 상태별 구성 (composition root 분기 지점 1곳)

TELEMETRY_ENABLED composition root 동작 생성되는 것 생성되지 않는 것 근거
false (hub default, §5.4) no-op TelemetryPort 주입 port 표면(record)만 queue · redaction projection · sink/transport · dropped counter · TELEMETRY_ENDPOINT 해석 §5.4, §16.4 Mitigation
true real telemetry adapter 구성 후 주입 구현 가이드 2~5 전체 경로 §11.2, §4.5
  • no-op 의 계약: record(event) 는 인자를 읽지 않고 즉시 반환하며 throw 하지 않는다(D1 non-blocking 불변식을 flag 양쪽 상태에서 동일하게 유지). 어떤 event 도 buffer 하지 않으므로 나중에 flag 가 켜져도 소급 전송되는 event 는 없다.
  • disable 은 "전송 억제"가 아니라 "경로 부재": queue 도 counter 도 생성되지 않으므로 §11.1 redaction 위반 표면과 §11.2 overflow 표면이 동시에 0 이 된다. TELEMETRY_ENDPOINT 는 hub §5.4 상 Required: conditional — 그 조건이 곧 TELEMETRY_ENABLED=true 라는 것이 본 브랜치의 소비 측 해석이며, schema 상 conditional 강제는 FE-OC-004 소유(§엣지·실패·의존).
  • runtime flip 가능성: runtime config 는 hub §6.3 boot sequence 에서 GET /config.json (no-store) 로 boot 시 1회 로드된 뒤 §4.5 composition root 가 의존성을 구성한다. hub 에 config hot-reload 계약이 없으므로 in-session flip 은 존재하지 않는다 — flag 변경은 provider 측에서 반영한 뒤 다음 document load(boot) 부터 적용된다.
  • flip 시 이미 queue 에 쌓인 event: 위 결과로 정의상 문제가 발생하지 않는다. truefalse 는 이전 session 의 queue 를 flush 하지 않고 document 와 함께 폐기하며(§11.2 best-effort — delivery guarantee 없음이므로 손실이 계약 위반이 아님), falsetrue 는 시작 시점부터의 event 만 다룬다(no-op 이 아무것도 보관하지 않았으므로 backfill 대상 없음).
  • FE-RB-004 mitigation 충족 경로: §16.4 Mitigation 의 "telemetry runtime flag disable" 은 ① provider 의 runtime config 에서 TELEMETRY_ENABLED=false 설정 → ② 이후 boot 부터 no-op 주입 → ③ sink 호출·queue 적재·drop counter 증가가 발생 원천에서 중단 → ④ §16.4 Containment("product flow 계속")와 Recovery assertion("product e2e unaffected")이 flag 양쪽 상태에서 동일하게 성립, 의 순서로 실행된다. 이 lever 는 sink restore 없이도 즉시 사용 가능한 격리 수단이다.
  • invalid value: hub §5.4 failure column 은 TELEMETRY_ENABLED invalid 를 boot fail 로 규정하고 §6.4 는 "boolean parsing without truthy string ambiguity" 를 요구한다. 따라서 composition root 는 검증된 boolean 만 받으며 "false" 같은 문자열을 스스로 해석하지 않는다(파싱·거부는 FE-OC-004). endpoint 부재/invalid 의 telemetry degrade(§5.4)와 달리 flag invalid 는 degrade 가 아니라 boot fail 이라는 비대칭에 유의.

엣지·실패·의존

R4 캡처. sibling 브랜치 링크는 소유 계약 FE-OC-### 로만 참조(consistency hook 안전).

  • 실패·엣지 경로:
    • sink non-2xx/network 실패 → TELEMETRY_FAILURE(hub §8.2), product error 없음, console-safe/drop, 재귀 금지.
    • queue overflow → 정책(기본 oldest-drop) 적용 + telemetry.delivery.dropped self-metric, unbounded 적재 금지 (§16.4).
    • telemetry adapter init 실패 / prod endpoint 부재·invalid → telemetry 만 degrade, app 계속 (§11.2).
    • redaction miss(forbidden attribute 유출) → forbidden-attribute scan test 가 build 를 실패시켜야 함 (§검증).
    • page hide → sendBeacon best-effort, delivery guarantee 로 표현 금지 (§11.2).
    • backend 가 traceparent 미지원 → local operation ID 로 degrade (§11.3).
    • TELEMETRY_ENABLED=false (hub §5.4 기본값) → real adapter 미구성, no-op port 주입, network·queue·counter 전부 부재. app 은 정상 동작하며 FE-RB-004 mitigation lever 로 사용 (구현 가이드 7).
    • TELEMETRY_ENABLED invalid → boot fail (§5.4, degrade 아님). 파싱·거부는 FE-OC-004 소유이며 telemetry adapter 는 검증된 boolean 만 수신.
    • flag truefalse 전환 → 이전 session queue 는 flush 되지 않고 폐기 (§11.2 best-effort, delivery guarantee 없음). in-session flip 은 §6.3 boot-time config 로딩상 존재하지 않으며 다음 boot 부터 반영.
    • navigation/user abort(REQUEST_ABORTED, §8.2) → error telemetry event 미발생(interaction-only).
  • 다른 계약 의존:

검증해야 할 주장

hub 계약은 근거지만 내 프로젝트 코드의 동작을 자동 보장하지 않는다. repository 생성 후 검증. 모두 needs-confirmation.

Claim Why uncertain How to verify Status
telemetry throw/sink 실패가 render·API critical path 를 깨지 않는다 (D1) 코드 부재; non-blocking 은 wiring 방식에 의존 throwing sink 주입 후 render + API success 유지 assert 하는 sink failure test (§20 Measurable completion) needs-confirmation
forbidden attribute 가 client 를 절대 떠나지 않는다 (D2) redaction 이 transport boundary 에서 강제되는지 코드로 확인 필요 emit payload 를 검사하는 forbidden-attribute scan / redaction test; 위반 시 build 실패 needs-confirmation
bounded queue 가 planned bound 내 drain 하고 정책대로 drop 한다 (D3) queue 상한·drop 방향이 UNSUPPORTED_IMPL_DECISION memory/queue drain test (FE-RB-004 recovery assertion) needs-confirmation
자유 문자열/미등록 event 가 reject 된다 (D4) registry enforcement 미구현 FE-REG-TELEMETRY schema validation test needs-confirmation
retry 간 같은 logical operation correlation 유지 + attempt 구분 (D5) traceparent 전파는 backend contract 의존 local operation ID + attempt 구분 correlation test (MSW 로 backend 유/무 traceparent 시나리오) needs-confirmation
prod endpoint 부재/invalid 시 telemetry 만 degrade 하고 app 계속 (D6) boot 경로에서 degrade 격리 미검증 invalid endpoint boot/sink-failure matrix test needs-confirmation
TELEMETRY_ENABLED=false 에서 network 요청·queue·counter 가 전혀 생성되지 않고 product e2e 가 flag true 와 동일하다 (D8) no-op 주입이 composition root 한 곳에만 있는지, call site 로 새지 않는지 코드로 확인 필요 flag off/on both-state test — off 상태에서 telemetry 관련 network 호출 0건 assert + FE-RB-004 recovery assertion("product e2e unaffected") 양쪽 상태 재실행 needs-confirmation
telemetry.delivery.dropped self-metric 이 실패한 queue/sink 로 재진입하지 않는다 (D3 + 구현 가이드 4) counter 채널이 queue 와 독립 lifetime 인지 미검증 overflow 유발 후 비재귀 test — queue 재적재 0건 assert + dropped counter 가 FE-RB-004 diagnosis evidence 로 노출되는지 확인 needs-confirmation

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

관심사 상태 owner 심각도 근거

마주친 문제

  • 없음 — scaffolding/spec 단계 (구현 전).

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

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용
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-015@1 raw/branch-notes/feature-frontend-render-recovery-boundary-contract expected operational error와 render defect를 MUST 분리하고 reload loop를 금지 import 참조로 적용
FE-OC-021@1 raw/branch-notes/feature-web-vitals-performance-budget-contract NFR은 device/network/cache/build context와 함께 MUST 측정 import 참조로 적용
FE-OC-025@1 raw/branch-notes/feature-frontend-operational-runbook-contract boot, chunk mismatch, API degradation, telemetry failure, rollback runbook을 MUST 유지 import 참조로 적용

Sub-branches (세부 작업)

  • 없음 — scaffolding 단계

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

  • 없음 — scaffolding 단계

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

  • 없음 — scaffolding 단계

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

  • 없음 — scaffolding 단계

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

  • 없음 — scaffolding 단계

관련 일일 노트

  • 없음 — scaffolding 단계

완료 후 정리

  • PR 링크: TODO
  • 리뷰 메모: TODO
  • 머지 결과 / 배포 환경: TODO
  • wiki 추출 대상: 없음 — 전 항목 planned (repository 부재, 추출 조건 미충족)
  • 추출하지 않을 항목: D1~D8 전부 — planned 등급이므로 verified 승급 및 wiki/projects 추출 전까지 제외