Files
tech-log-frontend/docs/operations/api-contract-and-server-state-recovery.md
T

582 lines
28 KiB
Markdown

# API contract와 Server State recovery
- 상태: current REST 절차 + future GraphQL/Connect/gRPC-Web/REST Gateway/
schema/cache 절차 분리
- backend 구조와 handoff:
[Backend API와 Server State contract](../architecture/backend-api-and-server-state-contract.md)
- 기준일: 2026-07-28
- 설계:
[API contract, Schema, Mapper와 Server State](../architecture/api-contract-schema-mapper-and-server-state.md)
- browser Protobuf/gateway 설계:
[Protobuf browser transport와 REST Gateway](../architecture/protobuf-browser-transport-and-rest-gateway.md)
## 1. 적용 범위
현재 reference REST → Schema → Mapper → TanStack Query vertical은 `COMPOSED`다.
하지만 다음 target delta는 아직 `DESIGNED_NOT_IMPLEMENTED`다.
- REST v2 auth fail-close/final invariant
- total logical deadline와 bounded response decoder
- complete cursor/conditional request
- typed schema/mapper registry
- strict query/mutation definition과 concurrency coordinator
- GraphQL reference adapter
- Connect-Web reference adapter
- gRPC-Web reference adapter
- Protobuf REST Gateway
GraphQL/Connect/gRPC-Web/REST Gateway 절차는 해당 runtime과 actual provider가
구현·조합된 뒤에만 운영 gate로 활성화한다. 문서나 fake fixture만으로 capability를
`AVAILABLE_NOT_COMPOSED`, `COMPOSED` 또는 production-ready라고 기록하지 않는다.
canonical readiness:
```text
Selection
TrafficAdmission
RuntimeHealth
PromotionEvidence
```
이 readiness model은 target v2 control plane이다. current v1에는 operation별
`TrafficAdmission` runtime switch가 없다.
| control | current v1 | target v2 |
| --- | --- | --- |
| operation traffic switch | 없음 | provider/family/operation별 `TrafficAdmission` |
| frontend containment | promotion 중지와 known-good release rollback; feature composition 변경은 재배포 필요 | atomic admission disable |
| provider containment | actual BFF/API owner의 route/kill switch가 있을 때만 사용 | registered provider kill switch와 probe |
| query cleanup | composed QueryClient/coordinator의 cancel·invalidate·local clear | generation fence와 profile-scoped cleanup |
| mutation recovery | backend 상태/idempotency owner와 수동 reconcile | effect certainty + runtime/scope coordinator |
따라서 current v1 incident에서 존재하지 않는 switch를 내렸다고 기록하지 않는다.
target v2가 composed된 operation만 `TrafficAdmission`을 먼저 내린다. 그 전에는
신규 promotion을 중지하고 known-good release rollback 또는 실제 backend/BFF
route 차단을 owner와 수행한다. primary status나 contract version을 운영자가
임의로 낮춰 현재 상태를 숨기지 않는다.
current v1으로의 fallback은 (1) 해당 operation의 provider/security evidence가
만료되지 않았고, (2) incident class가 v1 또는 shared boundary에 영향이 없으며,
(3) auth fail-close/final invariant hardening이 유지되는 경우만 허용한다. 하나라도
증명하지 못하면 v1을 사용하지 않고 safe unavailable 또는 실제 provider route
차단으로 닫는다.
## 2. 관측 허용과 금지
허용된 bounded aggregate:
- semantic operation/profile/provider ID
- protocol/semantics
- safe failure kind
- HTTP status group, GraphQL safe category, gRPC status bucket
- logical/physical attempt, auth recovery와 deadline bucket
- provider가 측정한 encoded transfer bucket과 browser가 측정한
decoded/result/message/frame/page/item byte/count bucket
- schema/mapper/query profile version과 compatibility outcome
- cache hit/miss/stale/refresh/admission/eviction
- mutation concurrency/optimistic/rollback/conflict/effect/invalidation outcome
- stream terminal/gap/overflow/idle bucket
금지:
- URL/path/search/header/body
- credential, cookie, CSRF, idempotency key
- GraphQL document/hash/variables/data/error message/path/extensions
- protobuf payload/debug JSON/metadata/trailer/status-details
- DTO/application/cache value/optimistic patch
- cursor/snapshot/ETag/revision/resume token
- account/tenant/resource/file ID
- raw backend request/trace/correlation value
incident ticket에 금지 값을 복사하지 않는다. credential/payload 노출 의심이면
일반 contract incident가 아니라 security incident로 분류하고 provider revoke,
key/session rotation과 로그 보존 범위를 별도 owner에게 escalate한다.
## 3. 최초 containment
1. 영향 operation family/protocol/provider/browser/release cohort를 safe aggregate로
좁힌다.
2. target v2 control이 실제 composed됐으면 해당 operation의
`TrafficAdmission``DISABLED` 또는 안전한 canary cohort로 낮춘다. current
v1이면 promotion을 중지하고 known-good release rollback 또는 실제
backend/BFF route control을 사용한다.
3. query/read는 cancel하고 stream reader를 닫는다.
4. command는 무조건 retry/rollback하지 않고 effect certainty를
`NOT_APPLIED | COMMITTED | UNKNOWN`으로 분류한다.
5. `UNKNOWN` command는 backend idempotency/status/reconcile owner에게 전달한다.
6. current scope의 suspect query를 invalidate한다. wrong-scope/contract-poison
가능성이 있으면 cancel 후 current runtime cache를 clear한다.
7. GraphQL/Connect/gRPC-Web failure를 REST command로 자동 failover하지 않는다.
8. contract tuple과 artifact를 확인한다.
```text
frontend release/build
runtime config/API contract version
installed operation registry digest
runtime schema/mapper/query policy digest
REST/OpenAPI artifact
GraphQL schema + persisted manifest
protobuf descriptor/generated artifact
Connect client/server/provider profile
HttpRule/ProtoJSON/OpenAPI/gateway artifact
BFF/router/proxy/backend release
```
실제 digest 값을 high-cardinality telemetry label로 보내지 않고 incident evidence
artifact에서 access-controlled하게 비교한다.
## 4. 공통 증상 분류
| 증상 | 우선 확인 |
| --- | --- |
| 특정 release에서 전 operation 실패 | runtime config, provider endpoint, auth owner, contract set |
| schema/mapper mismatch 급증 | backend artifact rollout, unknown/null/enum/scalar 변화, wrong codec |
| retry/traffic 폭증 | retry owner 중복, 401 loop, Retry-After, total deadline |
| stale/wrong account data | scope generation, late result, query key collision, invalidation |
| command duplicate/rollback 이상 | idempotency tuple, input-aware concurrency, optimistic revision |
| list가 반복/무한 증가 | cursor loop/snapshot/page/item/byte ceiling |
| provider 200인데 client 실패 | status/media/envelope/schema/mapper/body cap |
| 로그에서 payload/ID 발견 | redaction/allowlist bypass, diagnostics producer |
## 5. Auth와 CSRF
### 5.1 Auth-required request가 무자격으로 전송됨
현재 v1은 external auth integration이 unavailable이어도 unchanged request가
전송될 수 있으므로 target v2 전까지 제품 auth-required traffic을 provider
evidence 없이 활성화하지 않는다.
target 점검:
1. session state가 authenticated인지 확인한다.
2. auth owner가 `CredentialPatch`만 반환하는지 또는 final request invariant를
재검증하는지 확인한다.
3. URL/origin/method/body digest/idempotency/conditional/CSRF가 attach 전후 같은지
확인한다.
4. unavailable/integration-failed/attach rejected에서 fetch가 0회인지 증명한다.
5. 401 recovery가 logical execution당 1회인지 확인한다.
6. concurrent 401이 single-flight recovery를 공유하는지 확인한다.
7. non-replayable command가 recovery 뒤 재실행되지 않았는지 확인한다.
의심 시 operation auth traffic을 즉시 닫는다. anonymous fallback을 만들지 않는다.
### 5.2 CSRF/CORS
1. unsafe cookie request의 exact Origin/Fetch Metadata/CSRF proof를 server에서
확인한다.
2. SameSite/custom header/preflight 하나만으로 방어했다고 기록하지 않는다.
3. cross-origin allow-origin/credentials/method/header/expose가 exact한지 확인한다.
4. wildcard credential, redirect와 unexpected origin을 복구한다.
5. CSRF token/header 값을 ticket에 기록하지 않는다.
## 6. REST incident
### 6.0 Current v1 available checks
1. current per-attempt timeout/bounded retry, Query retry off, AbortSignal과 401
recovery observation을 확인한다.
2. installed request/envelope/payload Zod schema와 mapper failure kind를 확인하되
current `Response.json()`이 body cap 증거가 아님을 기록한다.
3. QueryClient/coordinator로 affected read를 cancel/invalidate/clear한다.
4. cursor response/page runtime, APP_ETAG와 total deadline은 아직 없으므로 해당
control을 실행했다고 기록하지 않는다.
5. command effect는 backend와 reconcile한다. basic optimistic snapshot 문제가
의심되면 runtime switch를 가정하지 말고 no-optimistic/known-good release로
rollback한다.
아래 6.1~6.5는 target v2 coordinator가 해당 operation에 composed된 뒤에만
운영 절차로 활성화한다.
### 6.1 Timeout/retry storm — target v2
1. Query retry가 꺼지고 REST transport 하나만 network retry하는지 확인한다.
2. total logical deadline 안에 auth, fetch, body, mapper, recovery와 sleep이 모두
포함되는지 확인한다.
3. attempt timeout과 logical deadline exhaustion을 별도 kind로 확인한다.
4. 초회/retry/401 replay 모든 provider fetch가 하나의 monotonic
physical-attempt cap을 소비하는지 확인한다.
5. exact retry status가 network/408/429/502/503/504 중 operation subset인지
확인한다.
6. 429/503 `Retry-After`가 injected clock, max sleep/elapsed ceiling을 지키는지
확인한다.
7. timer/listener/reader leak가 있는 cohort는 traffic을 닫는다.
8. keyed command는 backend dedupe evidence 없이는 retry를 끈다.
### 6.2 Body/media/schema failure — target v2
1. final URL/status/content type을 확인한다.
2. present/valid Content-Length advisory preflight와 actual browser-visible decoded
byte cap을 확인한다.
3. actual encoded transfer/decompression ratio cap은 BFF/proxy/CDN evidence에서
확인한다. browser reader가 encoded bytes를 셌다고 가정하지 않는다.
4. standard JSON parse profile이면 decoded byte는 pre-parse guard,
depth/node/key는 post-parse admission guard인지 확인한다.
5. truncated, content encoding/decompression overflow와 invalid UTF-8을 구분한다.
6. success status/media/envelope profile이 operation registry와 일치하는지 확인한다.
7. schema unknown-field policy와 actual codec fingerprint를 확인한다.
8. failure body/value를 출력하지 않는다.
9. schema/mapper failure result를 cache하지 않았는지 확인한다.
10. backend/frontend artifact가 coherent하지 않으면 operation traffic을 닫고
N/N-1 compatible set으로 rollback한다.
### 6.3 Idempotency/ambiguous command — target v2
1. principal/operation/payload digest/key tuple과 backend TTL/status를
access-controlled evidence에서 확인한다.
2. 같은 key + 다른 payload가 거절되는지 확인한다.
3. concurrent same-key request가 duplicate commit을 만들지 않았는지 확인한다.
4. `UNKNOWN` effect에 새 key를 생성해 retry하지 않는다.
5. backend status/receipt로 `COMMITTED`면 cache reconcile/invalidate한다.
6. `NOT_APPLIED`가 증명된 경우만 정책에 따라 retry한다.
### 6.4 Cursor loop — target v2
1. query root filters/sort/scope/snapshot을 확인한다.
2. same cursor 반복, `hasMore`/cursor 모순과 non-progress page를 확인한다.
3. max pages/items/bytes를 초과했으면 추가 fetch를 중지한다.
4. snapshot이 바뀌었으면 old/new pages를 합치지 않고 root부터 재시작한다.
5. raw cursor/next URL을 로그에 남기거나 임의 follow하지 않는다.
### 6.5 Conditional request — target v2
1. operation cache owner가 `APP_ETAG`인지 browser HTTP cache인지 확인한다.
2. 304에서 exact query/scope/generation/validator binding과 mapped cached value가
모두 있는지 확인한다.
3. 304가 same query-entry cache revision CAS를 통과했는지 확인한다.
4. cached value가 없으면 304를 success로 만들지 않는다.
5. full 200 value와 validator가 atomic하게 교체됐는지 확인한다.
6. Query removal/GC, scope/logout와 release/contract/schema/mapper epoch에서
sidecar가 함께 폐기됐는지 확인한다.
7. 412 precondition과 409 business conflict를 구분한다.
8. ETag/revision 값을 incident ticket에 기록하지 않는다.
## 7. GraphQL incident
이 절은 VD-26 runtime 조합 후 적용한다.
### 7.1 Persisted operation mismatch
1. frontend schema/operation manifest와 router manifest 호환성을 확인한다.
2. operation ID, hash, schema digest와 retirement window를 artifact에서 비교한다.
3. full document fallback/APQ miss fallback을 활성화하지 않는다.
4. affected GraphQL operation traffic을 닫는다.
5. frontend + manifest + router를 coherent N/N-1 set으로 rollback한다.
### 7.2 HTTP/media + data/errors
1. selected GraphQL-over-HTTP revision, persisted-envelope extension,
`Accept`/response media와 status/body matrix를 확인한다.
2. `application/graphql-response+json`이면 허용 status에서도 body를 bounded
GraphQL envelope로 처리했는지 확인한다. legacy `application/json` non-2xx
intermediary body를 GraphQL error로 해석하지 않는다.
3. `errors=[]`, null/absent data + no errors를 envelope mismatch로 닫았는지
확인한다.
4. data/errors state branch와 operation partial policy를 확인한다.
5. raw message/path/extensions를 보지 않고 allowlisted safe code만 확인한다.
6. query partial이 `ALLOW_TYPED_PARTIAL` 조건을 모두 만족하는지 확인한다.
7. unauthorized/contract error field를 previous cache로 자동 채우지 않는다.
8. mutation이면 effect certainty/receipt를 확인한다.
9. partial/mutation error를 ordinary success로 cache하지 않는다.
### 7.3 Cost/depth/rate failure
1. persisted operation manifest의 max cost/depth/aliases/list와 router 실제 budget을
비교한다.
2. variables/response size가 frontend/server 양쪽 ceiling 안인지 확인한다.
3. client retry storm을 끈다.
4. arbitrary operation 또는 introspection을 허용해 우회하지 않는다.
5. field authorization과 cost budget을 별도 확인한다.
### 7.4 Incremental/subscription
선택된 경우에만:
- exact incremental/subscription protocol/provider revision
- exact Accept/Content-Type parameter와 payload discriminant
- multipart boundary/part/path/terminal/byte/patch count
- truncated/duplicate/out-of-order
- proxy buffering
- sequence/gap/resume/heartbeat
- bounded queue/overflow
- logout/unsubscribe
terminal completeness 전 staging을 complete query cache로 commit하지 않는다.
## 8. gRPC-Web incident
이 절은 VD-27 runtime 조합 후 적용한다.
### 8.1 HTTP success인데 RPC 실패/멈춤
1. exact client runtime/wire-spec revision/content type/transport/rpc-kind capability
matrix를 확인한다. official XHR runtime과 Connect-Web/custom Fetch runtime을
같은 cancel/deadline/frame 관측 경로로 취급하지 않는다.
2. `responseHttpStatusProfileId`와 HTTP status/gRPC media/terminal-source
교차 matrix를 확인한다.
3. custom Fetch framed runtime이면 frame prefix/length/flag/compression을
확인한다. official runtime이면 runtime-owned callback/status API와
`ClientReadableStream.cancel()` 경로를 확인하며 raw `ReadableStream` parser가
있다고 가정하지 않는다.
4. body trailer frame 또는 zero-body trailers-only response header 중 terminal
status source가 정확히 하나인지 확인한다.
5. `grpc-status`가 있으면 canonical decimal `0..16`으로 exactly once인지, body
trailer name lowercase와 rich-details outer code가 맞는지 확인하며 그 status를
authority로 사용한다.
6. `grpc-status`가 없으면 공식 fallback만 적용한다:
`400→INTERNAL`, `401→UNAUTHENTICATED`, `403→PERMISSION_DENIED`,
`404→UNIMPLEMENTED`, `429|502|503|504→UNAVAILABLE`, 그 외 `UNKNOWN`.
이것을 wire header로 위조하지 않고 internal normalized failure로만 사용한다.
7. HTTP success만으로 RPC success를 기록하지 않는다. duplicate/conflicting/
malformed terminal source는 provider incompatibility로 traffic을 닫는다.
8. Envoy의 upstream HTTP/2, filter order, route/idle/max-stream timeout과 buffering
profile을 확인한다. default route timeout으로 long stream이 잘렸는지 확인한다.
9. raw grpc-message/status-details를 ticket에 복사하지 않는다.
### 8.2 Unary response
1. OK status에서 response message가 exact 1개인지 확인한다.
2. `google.protobuf.Empty`도 zero-length payload data frame 하나여야 한다.
trailers-only OK + zero-message unary는 contract mismatch다.
3. two-or-more message/data-after-trailer/extra bytes를 contract mismatch로 닫는다.
4. generated decode 뒤 semantic schema/mapper가 통과했는지 확인한다.
5. failure/late generation에서 cache write가 0인지 확인한다.
### 8.3 Server stream
1. message/frame/total bytes/count/idle/total deadline을 확인한다.
2. bounded queue와 consumer backpressure를 확인한다.
3. duplicate/order/gap/resume token protocol을 확인한다.
4. event 전달 뒤 transport-only auto replay가 없었는지 확인한다.
5. overflow/gap/truncation에서 current aggregate를 complete success로 쓰지 않는다.
6. finite aggregate는 valid OK terminal status/completeness 뒤 atomic cache
commit인지 확인한다.
7. actual proxy buffering/flush와 affected browser cohort를 확인한다.
### 8.4 Proxy/CORS
- Envoy/BFF/selected gateway filter와 upstream route
- exact allow/expose headers
- credential/CSRF/Origin
- trailer preservation
- content type
- compression/message/deadline cap
- stream buffering
actual proxy를 복구한다. client decoder를 느슨하게 만들어 provider drift를
수용하지 않는다.
## 9. Connect와 REST Gateway incident
이 절은 VD-29/VD-30 runtime이 실제 조합된 operation에만 적용한다.
### 9.1 Connect unary/server stream
1. exact Connect-Web package/runtime, `CONNECT | GRPC_WEB`, JSON/binary,
POST/GET와 rpc kind row를 확인한다. content type으로 다른 protocol을 자동
선택하지 않는다.
2. Connect unary는 HTTP status + bounded Connect error, stream은 HTTP admission +
exactly-one final EndStream을 각각 authority로 사용한다.
3. missing/early/duplicate EndStream, terminal 뒤 data, malformed/oversize
envelope와 compression mismatch에서 call을 cancel하고 cache write를 막는다.
4. stock runtime이 whole unary body를 읽는 profile이면 edge encoded/decompressed
cap과 selected version의 actual overflow evidence를 확인한다. interceptor가
raw-byte cap을 제공했다고 기록하지 않는다.
5. remaining total deadline이 0 이하면 runtime `timeoutMs=0`을 호출하지 않고
local deadline failure로 닫는다. abort 뒤 command는 backend receipt로
reconcile한다.
6. GET은 descriptor `NO_SIDE_EFFECTS`, input classification, URL cap, cache key,
`Vary`와 credential/preflight profile이 모두 일치하는지 확인한다.
7. raw Connect message/metadata/detail/debug를 ticket에 복사하지 않는다.
### 9.2 Protobuf REST Gateway
1. selected gateway kind/version과 descriptor, canonical HttpRule manifest,
ProtoJSON profile, OpenAPI와 runtime config digest를 coherent set으로 비교한다.
2. method/path/query/body/additional binding, path escaping과 response-body
projection drift를 확인한다.
3. ProtoJSON field name/default/enum/int64/bytes/null/presence/unknown behavior를
N/N-1 fixture와 비교한다.
4. current REST envelope/status/error를 direct ProtoJSON body나 raw
`google.rpc.Status`로 잘못 decode했는지 확인한다.
5. `201/204/304/412`, ETag, idempotency, pagination과 safe error rewrite가 실제
BFF/gateway owner의 contract인지 확인한다. transcoder가 자동 제공한다고
가정하지 않는다.
6. browser abort→gateway context→upstream gRPC→application work의 cancellation/
deadline 전파를 확인한다. 이미 commit된 command는 receipt로 reconcile한다.
7. runtime response rewrite와 generated OpenAPI가 다르면 affected route admission을
닫고 coherent gateway/contract set으로 rollback한다.
Connect/gRPC-Web/REST 사이 command replay는 금지한다. read-only registered
fallback도 old generation을 cancel한 뒤 새 logical query로만 시작한다.
## 10. Schema/Mapper incident
### 10.1 Current v1 available checks
1. operation의 string schema ID가 installed Zod resolver에 있는지 확인한다.
2. envelope/payload parse와 mapper/domain factory 중 어느 current boundary에서
실패했는지 safe failure/diagnostics로 좁힌다.
3. raw DTO/value를 출력하지 않고 affected query cache write를 확인한다.
4. current registry에는 semantic fingerprint/provenance/typed mapper Result가
없으므로 이 값을 비교했다고 기록하지 않는다.
5. frontend release/runtime config/manifest의 current string contract coherence를
확인하고 known-good coherent release로 rollback한다.
### 10.2 Target v2 composed 이후
1. operation → schema ID/fingerprint → mapper ID/version binding을 확인한다.
2. source artifact/generated output/runtime codec digest를 비교한다.
3. missing/null/enum/numeric/time/unknown-field change를 classification한다.
4. request strict와 response strip/reject 방향 정책을 확인한다.
5. provider encoded-transfer와 browser decoded-byte owner를 분리하고,
item/depth/node/string admission ceiling을 확인한다.
6. mapper expected semantic failure가 throw/`UNKNOWN_FAILURE`로 소실되지 않았는지
확인한다.
7. cache write와 partial collection이 0인지 확인한다.
8. raw validation value/path/DTO를 log에 남기지 않는다.
9. incompatible schema/mapper/query cache epoch를 coherent set으로 rollback/clear한다.
## 11. Server State Cache incident
### 11.0 Current v1 available checks
1. Query retry off, global stale/gc, AbortSignal과 affected query의
cancel/invalidate/local clear를 확인한다.
2. current arbitrary key/canonicalize와 hook-local pending Promise를 관측하고
collision/incorrect join cohort cache를 clear한다.
3. current whole-snapshot optimistic rollback이 다른 commit을 덮었는지 backend
authoritative state로 reconcile한다.
4. strict key/identity token, cursor page와 optimistic layer CAS는 아직 없으므로
해당 fixture/control이 실행됐다고 기록하지 않는다.
5. 필요하면 known-good/no-optimistic release로 rollback한다. operation별 runtime
optimistic switch가 있다고 가정하지 않는다.
아래 10.1~10.4는 target v2 cache/mutation coordinator가 composed된 뒤 활성화한다.
### 11.1 Wrong/stale scope — target v2
1. VD-13 frozen scope projection과 runtime generation을 확인한다.
2. account/logout/release switch 전 query를 cancel했는지 확인한다.
3. late response/mapper/cache write fence를 확인한다.
4. raw account/resource ID를 key에서 찾거나 출력하지 않는다.
5. current runtime cache를 clear/remount하고 backend authoritative data를 refetch한다.
### 11.2 Query key collision — target v2
1. arbitrary key API가 남아 있는지 확인한다.
2. undefined/NaN/Date/class/accessor/cycle/sparse/oversize fixture를 실행한다.
3. collision 가능 cohort의 cache를 clear한다.
4. strict key codec/profile 없는 신규 query traffic을 닫는다.
5. URL/document/protobuf serialization을 key로 급히 넣지 않는다.
### 11.3 Mutation ordering/rollback — target v2
1. 전체 validated semantic input의 runtime-private exact equality + identity
token이 아닌 hook instance로 join/reject를 판정했는지 확인한다.
2. `JOIN_IDENTICAL | REJECT_DUPLICATE | ALLOW_INDEPENDENT` 결과와 fetch/Promise
횟수가 profile대로인지 확인한다.
3. runtime/scope coordinator에서 same logical key의 two-hook/out-of-order
execution을 확인한다.
4. whole snapshot rollback이 다른 committed mutation을 덮었는지 확인한다.
5. 자기 optimistic layer만 base cache revision CAS로 제거/역적용했는지 확인한다.
6. CAS miss/unknown effect에서는 다른 commit을 보존하고 invalidate/refetch한다.
7. optimistic update를 끄고 authoritative pending/refetch UX로 downgrade한다.
8. server commit 뒤 invalidation failure는 command failure로 바꾸지 않는다.
### 11.4 Cache size/pagination — target v2
1. result/page/item/estimated-byte cap을 확인한다.
2. identity intern entry/total canonical bytes/active lease와 GC/terminal release
leak를 확인한다. token/canonical bytes 자체는 출력하지 않는다.
3. unbounded collection/stream history를 cancel/evict한다.
4. binary/generated DTO를 cache value로 넣지 않았는지 확인한다.
5. max pages와 page eviction/refetch policy를 적용한다.
## 12. Rollback
target v2 coordinator가 composed된 operation:
```text
TrafficAdmission=DISABLED
-> cancel reads/streams
-> reconcile command effects
-> fence runtime generation
-> clear suspect current-scope memory cache
-> detach provider/listener/auth collaboration
-> restore coherent frontend + contract artifacts + provider/backend
-> run compatibility/provider probes
-> canary
```
current v1은 위 control이 있다고 가정하지 않는다. 신규 promotion을 중지하고
known-good release를 rollback하며, 실제 backend/BFF owner가 제공하는 route/kill
switch가 있을 때만 provider traffic을 차단한다. v1 fallback은 unexpired
provider/security evidence, incident가 v1/shared boundary 밖이라는 증거와 auth
fail-close/final invariant 유지가 모두 있을 때만 선택하고, 아니면 safe
unavailable로 닫는다.
금지:
- GraphQL/Connect/gRPC command를 REST 또는 gateway route로 자동 replay
- schema number/digest만 낮추기
- incompatible cache value를 cast/loose parse
- validation/mapper를 끄고 traffic 유지
- unknown command effect를 optimistic rollback만으로 해결
- auth unavailable을 anonymous request로 downgrade
## 13. Security containment
다음은 security owner에게 즉시 escalate한다.
- credential/CSRF/idempotency/presigned material이 cache/log에 노출
- auth owner가 endpoint/method/body를 변경
- unauthorized request가 실제 전송
- GraphQL arbitrary document/field authorization bypass
- gRPC metadata/status details payload 노출
- cross-account cache observation
신규 traffic을 닫고 credential/session/provider key/manifest를 필요한 scope에서
revoke/rotate한다. 삭제/보존은 incident response 정책을 따른다.
## 14. Drill과 evidence
분기 또는 major contract 변경 전:
- REST auth unavailable/final-request mutation
- total deadline/retry/401 single-flight
- oversized/truncated/schema/mapper
- idempotency concurrent replay/unknown effect
- cursor loop/ETag 304/412
- GraphQL persisted miss/partial/cost
- gRPC missing/conflicting terminal status source, corrupt frame와 stream gap
- query key collision/account late result
- optimistic concurrent rollback
- kill switch/coherent rollback
- GraphQL/Connect/gRPC/Gateway generated dependency/provider removal
evidence record:
```text
protocol/operation/provider/profile
frontend/backend/router/proxy/browser version
contract artifact compatibility outcome
fault/drill ID
safe result
started/completed timestamp
owner/reviewer
artifact retention/expiry
```
raw payload, URL, document, protobuf와 identifier를 evidence record에 넣지 않는다.
## 15. 관련 문서
- [VD-23 API transport selection과 REST execution](../architecture/decisions/VD-23-api-transport-selection-and-rest-execution.md)
- [VD-24 Runtime Schema와 boundary Mapper](../architecture/decisions/VD-24-runtime-schema-and-boundary-mapper.md)
- [VD-25 Server State Cache lifecycle](../architecture/decisions/VD-25-server-state-cache-lifecycle.md)
- [VD-26 Persisted GraphQL operation](../architecture/decisions/VD-26-persisted-graphql-operation.md)
- [VD-27 gRPC-Web unary와 server stream](../architecture/decisions/VD-27-grpc-web-unary-and-server-stream.md)
- [VD-29 Connect-Web와 browser Protobuf runtime](../architecture/decisions/VD-29-connect-web-and-browser-protobuf-runtime.md)
- [VD-30 Protobuf contract와 REST Gateway](../architecture/decisions/VD-30-protobuf-contract-and-rest-gateway.md)
- [VD-13 Client cache scope와 persistence](../architecture/decisions/VD-13-client-cache-scope-and-persistence.md)