docs(keycloak-session-store): rewrite the prose and the diagram labels out of AI register

Two things read as machine-written and both are now fixed with the
repository's own tooling.

The diagram labels counted abstractions instead of naming things —
"틀린 예측 5건", "조용한 실패 9건", "로컬 아티팩트 76건". Replaced with what
those actually were, which is also more useful in a drawing:

  틀린 예측 5건        -> A-1 · A-2 · A-6 · B-4 · B-6
  조용한 실패 9건      -> NetworkPolicy · tc · kill · iptables
  로컬 아티팩트 76건   -> 연결수 0 · 50µs
  A층 결론 3건 반전    -> A-1 · A-2 · A-8

The prose was staccato: 30.7 characters average against a 48-75 reference,
45% of sentences under 25 characters, and causal connectives at 4.9 per 100
against a floor of 6. check_prose reported an error for closing six
sentences with 「~것이 ~이다」.

Roughly ninety sentences were rewritten — joining pairs that carry a real
causal or contrastive relation, and varying the joins. The first pass
overcorrected into a new monotony (는데 at 47 occurrences, connectives up to
31.9, above the ceiling), so twenty-three of those were varied into 지만,
-고, em-dashes, or split back apart.

  check_prose      FAIL error 1  ->  OK error 0
  평균 문장 길이    30.7  ->  43.1
  25자 미만 비율    45.4% ->  23.4%
  이유 연결어미     4.9   ->  within range

Two style_profile numbers still read outside the band, and the reason is
worth writing down rather than editing around: the tool counts each image
caption as a sentence, and this document carries 28 diagrams. Excluding
captions and separators the prose is 46.4 characters average with 14.3%
short — inside the reference range. Padding sentences to move the remaining
gap is what CLAUDE.md forbids, so it stops here.

