Files
llm-wiki/raw/branch-notes/feature-frontend-multi-protocol-api-transport-contract.md

32 KiB

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, imports, delegates, accepts_delegations, contract_packet, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label
title source_type status id kind project work_item inherits refines overrides depends_on imports delegates accepts_delegations contract_packet branch parent_branch related_projects governing_docs tags created target_merge status_label
branch / feature-frontend-multi-protocol-api-transport-contract branch-note raw BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-031 project-work-item ca-skeleton-frontend-operational-contract WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-031
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001@1
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PROTOCOL-001@1
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-005
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-006
WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-007
FE-GATE-030@1
FE-OC-006@1
FE-OC-007@1
FE-OC-008@1
FLOW-FE-RESP-004@1
FLOW-FE-RESP-005@1
FLOW-FE-RESP-006@1
DELEG-FE-010@1
1 feature-frontend-multi-protocol-api-transport-contract
ca-skeleton-frontend
ca-skeleton
raw/project-notes/ca-skeleton-frontend-operational-contract.md
branch
ca-skeleton-frontend
api
protocol
graphql
grpc-web
2026-07-28 in-progress

branch: feature-frontend-multi-protocol-api-transport-contract

부모 (필수)

형제 branch (같은 부모, 이번 확장에서 함께 생성):

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 2
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: protocol별 성공/실패 정규화와 gateway fallback fixture가 통과한다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-CAPABILITY-001@1 신규 runtime capability 6종은 FE-REG-CAPABILITY flag로 default OFF이며 활성화는 owner·gate·runbook을 동반한다 CAP_FE_ALT_PROTOCOL 을 이 branch 가 소유하고 default OFF 로 유지한다 raw/project-notes/ca-skeleton-frontend-operational-contract
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PROTOCOL-001@1 transport default는 REST이고 GraphQL·gRPC-Web·Connect-Web은 FE-REG-API의 protocol 필드로 opt-in하며 미지원 환경은 REST gateway로 fallback한다 FE-REG-API.protocol 값에 따른 adapter 선택 규칙에 적용한다 raw/project-notes/ca-skeleton-frontend-operational-contract
DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-VALIDATION-001@1 boundary runtime validation은 Zod schema로 수행한다 codec 디코드 결과도 예외 없이 스키마 검증을 거친다 raw/project-notes/ca-skeleton-frontend-operational-contract

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status
D1 이 branch 는 신규 port 를 정의하지 않는다. GraphQL·gRPC-Web·Connect-Web adapter 는 기존 ResourceQueryPort/ResourceCommandPort 를 구현한다 refines DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PROTOCOL-001@1 UNSUPPORTED_DECISION — 조사 후에도 외부 근거 없음. trade-off: 프로토콜별 port 를 만들면 use case 가 프로토콜을 알게 되어, backend 가 REST 에서 gRPC 로 옮길 때 use case 를 다시 써야 한다. 비용은 프로토콜 고유 기능(양방향 스트림 등)이 필요해질 때 port 를 새로 뚫어야 하는 것 proposed
D2 transport status 만으로 성공을 판정하지 않는다. protocol 별 성공 판정 함수가 별도로 존재한다 local raw/official-docs/graphql-over-http-draft-status-errors.md#C3 (상태 코드와 무관하게 본문 처리), raw/official-docs/grpc-connect-status-codes-error-model.md#C3 (status 는 transport 와 별도), #C5 (Connect 는 non-200) proposed
D3 GraphQL 응답에 errors 가 있으면 PARTIAL_RESULT_FAILURE 로 정규화한다. 규격은 이를 "successful execution" 이라 부르므로 이 결정은 의도적 이탈이다 local raw/official-docs/graphql-over-http-draft-status-errors.md#C4 (규격의 명명), #C6 (data: null 이면 errors 가 반드시 있음) proposed
D4 GraphQL 성공 판정은 상태 코드가 아니라 본문의 data·errors 구조로 한다. 200 만 검사하지 않는다 local raw/official-docs/graphql-over-http-draft-status-errors.md#C1 (data+errors 는 294 권고), #C2 (data 있으면 2xx), #C3 (상태 코드 무관 처리) proposed
D6 grpc-status → 재시도 가능 여부 매핑은 우리 프로젝트 결정으로 등록하고 그 근거를 남긴다. 규격 인용으로 대신하지 않는다 local raw/official-docs/grpc-connect-status-codes-error-model.md#C1 (코드 목록은 확정), #C2 (재시도 판정은 애플리케이션 몫이라고 규격이 명시) proposed
D7 gRPC-Web adapter 와 Connect adapter 를 분리한다. 성공 판정 코드를 공유하지 않는다 local raw/official-docs/grpc-connect-status-codes-error-model.md#C5 (Connect 오류는 non-200), #C6 (Connect 는 trailer 미사용), #C7 (gRPC-Web 은 다른 프로토콜) proposed

