47 lines
2.9 KiB
Markdown
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.
|