Files
llm-wiki/raw/errors/internal-auth-misconfiguration-retryable-invariant-conflict-2026-06-08.md
T

47 lines
2.9 KiB
Markdown

---
title: error / internal-auth-misconfiguration-retryable-invariant-conflict
source_type: error-note
status: raw
related_branches: [feature-security-operational-baseline]
related_projects: [ca-skeleton]
tags: [error, ca-skeleton, security, error-codes, contract-test, retryable]
created: 2026-06-08
status_label: resolved
---
# error: INTERNAL_AUTH_MISCONFIGURATION retryable invariant conflict
> Layer: `raw/errors/` — 구현 중 발견한 enum invariant ↔ registry SSOT 충돌과 그 해소.
## Parent / 부모
- [[raw/branch-notes/feature-security-operational-baseline]] — 12 fine-grained auth code 를 `OperationalError` enum 에 추가하는 과정에서 발생.
## 증상 / Symptom
`OperationalError` enum 에 `INTERNAL_AUTH_MISCONFIGURATION(Category.INTERNAL, 500, retryable=false)` 를 추가하자, 기존 `shared-contract` 테스트 `OperationalErrorTest.internal_category_codes_are_retryable` 가 빨간불 위험. 이 테스트는 **"모든 INTERNAL category code 는 retryable=true"** 를 단언했다 (작성 당시 INTERNAL 은 `INTERNAL_ERROR` 하나뿐, 그것은 transient server fault 라 retryable=true 가 맞았음).
## 근본 원인 / Root cause
두 SSOT 가 충돌:
- **enum 테스트의 일반화 invariant**: "INTERNAL = 일시적 server fault = retryable".
- **`docs/registries/error-codes.yaml` 의 per-code SSOT**: `INTERNAL_AUTH_MISCONFIGURATION``retryable: false`. 이유 — 보호 endpoint 가 public 으로 새는 것은 *배포 시점 설정 버그*이지 transient fault 가 아니다. 같은 요청을 재시도해도 redeploy 전까지 계속 misconfiguration 에 부딪힌다.
즉 "INTERNAL 은 무조건 retryable" 이라는 일반화가 너무 넓었다. registry 의 per-code 판단이 더 정확.
## 해소 / Resolution
1. enum 값은 registry SSOT 에 맞춰 `retryable=false` 로 둠.
2. 테스트 `internal_category_codes_are_retryable` 를 정정: INTERNAL 중 `INTERNAL_AUTH_MISCONFIGURATION` 은 예외(deterministic config bug)임을 명시하고, 나머지 transient INTERNAL 만 retryable=true 를 단언. 추가로 misconfig 의 retryable=false 를 별도 단언.
3. `BusinessRuleValidationContractTest.deterministic_client_error_rows_are_never_retryable` 는 VALIDATION/AUTHZ/NOT_FOUND 만 검사하므로 영향 없음 (INTERNAL 미포함). `ErrorCodeRegistryMappingTest` 는 http_status 만 비교하므로 retryable drift 는 검출 안 함 — enum↔registry retryable 정합은 수동 보장.
## 교훈 / Lesson
- category 단위 일반화 invariant(`category → retryable`)는 편하지만, per-code 예외가 생기면 깨진다. retryable 은 **per-code SSOT**(registry)가 1차이고 category 는 보조.
- 자동 테스트가 잡지 못하는 정합(enum.retryable ↔ registry.retryable)은 review checklist 로 남겨야 한다.
## 검증
- `./gradlew :shared-contract:test` GREEN, `:app-bootstrap:test` (ErrorCodeRegistryMappingTest + BusinessRuleValidationContractTest) GREEN.