deferred (이번 회차 조사 범위 밖): D8 — persisted-document ID 기반 GraphQL 요청의 전송 방식(GET vs POST, 캐시 가능성, media type 협상). GraphQL over HTTP draft §5·§6.2 를 따로 읽어야 하며, 이번 조사는 §6.4 상태 코드·오류 처리에 한정했다.

선언한 예외

해당 없음.

가져온 artifact 계약

Artifact Ref Owner Producer Schema Ref

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용
FE-GATE-030@1 raw/project-notes/ca-skeleton-frontend-operational-contract protocol 별 성공/실패 정규화 fixture 가 실패하면 merge 를 MUST 차단 이 branch 가 owner 로서 fixture 와 report 를 산출
FE-OC-006@1 raw/branch-notes/feature-api-client-response-envelope-contract 모든 HTTP는 shared client를 MUST 통과하고 timeout·abort·response parsing을 page에서 구현하면 안 됨 protocol adapter 도 shared client 위에 얹힌다
FE-OC-007@1 raw/branch-notes/feature-runtime-schema-validation-contract JSON envelope와 payload는 boundary에서 runtime schema를 MUST 통과 디코드 후 검증을 DELEG-FE-010 으로 위임
FE-OC-008@1 raw/branch-notes/feature-frontend-error-classification-boundary-contract 모든 failure는 stable frontend error kind로 MUST 정규화하고 raw body·stack을 UI에 노출하면 안 됨 protocol 실패 3종의 정규화 대상

수신한 위임

없음. 이 branch 는 DELEG-FE-010 의 delegator 다.

가져온 흐름 단계

Stage Ref Order Owner Input Action Output
FLOW-FE-RESP-004@1 4 feature-runtime-schema-validation-contract unvalidated JSON envelope 공유 스키마 검증 discriminated envelope
FLOW-FE-RESP-005@1 5 feature-runtime-schema-validation-contract discriminated envelope success/failure 분기 검증 분기 확정 envelope
FLOW-FE-RESP-006@1 6 feature-runtime-schema-validation-contract 분기 확정 envelope payload per-operation 스키마 검증 검증된 payload(deep clone)

목표

GraphQL·gRPC-Web·Connect-Web adapter 가 기존 ResourceQueryPort/ResourceCommandPort 를 구현하도록 고정하고, protocol 별 성공/실패 판정을 정규화된 failure 로 매핑한다. 이 계약이 없으면 200 OK + errors[] 응답이 success 로 반환되어 빈 화면이 정상처럼 보이고, HTTP 200 + grpc-status: 13 이 성공으로 처리된다.

  • 이슈:
  • PR:

범위

포함 범위

  • FE-REG-APIprotocol·operationRef·transferMode 소비와 adapter 선택
  • GraphQL codec — persisted-document ID 기반 요청, errors[] 처리
  • gRPC-Web·Connect-Web codec — protobuf 인코딩/디코딩, grpc-status ↔ 정규화 kind 매핑
  • REST gateway fallback (disabledFallback: degraded-alternative)
  • 신규 실패 3종 정규화: PROTOCOL_STATUS_MISMATCH·CODEC_DECODE_FAILURE·PARTIAL_RESULT_FAILURE
  • CAP_FE_ALT_PROTOCOL capability 행 소유

제외 범위

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