Protected values were checked against source and are unchanged: 153건/149건,
1,872 ms, 20,000 ms, 22.2 초, 2305초, 845361바이트, 8856건, 205.7ms, 106초.
All 28 diagrams still lint clean with no sentence left on any canvas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-05 12:05:52 +09:00
co-authored by Claude Opus 5
parent 95c0e680b5
commit 73026cada6
35 changed files with 328 additions and 323 deletions
@@ -20,14 +20,14 @@ assets:
앞단에 세운 프록시가 로그인을 대신 받으면 upstream은 OAuth를 몰라도 되고, 대신 요청에 붙어 온 X-Auth-Request-User 하나로 사용자를 판단한다. 이 헤더는 인증을 마친 프록시가 붙일 수도 있고 브라우저가 직접 적어 보낼 수도 있는데, 두 값은 upstream이 받은 요청에서 이름도 형식도 같아 서로 구분되지 않는다.
그래서 이 구성에서는 헤더를 믿을 조건을 세 곳에 나눠 두었다. 밖에서 들어오는 길을 Nginx 8088 하나로 줄이고, Nginx가 클라이언트의 동명 헤더를 자기 값으로 덮어쓰고, upstream이 사용자 헤더와 함께 내부 토큰까지 대조한다. 세 곳은 각각 다른 구간을 맡아서 하나가 나머지 둘을 대신하지 못한다.
그래서 이 구성에서는 헤더를 믿을 조건을 세 곳에 나눠 두었다. 밖에서 들어오는 길을 Nginx 8088 하나로 줄이고, Nginx가 클라이언트의 동명 헤더를 자기 값으로 덮어쓰고, upstream이 사용자 헤더와 함께 내부 토큰까지 대조한다. 호스트 포트를 닫아도 같은 Compose 네트워크 안에서는 app의 8081에 닿을 수 있고 그 요청은 Nginx를 거치지 않으니, 덮어쓰기도 함께 지나친다. upstream이 내부 토큰을 따로 대조하는 것은 그 요청을 걸러 내기 위해서다.
## 관계
- **Forward-Auth에서 Identity Header를 신뢰하기 위한 조건**
그 기준이 세운 다섯 조건을 Nginx 설정과 upstream 코드에서 하나씩 찾아 어디에 들어가 있는지 확인했다.
- **OAuth Token과 Application Session을 구분하는 기준**
프록시 세션 쿠키 AP4_SESSION과 identity 헤더가 각각 다른 구간에서 쓰이고, upstream은 JWT를 입력으로 받지 않는다.
AP4_SESSION은 브라우저와 Nginx 사이에서만 오가고 identity 헤더는 Nginx와 upstream 사이에서만 붙으며, upstream은 JWT를 입력으로 받지 않는다.
- **OAuth/OIDC 인증 패턴 선택 기준**
이 구조를 고르면 OAuth를 모르는 upstream 앞에 공통 관문이 생기는 대신, 네트워크 경로와 헤더를 어디까지 믿을지를 따로 정해 두어야 한다.
- **Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가**
@@ -43,13 +43,13 @@ assets:
## 결론
헤더를 인증 근거로 쓰려면 서로 독립된 세 곳에서 막아야 한다.
헤더를 인증 근거로 쓰려면 세 곳에서 막아야 한다.
host port 닫힘 : 외부에서 upstream과 프록시로 바로 가는 경로를 막는다
Nginx header 덮어쓰기 : client가 보낸 동명 헤더를 merge하지 않고 덮어쓴다
upstream internal token : edge를 거치지 않은 내부 요청을 막는다
세 곳은 각각 다른 구간을 맡는다. 네트워크를 나눠 두는 것만으로는 내부 workload가 보낸 요청이나 Nginx가 잘못 넘긴 헤더가 신뢰되는 것까지 막지는 못한다. 컨트롤러가 들고 있는 공유 토큰만으로는 외부에서 upstream으로 바로 가는 경로가 막혀 있다는 네트워크 쪽 성질을 대신할다.
네트워크를 나눠 두는 것만으로는 내부 workload가 보낸 요청이나 Nginx가 잘못 넘긴 헤더가 신뢰되는 것까지 막지는 못한다. 공유 토큰만 두고 포트를 열어 두면, 그 토큰을 얻은 쪽이 Nginx를 건너뛰고 upstream 바로 붙을다.
## 검증 환경
@@ -143,7 +143,7 @@ X-Internal-Auth-Token: attacker-controlled-token
## 세 곳에서 나눠 막는다
헤더를 믿으려면 서로 독립된 세 곳에서 막아야 한다. 세 곳은 각각 다른 구간을 맡고 있어서 어느 하나도 나머지 둘의 자리를 대신하지 못한다.
헤더를 믿으려면 세 곳에서 막아야 한다. 각각이 걸러 내는 요청과 놓치는 요청이 다르므로, 아래에서 하나씩 무엇을 통과시키는지 함께 적는다.
### 밖에서 들어올 수 있는 길을 8088 하나로 줄인다
@@ -211,7 +211,7 @@ X-Internal-Auth-Token: <nginx-environment-secret>
:::
검사가 컨트롤러 하나에만 들어 있어서 운영으로 넘어갈 때는 필터나 인터셉터, security chain처럼 대상 엔드포인트 전체에 걸리는 공통 경계로 옮겨야 한다. 이 경계가 막는 것은 edge를 거치지 않 내부 요청이고, 공유 토큰만으로는 외부에서 upstream으로 바로 가는 경로가 어려워지는 네트워크 속성을 대신할 수 없다.
검사가 컨트롤러 하나에만 들어 있어서 운영으로 넘어갈 때는 필터나 인터셉터, security chain처럼 대상 엔드포인트 전체에 걸리는 공통 경계로 옮겨야 한다. 이 검사가 걸러 내는 것은 edge를 거치지 않고 들어온 내부 요청이다. 다만 토큰을 얻은 쪽에는 소용이 없으므로, 호스트 포트를 닫아 두는 일은 그대로 남는다.
### 경로에 따라 다른 코드가 돌아온다