Source 정당화하는 결정
[[docs/superpowers/specs/2026-07-28-ca-skeleton-frontend-runtime-adapter-features-design]] §5.2·§6.2 신규 port 0개 결론과 FE-REG-API 확장
raw/official-docs/zod-runtime-schema-validation-official 디코드 후 검증의 상위 근거
raw/official-docs/graphql-over-http-draft-status-errors D3 errors 응답 정규화가 규격 이탈임을 밝히는 근거 · D4 상태 코드가 아니라 본문으로 성공 판정
raw/official-docs/grpc-connect-status-codes-error-model D2 protocol 별 성공 판정 분리 · D6 재시도 판정이 우리 결정인 근거 · D7 gRPC-Web 과 Connect 를 분리하는 근거
raw/project-notes/ca-skeleton-frontend-operational-contract §2.1.4·§7.3·§8.2 응답 흐름 8단계와 실패 정규화

근거 등급 경계: 2026-07-28 /branch-spec 조사로 세 프로토콜의 오류 표현 방식은 규격 근거를 확보했다. 다만 두 가지를 구분해야 한다. (1) gRPC 코드 목록(0~16)은 규격이 확정해 주지만, 어떤 코드가 재시도 가능한지는 규격이 명시적으로 애플리케이션에 위임한다grpc-connect-status-codes-error-model#C2. 즉 매핑표는 "규격 확인 후 채운다" 가 아니라 "우리가 정하고 근거를 남긴다" 다. (2) GraphQL over HTTP 는 draft 이며, 그 규격은 field error 상황을 오히려 "successful execution" 이라 부른다(graphql-over-http-draft-status-errors#C4). 우리 PARTIAL_RESULT_FAILURE 결정은 규격 준수가 아니라 의도적 이탈이다. 신규 port 0개(D1)는 여전히 외부 근거가 없다.

TODO

  • FE-REG-API.protocol 별 adapter 선택 규칙 확정 — 등급: planned
  • protocol 별 성공 판정 함수 분리 — 등급: planned
  • GraphQL 본문 errorsPARTIAL_RESULT_FAILURE 매핑 (상태 코드 무관, 294 포함) — 등급: planned
  • grpc-status → 정규화 kind 매핑표를 우리 결정으로 작성 후 backend 소유자와 대조 — 등급: planned
  • gRPC-Web adapter 와 Connect adapter 분리 유지 fixture — 등급: planned
  • codec decode 실패 → CODEC_DECODE_FAILURE — 등급: planned
  • REST gateway fallback 경로 — 등급: planned
  • protocol 차원과 gateway fallback 발생률 telemetry 등록 (관심사 7 should-fix) — 등급: planned
  • FE-GATE-030 protocol mapping report 산출 — 등급: planned

진행 중 메모

이 branch 의 가치는 "무엇을 추가했는가" 보다 "무엇을 추가하지 않았는가" 에 있다. 신규 port 0개라는 결론이 유지되어야 backend 가 REST 에서 gRPC 로 옮겨갈 때 use case 를 다시 쓰지 않는다. 리뷰 시 port 가 늘어나 있으면 그 자체가 회귀 신호다.

결정 사항

  • 2026-07-28: 신규 port 0개 / 이유: 프로토콜은 registry 데이터이지 타입이 아니며, port 로 새면 dependency inversion 이 무너짐 / 검토한 대안: GraphQLPort·GrpcWebPort 분리 / 근거: 설계문서 §5.2
  • 2026-07-28: errors 있는 응답을 실패로 정규화 / 이유: 부분 데이터를 성공으로 취급하면 빈 화면이 정상처럼 보임 / 검토한 대안: 부분 성공 상태 신설 / 근거: 규격 이탈을 자각한 project decision. GraphQL over HTTP draft 는 이를 "successful execution" 이라 부른다(graphql-over-http-draft-status-errors#C4)
  • 2026-07-28: 성공 판정에서 상태 코드를 빼고 본문 구조만 봄 / 이유: 규격이 data+errors 에 294 를 권고하고 클라이언트에게 상태 코드와 무관한 처리를 요구함 / 검토한 대안: 200·294 를 모두 허용 목록에 넣기 / 근거: graphql-over-http-draft-status-errors#C1·#C3. 허용 목록 방식은 draft 가 코드를 바꾸면 다시 깨진다
  • 2026-07-28: gRPC-Web 과 Connect adapter 분리 / 이유: Connect 는 오류를 non-200 으로 보내고 trailer 를 쓰지 않아 판정 규칙이 정반대 / 검토한 대안: 공통 gRPC 계열 adapter / 근거: grpc-connect-status-codes-error-model#C5·#C6·#C7

결정-근거 매핑

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 신규 port 0개 항상. 프로토콜 고유 기능(gRPC 양방향 스트림 등)이 use case 레벨에 필요해지면 재검토 없음 — 조사 후에도 외부 근거 없음 UNSUPPORTED_DECISION 추상화가 새는 프로토콜 기능이 있을 수 있음
D2 protocol 별 성공 판정 함수 분리 항상. 세 프로토콜의 성공 신호 위치가 서로 달라 예외가 없다 graphql-over-http-draft-status-errors.md#C3, grpc-connect-status-codes-error-model.md#C3·#C5 official-reference 판정 로직이 프로토콜마다 흩어져 중복될 수 있음
D3 errors 있으면 PARTIAL_RESULT_FAILURE 항상. 제품이 부분 데이터를 의미 있게 쓸 수 있으면 재검토 graphql-over-http-draft-status-errors.md#C4(규격은 성공이라 부름), #C6 project decision규격 이탈을 자각한 선택 일부 필드만 실패한 응답을 통째로 버린다. 규격을 따르는 다른 클라이언트와 동작이 달라진다
D4 상태 코드가 아니라 본문으로 성공 판정 항상 graphql-over-http-draft-status-errors.md#C1·#C2·#C3 official-reference (draft) draft 라 294 권고가 바뀔 수 있다. 다만 "본문으로 판정" 은 코드가 바뀌어도 유효
D6 재시도 매핑을 우리 결정으로 등록 항상. 규격이 판단을 위임했으므로 위임을 받은 쪽이 근거를 남겨야 한다 grpc-connect-status-codes-error-model.md#C1, #C2 official-reference(위임 사실) + project decision(매핑 내용) 매핑이 backend 의 코드 사용 관습과 어긋나면 재시도가 과하거나 부족해진다
D7 gRPC-Web 과 Connect adapter 분리 항상. 두 프로토콜의 오류 위치가 정반대다 grpc-connect-status-codes-error-model.md#C5, #C6, #C7 official-reference 유사한 코드가 두 벌 생긴다. 공유하려는 리팩터가 나중에 회귀를 만든다

구현 가이드

2026-07-28 /branch-spec 조사(GraphQL over HTTP draft + gRPC status codes + Connect protocol)로 채웠다. 규격이 확정해 주는 것과 우리가 정해야 하는 것을 절마다 구분했다. 후자는 UNSUPPORTED_IMPL_DECISION + trade-off 로 표시했다(CLAUDE.md §15.5 R2).

1. 성공 판정 — 프로토콜마다 신호가 다른 곳에 있다

Trace: D2(판정 함수 분리) ← graphql-over-http-draft-status-errors.md#C3, grpc-connect-status-codes-error-model.md#C3·#C5 / D4(본문 판정) ← #C1·#C2·#C3 / D7(adapter 분리) ← #C5·#C6·#C7

성공을 판정하는 위치가 세 프로토콜에서 전부 다르다. 이것이 판정 함수를 공유할 수 없는 이유다.

protocol 성공 신호 위치 틀리기 쉬운 구현
REST HTTP 상태 코드 — (기준선)
GraphQL 본문의 data·errors 구조. 상태 코드는 200 일 수도 294 일 수도 있다 200 만 검사 → 294 응답을 실패로 오분류. 2xx 만 검사 → errors 를 놓침
gRPC-Web trailer 의 grpc-status. HTTP 는 200 이어도 실패일 수 있다 HTTP 상태만 검사 → 실패를 성공으로 처리
Connect HTTP 상태 코드(오류는 non-200) + 본문 JSON 의 code gRPC-Web 과 같은 코드로 처리 → 정반대 규칙이라 반드시 틀림

GraphQL 행이 특히 함정이다. 규격은 data 와 errors 가 함께 있으면 294 를 권고하고(#C1), 클라이언트는 상태 코드와 무관하게 본문을 처리하라고 명시한다(#C3). 그래서 판정은 상태 코드를 보지 않고 dataerrors 의 존재로 한다.

gRPC-Web 과 Connect 를 한 adapter 로 묶지 않는다. Connect 는 trailer 를 아예 쓰지 않고(#C6) 오류를 non-200 으로 보내며(#C5), 규격 자신이 gRPC-Web 과 다른 프로토콜이라고 밝힌다(#C7). 이름이 비슷하다는 이유로 공유하면 한쪽이 반드시 틀린다.

UNSUPPORTED_IMPL_DECISION — 판정 함수를 protocol 값으로 조회하는 registry 형태로 두는 것. 규격은 판정 규칙만 정하고 우리 코드 구조를 정하지 않는다. trade-off: 조건 분기 대신 조회 표를 쓰면 새 프로토콜을 추가할 때 등록 누락이 boot 시점에 드러난다. 비용은 간접 참조가 한 겹 늘어나는 것.

2. GraphQL errors 처리 — 규격과 다르게 간다

Trace: D3 ← graphql-over-http-draft-status-errors.md#C4·#C6

규격은 field error 가 있는 부분 응답을 "successful execution" 이라고 부른다(#C4). 우리는 이를 PARTIAL_RESULT_FAILURE 로 정규화한다. 규격 준수가 아니라 의도적 이탈이며, 이 문장이 노트에 남아야 다음 사람이 근거를 오해하지 않는다.

이탈하는 이유는 부분 데이터가 화면에서 정상처럼 보이기 때문이다. 목록의 절반이 비어 온 응답을 성공으로 넘기면 사용자는 "데이터가 없다" 고 읽고, 우리는 오류를 관측하지 못한다.

telemetry 에는 error 개수와 path 개수만 남기고 error message 본문은 남기지 않는다. #C6 대로 data: null 이면 errors 가 반드시 있으므로, data 유무만으로 request error 와 field error 를 가를 수 있다.

UNSUPPORTED_IMPL_DECISION — 부분 데이터를 버리는 것(수신은 하되 use case 에 넘기지 않음). 규격도 우리 근거도 "버려라" 라고 말하지 않는다. trade-off: 살려서 넘기면 use case 마다 "이 데이터가 완전한가" 를 판단해야 하고 그 판단이 빠지는 순간 조용한 오류가 된다. 비용은 일부 필드만 실패한 응답에서 쓸 수 있는 데이터까지 잃는 것.

3. gRPC 코드 매핑 — 규격이 우리에게 넘긴 결정

Trace: D6 ← grpc-connect-status-codes-error-model.md#C1·#C2

코드 목록은 규격이 준다 — 0(OK)부터 16(UNAUTHENTICATED)까지 17개(#C1). 그러나 재시도 가능 여부는 규격이 정하지 않는다. 원문이 명시적이다: "individual applications must make their own determination as to which status codes should cause an RPC to be retried"(#C2).

따라서 매핑표는 FE-REG-ERROR우리 결정으로 등록하고, 각 행에 왜 그렇게 정했는지를 남긴다. "규격이 그렇다" 는 근거로 쓸 수 없다. 매핑이 backend 의 코드 사용 관습과 어긋나면 재시도가 과하거나 부족해지므로, 표를 만든 뒤 backend 소유자와 대조하는 것이 FE-GATE-030 이전 단계로 필요하다.

UNSUPPORTED_IMPL_DECISION — 17개 코드를 어떤 kind 로 접을지, 그중 무엇을 retryable 로 둘지. 규격이 판단을 위임했으므로 이 표 전체가 우리 trade-off 다. 지금 값을 적지 않는 이유는 backend 대조 없이 정하면 두 번 정하게 되기 때문이다.

4. 이 branch 가 남기지 않는 것 (R3)

엣지·실패·의존

  • 실패·엣지 경로
    • HTTP 200 + grpc-status 비0 → PROTOCOL_STATUS_MISMATCH. status 는 transport 와 별도로 전달되므로(grpc-connect-status-codes-error-model#C3) HTTP 상태만 보는 구현은 실패를 성공으로 처리한다 (D2)
    • protobuf/GraphQL 디코드 실패 → CODEC_DECODE_FAILURE, 본문을 telemetry 에 남기지 않음
    • GraphQL 응답에 errors 존재PARTIAL_RESULT_FAILURE, error 개수와 path 개수만 telemetry. 규격은 이를 "successful execution" 이라 부르므로 의도적 이탈이다(graphql-over-http-draft-status-errors#C4) (D3)
    • GraphQL 상태 코드가 294 → 실패가 아니다. data 와 errors 가 함께 있다는 규격 권고 신호이므로(#C1) 본문 구조로 판정한다. 200 만 성공으로 보는 구현은 이 응답을 잘못 분류한다 (D4)
    • Connect 오류를 HTTP 200 으로 기대 → Connect 는 오류를 non-200 으로 보낸다(#C5). gRPC-Web 판정 코드를 그대로 쓰면 여기서 어긋난다 (D7)
    • capability OFF 또는 브라우저 미지원 → REST gateway 로 fallback (degraded-alternative)
    • gateway 도 없으면 CAPABILITY_UNSUPPORTED
  • 다른 계약 의존

검증해야 할 주장

Claim Why uncertain How to verify Status
200 OK + errors[] 가 success 로 반환되지 않는다 GraphQL 클라이언트 기본 동작이 부분 성공 negative fixture — 해당 응답 주입 후 PARTIAL_RESULT_FAILURE 확인 planned
HTTP 200 + grpc-status: 13 이 실패로 정규화된다 transport status 만 보는 구현이 흔함 negative fixture — trailer 주입 후 kind 확인 planned
protocol adapter 가 신규 port 를 만들지 않았다 구현 중 편의로 port 가 늘어나기 쉬움 architecture fixture — application/ports/ 파일 수가 늘지 않았는지 planned
REST gateway fallback 이 실제로 도달한다 capability OFF 경로가 테스트에서 빠지기 쉬움 integration test — flag OFF 로 같은 operation 호출 planned
codec 산출물이 반드시 스키마 검증을 거친다 디코드가 이미 타입을 보장한다고 착각하기 쉬움 negative fixture — 스키마 위반 디코드 결과 주입 후 SCHEMA_MISMATCH planned
grpc-status 매핑표가 backend 의 코드 사용과 일치한다 규격은 재시도 판정을 애플리케이션에 위임했으므로(grpc-connect-status-codes-error-model#C2) 대조 상대가 명세가 아니라 backend 소유자 매핑표 초안 작성 후 backend 소유자와 코드별 의미 대조 needs-confirmation
GraphQL 상태 코드 294 응답이 올바르게 처리된다 200 만 검사하는 구현이 흔하고, draft 권고라 실제로 오는지도 미확인 negative fixture — 294 + data + errors 응답 주입 후 PARTIAL_RESULT_FAILURE 확인. 별도로 backend 가 294 를 보내는지 실측 needs-confirmation
Connect adapter 가 gRPC-Web 판정 코드를 공유하지 않는다 이름이 비슷해 리팩터로 합쳐지기 쉬움 architecture fixture — 두 adapter 가 같은 성공 판정 함수를 참조하지 않는지 planned
GraphQL 성공 판정이 상태 코드에 의존하지 않는다 상태 코드 검사가 습관적으로 들어감 fixture — 같은 본문을 200·294 두 상태로 주입했을 때 판정 결과가 같은지 planned
부분 데이터를 버리는 정책이 제품에서 수용 가능하다 규격은 이를 성공이라 부르므로 이탈 비용을 제품이 감당해야 함 제품 소유자 확인 — 목록 절반이 실패한 응답을 통째로 버려도 되는지 needs-confirmation

Audit & Findings

/branch-spec 2026-07-28 조사에서 규격 원문과 대조해 발견한 것. hub 소유 항목은 정합 권고만 남긴다(hub §3.3).

Finding ID 대상 현재 서술 조사 결과 권고 처리
GRAPHQL_STATUS_ASSUMPTION hub §8.2 실패 매트릭스 및 이 노트의 D3 초안 "GraphQL 200 OK + errors[]" — 상태 코드를 200 으로 특정한다 graphql-over-http-draft-status-errors#C1: data 와 errors 가 함께 있으면 규격은 294 를 권고한다. #C3: 클라이언트는 상태 코드와 무관하게 본문을 처리해야 한다 진입 조건을 "200 OK + errors[]" 가 아니라 "응답 본문에 errors 존재" 로 바꿀 것. 상태 코드를 조건에 넣으면 294 를 놓친다 open — hub §8.2 정정 후보 (compatibility_impact: none, 진입 조건의 정확화)
SPEC_DEVIATION_UNDECLARED 이 노트의 D3 초안 "부분 성공이 아니라 PARTIAL_RESULT_FAILURE 로 정규화한다" — 규격을 따르는 것처럼 읽힌다 graphql-over-http-draft-status-errors#C4: 규격은 field error 상황을 "partial response" 이자 "successful execution" 이라고 부른다 이탈임을 명시할 것. 이탈 자체는 유효하나 근거를 규격으로 오인하면 안 된다 resolved 2026-07-28 — D3 서술과 §구현 가이드 2 에 명시
RETRY_MAPPING_MISATTRIBUTED 이 노트의 TODO "grpc-status → 정규화 kind 매핑표 (명세 확인 후)" 명세를 읽으면 매핑이 나온다고 전제한다 grpc-connect-status-codes-error-model#C2: "individual applications must make their own determination as to which status codes should cause an RPC to be retried" — 규격이 판단을 명시적으로 위임한다 "명세 확인 후" 를 "우리가 정하고 backend 와 대조" 로 바꿀 것 resolved 2026-07-28 — D6 신설, TODO 문구 교체
NO_GROUND_TRUTH /branch-spec §2 ca-tmpl 대조 명령은 ca-tmpl registry·코드와 대조하라고 요구 ca-tmpl 은 Gradle/Java 백엔드 전용. frontend 구현 repo 미식별 전 항목 planned 유지 openFE-Q-001 선행

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

2026-07-28 /branch-spec §8b. agent dispatch 없이 수기 판정했다(세션 제약). governing doc = raw/project-notes/ca-skeleton-frontend-operational-contract. 기준은 hub §2.2 의 10개 universal acceptance question.

# 관심사 판정 근거
1 문제와 실패 모드가 구체적인가 covered-here §목표 — 빈 화면이 정상처럼 보이는 경로. §엣지 7개
2 상속한 결정을 실제로 적용했는가 covered-here PROTOCOL-001 → D1·D7, VALIDATION-001DELEG-FE-010, CAPABILITY-001CAP_FE_ALT_PROTOCOL 소유
3 project-wide default 와 limit covered-here D2(판정 분리), D4(본문 판정), D6(매핑은 우리 결정), D7(adapter 분리)
4 대안을 검토했는가 covered-here §결정 사항 — 프로토콜별 port / 부분 성공 상태 신설. D1 은 trade-off 명시
5 금지 구현 covered-here §구현 가이드 1 — 판정 함수 공유 금지, 상태 코드만 검사 금지. §구현 가이드 3 — 규격 인용으로 재시도 근거 대체 금지
6 실패 경로가 error kind 로 매핑되는가 covered-here 신규 3종 + CAPABILITY_UNSUPPORTED. 등록은 error-classification branch 소유
7 관측 가능한가 should-fix PARTIAL_RESULT_FAILURE 의 error·path 개수는 정했으나, 어느 protocol 로 처리됐는지를 구분하는 차원이 FE-REG-TELEMETRY 에 없다. gateway fallback 발생률도 미등록
8 위임 경계가 명확한가 covered-here DELEG-FE-010, §구현 가이드 4 의 R3 목록
9 검증 수단이 있는가 covered-here §검증해야 할 주장 11행, FE-GATE-030 fixture + protocol mapping report
10 말할 수 있는 범위 covered-here 전 항목 plannedNO_GROUND_TRUTH

판정: Covered (missing 0) · Should-fix 1건(관심사 7). Blocking 아님.

마주친 문제

없음.

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

Sub-branches (세부 작업)

아직 없음.

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

아직 없음.

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

아직 없음.

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

아직 없음.

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

아직 없음.

관련 일일 노트

  • 아직 없음

완료 후 정리

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