chore: 불필요한한 파일 제거

This commit is contained in:
DongHyeonka
2026-09-04 18:23:48 +09:00
parent 2efb7ee1f2
commit 4b9e7148b5
4 changed files with 0 additions and 2778 deletions
@@ -1,7 +0,0 @@
# Deterministic lint report
- Score: **100.0/100**
- Word count: **9043**
- Issues: **0**
No issues found.
File diff suppressed because it is too large Load Diff
-559
View File
@@ -1,559 +0,0 @@
# Evidence and decision provenance
> This is an internal sidecar. It is not reader-facing article content.
> Source IDs, repository paths, line ranges, status labels, and access dates belong here—not in `document.md`.
- Document: **브라우저 토큰에서 엣지 세션까지: Keycloak 인증 패턴 네 가지의 경계 설계**
- Citation rendering: `hidden`
- Evidence sources: **48**
## Section evidence map
| Section | Decision contract | Evidence | Status / location |
|---|---|---|---|
| 코드보다 먼저 드러난 문제 | — | `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns | `unspecified` · docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14) |
| ↳ | — | `AP1_BOUNDARY` AP1 SPA direct의 OAuth·token 책임 경계 | `reviewed` · docs/internal-spa-direct-no-google.md — AP1 internal SPA direct: local identity profile (lines 3-10) |
| ↳ | — | `AP2_BOUNDARY` AP2 confidential token mediator의 책임 경계 | `reviewed` · docs/ap2-token-boundary.md — 책임 경계 (lines 3-18) |
| ↳ | — | `AP3_BOUNDARY` AP3 BFF의 tokenless browser 경계 | `reviewed` · docs/ap3-bff-boundary.md — 요청과 token 경계 (lines 3-18) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
| 문제를 어렵게 만든 제약 | — | `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns | `unspecified` · docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14) |
| ↳ | — | `AP1_STORAGE` AP1 token 저장 선택과 수용 비용 | `reviewed` · docs/ap1-token-storage.md — AP1 token storage trade-off (lines 3-29) |
| ↳ | — | `AP2_GUARDRAILS` AP2 session, refresh custody, CORS와 audience 가드레일 | `reviewed` · token-mediator/src/main/resources/application.yml — AP2 session and OAuth client configuration (lines 3-34) |
| ↳ | — | `AP3_TRADEOFF` AP3와 AP1의 위협 모델·운영비 교환 | `reviewed` · docs/bff-vs-spa-direct.md — BFF vs SPA direct (lines 3-22) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
| ↳ | — | `AP4_RESPONSE_RUNTIME` AP4 trusted header input에서 edge identity JSON까지 | `reviewed` · backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java — currentUser and hasValidInternalToken (lines 27-53) |
| 검토한 선택지와 막힌 지점 | 상황·제약, 선택, 선택 이유, 검토한 대안, 수용한 비용, 보완 가드레일 | `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns | `unspecified` · docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14) |
| ↳ | — | `AP1_BOUNDARY` AP1 SPA direct의 OAuth·token 책임 경계 | `reviewed` · docs/internal-spa-direct-no-google.md — AP1 internal SPA direct: local identity profile (lines 3-10) |
| ↳ | — | `AP1_STORAGE` AP1 token 저장 선택과 수용 비용 | `reviewed` · docs/ap1-token-storage.md — AP1 token storage trade-off (lines 3-29) |
| ↳ | — | `AP2_BOUNDARY` AP2 confidential token mediator의 책임 경계 | `reviewed` · docs/ap2-token-boundary.md — 책임 경계 (lines 3-18) |
| ↳ | — | `AP2_IMPLEMENTATION` AP2 access-only handoff의 실제 구현 | `reviewed-discrepancy` · token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java — accessToken (lines 28-55) |
| ↳ | — | `AP3_BOUNDARY` AP3 BFF의 tokenless browser 경계 | `reviewed` · docs/ap3-bff-boundary.md — 요청과 token 경계 (lines 3-18) |
| ↳ | — | `AP3_TRADEOFF` AP3와 AP1의 위협 모델·운영비 교환 | `reviewed` · docs/bff-vs-spa-direct.md — BFF vs SPA direct (lines 3-22) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
| ↳ | — | `AP4_ALTERNATIVE` AP4 Traefik ForwardAuth 대안과 추가 비용 | `config-tested` · docs/traefik-forwardauth-alternative.md — Traefik ForwardAuth alternative (lines 3-22) |
| 선택의 이유와 지킨 경계 | 상황·제약, 선택, 선택 이유, 검토한 대안, 수용한 비용, 보완 가드레일 | `AP1_BOUNDARY` AP1 SPA direct의 OAuth·token 책임 경계 | `reviewed` · docs/internal-spa-direct-no-google.md — AP1 internal SPA direct: local identity profile (lines 3-10) |
| ↳ | — | `AP1_STORAGE` AP1 token 저장 선택과 수용 비용 | `reviewed` · docs/ap1-token-storage.md — AP1 token storage trade-off (lines 3-29) |
| ↳ | — | `AP2_BOUNDARY` AP2 confidential token mediator의 책임 경계 | `reviewed` · docs/ap2-token-boundary.md — 책임 경계 (lines 3-18) |
| ↳ | — | `AP3_BOUNDARY` AP3 BFF의 tokenless browser 경계 | `reviewed` · docs/ap3-bff-boundary.md — 요청과 token 경계 (lines 3-18) |
| ↳ | — | `AP3_TRADEOFF` AP3와 AP1의 위협 모델·운영비 교환 | `reviewed` · docs/bff-vs-spa-direct.md — BFF vs SPA direct (lines 3-22) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
| ↳ | — | `AP4_ALTERNATIVE` AP4 Traefik ForwardAuth 대안과 추가 비용 | `config-tested` · docs/traefik-forwardauth-alternative.md — Traefik ForwardAuth alternative (lines 3-22) |
| 선택이 코드와 흐름에 반영되는 방식 | — | `AP1_LOGIN_RUNTIME` AP1 SPA authorization, callback와 browser token data flow | `reviewed` · frontend/src/app.js — UserManager configuration, callback, and renderSession (lines 9-81) |
| ↳ | — | `AP1_PKCE_DEMO_GAP` AP1 manual PKCE helper와 실제 signin path의 구분 | `reviewed-gap` · frontend/src/pkce.js — createPkcePair (lines 1-25) |
| ↳ | — | `AP1_API_RUNTIME` AP1 browser Bearer input에서 /api/me JSON까지 | `reviewed` · frontend/src/app.js — callProtectedApi (lines 83-109) |
| ↳ | — | `AP1_ROLE_FAILURE_RUNTIME` AP1 JWT failure와 realm role authorization 경계 | `reviewed-gap` · backend/src/main/java/com/example/keycloakpattern/KeycloakRealmRoleConverter.java — convert (lines 12-27) |
| ↳ | — | `AP2_LOGIN_FLOW` AP2 browser entry와 Spring oauth2Login code 교환 | `reviewed` · token-mediator/src/main/resources/static/app.js — loginButton click and OAuth client registration (lines 7-9) |
| ↳ | — | `AP2_BOUNDARY_RUNTIME` AP2 token boundary endpoint input과 output | `reviewed` · token-mediator/src/main/java/com/example/keycloakpattern/mediator/TokenBoundaryController.java — tokenBoundary (lines 25-42) |
| ↳ | — | `AP2_ACCESS_RUNTIME` AP2 access handoff와 browser direct API의 data transformation | `reviewed` · token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java — accessToken (lines 28-54) |
| ↳ | — | `AP2_RESOURCE_RUNTIME` AP2 Resource Server의 JWT input과 /api/me output | `reviewed` · backend/src/main/java/com/example/keycloakpattern/ApiController.java — currentUser (lines 21-28) |
| ↳ | — | `AP3_LOGIN_FLOW` AP3 oauth2Login과 server-side PKCE data flow | `reviewed` · bff/src/main/java/com/example/keycloakpattern/bff/SecurityConfig.java — authorizationRequestResolver and bffSecurity (lines 20-58) |
| ↳ | — | `AP3_BOUNDARY_RUNTIME` AP3 token boundary endpoint의 input과 관측 output | `reviewed` · bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — tokenBoundary (lines 44-64) |
| ↳ | — | `AP3_API_RUNTIME` AP3 session input에서 downstream Bearer와 reader JSON까지 | `reviewed` · bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — currentUser and authorizedClient (lines 67-111) |
| ↳ | — | `AP3_CSRF_RUNTIME` AP3 CSRF cookie-to-header transformation과 preferences output | `reviewed` · bff/src/main/java/com/example/keycloakpattern/bff/CsrfController.java — csrf (lines 14-23) |
| ↳ | — | `AP3_PREFERENCE_SCOPE` AP3 preferences 예시의 process-global state 간극 | `reviewed-gap` · bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — preferenceTheme and updatePreferences (lines 28-95) |
| ↳ | — | `AP4_LOGIN_RUNTIME` AP4 unauthenticated navigation에서 oauth2-proxy session까지 | `reviewed` · docker-compose.yml — oauth2-proxy service (lines 92-143) |
| ↳ | — | `AP4_REQUEST_RUNTIME` AP4 external request에서 auth subrequest와 upstream input까지 | `reviewed` · frontend/default.conf.template — auth_request and upstream mapping (lines 13-74) |
| ↳ | — | `AP4_RESPONSE_RUNTIME` AP4 trusted header input에서 edge identity JSON까지 | `reviewed` · backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java — currentUser and hasValidInternalToken (lines 27-53) |
| 결정이 지켜지는지 확인하는 방법 | — | `AP1_VERIFY` AP1 브라우저 흐름과 token 수명주기 검증 계약 | `test-defined` · e2e/pattern1.mjs — AP1 Playwright acceptance contract (lines 82-202) |
| ↳ | — | `AP1_ROLE_FAILURE_RUNTIME` AP1 JWT failure와 realm role authorization 경계 | `reviewed-gap` · backend/src/main/java/com/example/keycloakpattern/KeycloakRealmRoleConverter.java — convert (lines 12-27) |
| ↳ | — | `AP2_VERIFY` AP2 access-only 전달과 브라우저 직접 API 호출 검증 계약 | `test-defined` · e2e/pattern2.mjs — AP2 Playwright acceptance contract (lines 39-112) |
| ↳ | — | `AP2_ACCESS_RUNTIME` AP2 access handoff와 browser direct API의 data transformation | `reviewed` · token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java — accessToken (lines 28-54) |
| ↳ | — | `AP3_VERIFY` AP3 browser token 비노출과 CSRF 방어 검증 계약 | `test-defined` · e2e/pattern3.mjs — AP3 Playwright acceptance contract (lines 43-191) |
| ↳ | — | `AP3_CSRF_RUNTIME` AP3 CSRF cookie-to-header transformation과 preferences output | `reviewed` · bff/src/main/java/com/example/keycloakpattern/bff/CsrfController.java — csrf (lines 14-23) |
| ↳ | — | `AP4_VERIFY` AP4 edge login과 header spoofing 방어 검증 계약 | `test-defined` · e2e/pattern4.mjs — AP4 Playwright acceptance contract (lines 44-131) |
| ↳ | — | `AP4_RESPONSE_RUNTIME` AP4 trusted header input에서 edge identity JSON까지 | `reviewed` · backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java — currentUser and hasValidInternalToken (lines 27-53) |
| ↳ | — | `BRANCH_REACHABILITY` 네 pattern branch와 39개 feature ref의 도달성 | `partially-verified` · docs/keycloak-branch-manifest.tsv — branch target delivery registry (lines 1-40) |
| 얻은 것, 잃은 것, 적용하지 않을 때 | 상황·제약, 선택, 선택 이유, 검토한 대안, 수용한 비용, 보완 가드레일 | `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns | `unspecified` · docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14) |
| ↳ | — | `AP1_STORAGE` AP1 token 저장 선택과 수용 비용 | `reviewed` · docs/ap1-token-storage.md — AP1 token storage trade-off (lines 3-29) |
| ↳ | — | `AP2_GUARDRAILS` AP2 session, refresh custody, CORS와 audience 가드레일 | `reviewed` · token-mediator/src/main/resources/application.yml — AP2 session and OAuth client configuration (lines 3-34) |
| ↳ | — | `AP3_TRADEOFF` AP3와 AP1의 위협 모델·운영비 교환 | `reviewed` · docs/bff-vs-spa-direct.md — BFF vs SPA direct (lines 3-22) |
| ↳ | — | `AP3_PREFERENCE_SCOPE` AP3 preferences 예시의 process-global state 간극 | `reviewed-gap` · bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — preferenceTheme and updatePreferences (lines 28-95) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
| ↳ | — | `AP4_ALTERNATIVE` AP4 Traefik ForwardAuth 대안과 추가 비용 | `config-tested` · docs/traefik-forwardauth-alternative.md — Traefik ForwardAuth alternative (lines 3-22) |
| 결국 지키려던 것은 무엇이었나 | — | `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns | `unspecified` · docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14) |
| ↳ | — | `AP1_BOUNDARY` AP1 SPA direct의 OAuth·token 책임 경계 | `reviewed` · docs/internal-spa-direct-no-google.md — AP1 internal SPA direct: local identity profile (lines 3-10) |
| ↳ | — | `AP2_BOUNDARY` AP2 confidential token mediator의 책임 경계 | `reviewed` · docs/ap2-token-boundary.md — 책임 경계 (lines 3-18) |
| ↳ | — | `AP3_BOUNDARY` AP3 BFF의 tokenless browser 경계 | `reviewed` · docs/ap3-bff-boundary.md — 요청과 token 경계 (lines 3-18) |
| ↳ | — | `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계 | `reviewed` · docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70) |
## Source details
### `AP1_BOUNDARY` AP1 SPA direct의 OAuth·token 책임 경계
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/internal-spa-direct-no-google.md — AP1 internal SPA direct: local identity profile (lines 3-10)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/docs/internal-spa-direct-no-google.md`
- Claim IDs: `AP1-C1`
- Decision IDs: `AP1-D1`
- Retrieval priority: `100.0000`
### `AP1_STORAGE` AP1 token 저장 선택과 수용 비용
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/ap1-token-storage.md — AP1 token storage trade-off (lines 3-29)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/docs/ap1-token-storage.md`
- Claim IDs: `AP1-C2`
- Decision IDs: `AP1-D2`
- Retrieval priority: `100.0000`
### `AP1_LOGIN_RUNTIME` AP1 SPA authorization, callback와 browser token data flow
- Type: `canonical-project`
- Status: `reviewed`
- Location: `frontend/src/app.js — UserManager configuration, callback, and renderSession (lines 9-81)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/frontend/src/app.js`
- Claim IDs: `AP1-C4`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP1_PKCE_DEMO_GAP` AP1 manual PKCE helper와 실제 signin path의 구분
- Type: `canonical-project`
- Status: `reviewed-gap`
- Location: `frontend/src/pkce.js — createPkcePair (lines 1-25)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/frontend/src/pkce.js`
- Claim IDs: `AP1-C5`
- Decision IDs: —
- Retrieval priority: `85.0000`
### `AP1_API_RUNTIME` AP1 browser Bearer input에서 /api/me JSON까지
- Type: `canonical-project`
- Status: `reviewed`
- Location: `frontend/src/app.js — callProtectedApi (lines 83-109)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/frontend/src/app.js`
- Claim IDs: `AP1-C6`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP1_ROLE_FAILURE_RUNTIME` AP1 JWT failure와 realm role authorization 경계
- Type: `canonical-project`
- Status: `reviewed-gap`
- Location: `backend/src/main/java/com/example/keycloakpattern/KeycloakRealmRoleConverter.java — convert (lines 12-27)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/backend/src/main/java/com/example/keycloakpattern/KeycloakRealmRoleConverter.java`
- Claim IDs: `AP1-C7`
- Decision IDs: —
- Retrieval priority: `90.0000`
### `AP1_GUARDRAILS` AP1 public client와 Resource Server 가드레일
- Type: `canonical-project`
- Status: `reviewed`
- Location: `keycloak/import/keycloak-patterns-realm.json — spa-public client and realm token settings (lines 11-73)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/keycloak/import/keycloak-patterns-realm.json`
- Claim IDs: `AP1-C3`
- Decision IDs: —
- Retrieval priority: `85.0000`
### `AP1_VERIFY` AP1 브라우저 흐름과 token 수명주기 검증 계약
- Type: `canonical-project`
- Status: `test-defined`
- Location: `e2e/pattern1.mjs — AP1 Playwright acceptance contract (lines 82-202)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern1/e2e/pattern1.mjs`
- Claim IDs: `AP1-T1`
- Decision IDs: —
- Retrieval priority: `80.0000`
### `AP2_BOUNDARY` AP2 confidential token mediator의 책임 경계
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/ap2-token-boundary.md — 책임 경계 (lines 3-18)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/docs/ap2-token-boundary.md`
- Claim IDs: `AP2-C1`
- Decision IDs: `AP2-D1`
- Retrieval priority: `100.0000`
### `AP2_IMPLEMENTATION` AP2 access-only handoff의 실제 구현
- Type: `canonical-project`
- Status: `reviewed-discrepancy`
- Location: `token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java — accessToken (lines 28-55)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java`
- Claim IDs: `AP2-C2`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP2_LOGIN_FLOW` AP2 browser entry와 Spring oauth2Login code 교환
- Type: `canonical-project`
- Status: `reviewed`
- Location: `token-mediator/src/main/resources/static/app.js — loginButton click and OAuth client registration (lines 7-9)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/token-mediator/src/main/resources/static/app.js`
- Claim IDs: `AP2-C4`
- Decision IDs: —
- Retrieval priority: `90.0000`
### `AP2_BOUNDARY_RUNTIME` AP2 token boundary endpoint input과 output
- Type: `canonical-project`
- Status: `reviewed`
- Location: `token-mediator/src/main/java/com/example/keycloakpattern/mediator/TokenBoundaryController.java — tokenBoundary (lines 25-42)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/token-mediator/src/main/java/com/example/keycloakpattern/mediator/TokenBoundaryController.java`
- Claim IDs: `AP2-C5`
- Decision IDs: —
- Retrieval priority: `95.0000`
### `AP2_ACCESS_RUNTIME` AP2 access handoff와 browser direct API의 data transformation
- Type: `canonical-project`
- Status: `reviewed`
- Location: `token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java — accessToken (lines 28-54)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/token-mediator/src/main/java/com/example/keycloakpattern/mediator/AccessTokenController.java`
- Claim IDs: `AP2-C6`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP2_RESOURCE_RUNTIME` AP2 Resource Server의 JWT input과 /api/me output
- Type: `canonical-project`
- Status: `reviewed`
- Location: `backend/src/main/java/com/example/keycloakpattern/ApiController.java — currentUser (lines 21-28)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/backend/src/main/java/com/example/keycloakpattern/ApiController.java`
- Claim IDs: `AP2-C7`
- Decision IDs: —
- Retrieval priority: `95.0000`
### `AP2_GUARDRAILS` AP2 session, refresh custody, CORS와 audience 가드레일
- Type: `canonical-project`
- Status: `reviewed`
- Location: `token-mediator/src/main/resources/application.yml — AP2 session and OAuth client configuration (lines 3-34)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/token-mediator/src/main/resources/application.yml`
- Claim IDs: `AP2-C3`
- Decision IDs: —
- Retrieval priority: `85.0000`
### `AP2_VERIFY` AP2 access-only 전달과 브라우저 직접 API 호출 검증 계약
- Type: `canonical-project`
- Status: `test-defined`
- Location: `e2e/pattern2.mjs — AP2 Playwright acceptance contract (lines 39-112)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern2/e2e/pattern2.mjs`
- Claim IDs: `AP2-T1`
- Decision IDs: —
- Retrieval priority: `80.0000`
### `AP3_BOUNDARY` AP3 BFF의 tokenless browser 경계
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/ap3-bff-boundary.md — 요청과 token 경계 (lines 3-18)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/docs/ap3-bff-boundary.md`
- Claim IDs: `AP3-C1`
- Decision IDs: `AP3-D1`
- Retrieval priority: `100.0000`
### `AP3_TRADEOFF` AP3와 AP1의 위협 모델·운영비 교환
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/bff-vs-spa-direct.md — BFF vs SPA direct (lines 3-22)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/docs/bff-vs-spa-direct.md`
- Claim IDs: `AP3-C2`
- Decision IDs: `AP3-D2`
- Retrieval priority: `100.0000`
### `AP3_GUARDRAILS` AP3 CSRF token과 SameSite 가드레일
- Type: `canonical-project`
- Status: `reviewed`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/SecurityConfig.java — bffSecurity (lines 25-58)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/SecurityConfig.java`
- Claim IDs: `AP3-C3`
- Decision IDs: —
- Retrieval priority: `85.0000`
### `AP3_LOGIN_FLOW` AP3 oauth2Login과 server-side PKCE data flow
- Type: `canonical-project`
- Status: `reviewed`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/SecurityConfig.java — authorizationRequestResolver and bffSecurity (lines 20-58)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/SecurityConfig.java`
- Claim IDs: `AP3-C4`
- Decision IDs: —
- Retrieval priority: `95.0000`
### `AP3_BOUNDARY_RUNTIME` AP3 token boundary endpoint의 input과 관측 output
- Type: `canonical-project`
- Status: `reviewed`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — tokenBoundary (lines 44-64)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/BffController.java`
- Claim IDs: `AP3-C5`
- Decision IDs: —
- Retrieval priority: `95.0000`
### `AP3_API_RUNTIME` AP3 session input에서 downstream Bearer와 reader JSON까지
- Type: `canonical-project`
- Status: `reviewed`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — currentUser and authorizedClient (lines 67-111)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/BffController.java`
- Claim IDs: `AP3-C6`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP3_CSRF_RUNTIME` AP3 CSRF cookie-to-header transformation과 preferences output
- Type: `canonical-project`
- Status: `reviewed`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/CsrfController.java — csrf (lines 14-23)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/CsrfController.java`
- Claim IDs: `AP3-C7`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP3_PREFERENCE_SCOPE` AP3 preferences 예시의 process-global state 간극
- Type: `canonical-project`
- Status: `reviewed-gap`
- Location: `bff/src/main/java/com/example/keycloakpattern/bff/BffController.java — preferenceTheme and updatePreferences (lines 28-95)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/bff/src/main/java/com/example/keycloakpattern/bff/BffController.java`
- Claim IDs: `AP3-C8`
- Decision IDs: —
- Retrieval priority: `90.0000`
### `AP3_VERIFY` AP3 browser token 비노출과 CSRF 방어 검증 계약
- Type: `canonical-project`
- Status: `test-defined`
- Location: `e2e/pattern3.mjs — AP3 Playwright acceptance contract (lines 43-191)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern3/e2e/pattern3.mjs`
- Claim IDs: `AP3-T1`
- Decision IDs: —
- Retrieval priority: `80.0000`
### `AP4_BOUNDARY` AP4 oauth2-proxy와 nginx edge 책임 경계
- Type: `branch-note`
- Status: `reviewed`
- Location: `docs/ap4-edge-forward-auth.md — AP4 oauth2-proxy Edge Forward Auth (lines 3-70)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/docs/ap4-edge-forward-auth.md`
- Claim IDs: `AP4-C1`
- Decision IDs: `AP4-D1`
- Retrieval priority: `100.0000`
### `AP4_NGINX` AP4 auth_request와 identity header 덮어쓰기
- Type: `canonical-project`
- Status: `reviewed`
- Location: `frontend/default.conf.template — nginx AP4 server configuration (lines 13-74)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/frontend/default.conf.template`
- Claim IDs: `AP4-C2`
- Decision IDs: —
- Retrieval priority: `90.0000`
### `AP4_LOGIN_RUNTIME` AP4 unauthenticated navigation에서 oauth2-proxy session까지
- Type: `canonical-project`
- Status: `reviewed`
- Location: `docker-compose.yml — oauth2-proxy service (lines 92-143)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/docker-compose.yml`
- Claim IDs: `AP4-C5`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP4_REQUEST_RUNTIME` AP4 external request에서 auth subrequest와 upstream input까지
- Type: `canonical-project`
- Status: `reviewed`
- Location: `frontend/default.conf.template — auth_request and upstream mapping (lines 13-74)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/frontend/default.conf.template`
- Claim IDs: `AP4-C6`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP4_RESPONSE_RUNTIME` AP4 trusted header input에서 edge identity JSON까지
- Type: `canonical-project`
- Status: `reviewed`
- Location: `backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java — currentUser and hasValidInternalToken (lines 27-53)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java`
- Claim IDs: `AP4-C7`
- Decision IDs: —
- Retrieval priority: `100.0000`
### `AP4_BACKEND` AP4 upstream의 내부 token 검증
- Type: `canonical-project`
- Status: `reviewed`
- Location: `backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java — currentUser and hasValidInternalToken (lines 18-53)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/backend/src/main/java/com/example/keycloakpattern/EdgeIdentityController.java`
- Claim IDs: `AP4-C3`
- Decision IDs: —
- Retrieval priority: `85.0000`
### `AP4_VERIFY` AP4 edge login과 header spoofing 방어 검증 계약
- Type: `canonical-project`
- Status: `test-defined`
- Location: `e2e/pattern4.mjs — AP4 Playwright acceptance contract (lines 44-131)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/e2e/pattern4.mjs`
- Claim IDs: `AP4-T1`
- Decision IDs: —
- Retrieval priority: `80.0000`
### `AP4_ALTERNATIVE` AP4 Traefik ForwardAuth 대안과 추가 비용
- Type: `branch-note`
- Status: `config-tested`
- Location: `docs/traefik-forwardauth-alternative.md — Traefik ForwardAuth alternative (lines 3-22)`
- Public/reference URL: `repo://keycloak-pattern/develop-keycloak-pattern4/docs/traefik-forwardauth-alternative.md`
- Claim IDs: `AP4-C4`
- Decision IDs: `AP4-D2`
- Retrieval priority: `85.0000`
### `BRANCH_REACHABILITY` 네 pattern branch와 39개 feature ref의 도달성
- Type: `canonical-project`
- Status: `partially-verified`
- Location: `docs/keycloak-branch-manifest.tsv — branch target delivery registry (lines 1-40)`
- Public/reference URL: `repo://keycloak-pattern/develop/docs/keycloak-branch-manifest.tsv`
- Claim IDs: `COMMON-T1`
- Decision IDs: —
- Retrieval priority: `70.0000`
### `L4121b8d86b` four pattern tradeoff matrix — Four Keycloak integration patterns
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/four-pattern-tradeoff-matrix.md — Four Keycloak integration patterns (lines 1-14)`
- Public/reference URL: `repo:///docs/four-pattern-tradeoff-matrix.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `45.7404`
### `La5d0a70f24` four pattern tradeoff matrix — 이 repository의 실행 증거
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/four-pattern-tradeoff-matrix.md — 이 repository의 실행 증거 (lines 28-37)`
- Public/reference URL: `repo:///docs/four-pattern-tradeoff-matrix.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `21.7129`
### `L2c120c8093` four pattern tradeoff matrix — 선택 기준
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/four-pattern-tradeoff-matrix.md — 선택 기준 (lines 15-27)`
- Public/reference URL: `repo:///docs/four-pattern-tradeoff-matrix.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `17.2810`
### `L4ec23ba045` keycloak branch index — Keycloak branch implementation index
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/keycloak-branch-index.md — Keycloak branch implementation index (lines 1-29)`
- Public/reference URL: `repo:///docs/keycloak-branch-index.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `14.8301`
### `Lb39734ea9b` google idp brokering — Google IdP brokering
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/google-idp-brokering.md — Google IdP brokering (lines 1-5)`
- Public/reference URL: `repo:///docs/google-idp-brokering.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `5.8515`
### `La28755902d` google claim to role — Google claim-to-role mapping
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/google-claim-to-role.md — Google claim-to-role mapping (lines 1-18)`
- Public/reference URL: `repo:///docs/google-claim-to-role.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `4.7503`
### `Le8474e5ddd` https termination — HTTPS termination: nginx or Caddy
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/https-termination.md — HTTPS termination: nginx or Caddy (lines 1-20)`
- Public/reference URL: `repo:///docs/https-termination.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `2.6850`
### `L0eb117abf5` google redirect uri policy — Google redirect URI policy
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/google-redirect-uri-policy.md — Google redirect URI policy (lines 1-24)`
- Public/reference URL: `repo:///docs/google-redirect-uri-policy.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `2.5149`
### `L5d2c3b8016` reverse proxy headers — Reverse proxy headers
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/reverse-proxy-headers.md — Reverse proxy headers (lines 1-15)`
- Public/reference URL: `repo:///docs/reverse-proxy-headers.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `1.8170`
### `L03b6abccb3` google claim mapping — Google claim and identity mapping
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/google-claim-mapping.md — Google claim and identity mapping (lines 1-23)`
- Public/reference URL: `repo:///docs/google-claim-mapping.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `1.5038`
### `L0217277f31` account linking sub vs email — Federated account key: `sub`, not email
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/account-linking-sub-vs-email.md — Federated account key: `sub`, not email (lines 1-18)`
- Public/reference URL: `repo:///docs/account-linking-sub-vs-email.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `1.4977`
### `L4a3b756b3d` google idp brokering — Two verification profiles
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/google-idp-brokering.md — Two verification profiles (lines 6-28)`
- Public/reference URL: `repo:///docs/google-idp-brokering.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `1.0205`
### `Le9a41ffd86` public domain tunneling — Public HTTPS domain for broker callbacks
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/public-domain-tunneling.md — Public HTTPS domain for broker callbacks (lines 1-21)`
- Public/reference URL: `repo:///docs/public-domain-tunneling.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `0.7299`
### `L55212df816` first broker login security — First Broker Login security
- Type: `local-document`
- Status: `unspecified`
- Location: `docs/first-broker-login-security.md — First Broker Login security (lines 1-27)`
- Public/reference URL: `repo:///docs/first-broker-login-security.md`
- Claim IDs: —
- Decision IDs: —
- Retrieval priority: `0.0881`
-163
View File
@@ -1,163 +0,0 @@
# Quality report
## Gate result
**PASS**
- Document type: `technical_blog`
- Reader language: `ko-KR`
- Citation mode: `hidden`
- Source pack: 48 entries
- Required H2 intents: 8/8, in contract order
- Deterministic lint: 100.0/100
- ClariDoc word count: 9,043
- Blockers: 0
- Errors: 0
- Warnings: 0
No mock-provider score is used as evidence of prose or factual quality.
## Evidence collection
All four pattern tips were inspected independently and read-only:
| Pattern | Git tip |
|---|---|
| AP1 | `bb8fd9333d7da1c6424d6e0b039fc1c80c2cf0ca` |
| AP2 | `d019846f8725bdb0badde33043b020dc252e32ff` |
| AP3 | `934c5da5d6edc2429dfb558b773656e46f21d677` |
| AP4 | `f4aea65dc6255eae07b20ebbe21e02fb6115e563` |
The canonical `develop` corpus was merged with branch-specific implementation,
configuration, test-contract, decision-rationale, and worked-flow evidence. The
expanded evidence covers browser entry, authorization callback, token/session
storage, controller and framework transformations, downstream requests, exact
reader JSON fields, failure statuses, and implementation gaps.
The common comparison described AP2 as a short or one-time handoff, but the
current controller returns the raw Keycloak access token on repeatable
authenticated GET requests and has no nonce consumption or deletion. The
article therefore uses the implementation-backed term `access-only handoff`.
## Reference-document calibration
The requested comparison document was inspected for its authoring pattern. Its
important technique is a concrete initial HTTP input followed through actual
classes and methods, intermediate models, next-hop input, and observable final
output. The revised Keycloak article applies the same technique separately to:
- AP1 login callback and browser Bearer `/api/me`;
- AP2 login session, `/token/boundary`, `/token/access`, and direct API call;
- AP3 login, `/bff/api/me`, CSRF issuance, and preference POST;
- AP4 login redirect, Nginx auth subrequest, upstream rewrite, and identity JSON.
## Independent reviews and revisions
### AP1 and AP2 technical review
Initial result: **NEEDS REVISION**
Material findings:
- the general Authorization Code introduction implied that every pattern used a
`code_challenge`, contradicting AP2's unverified PKCE boundary;
- the AP1 browser E2E was said to assert `username`, while its live assertion is
UI status plus decoded audience;
- AP2's `AP2_SESSION` transaction role before callback was missing;
- CORS wording could be mistaken for network-level access control;
- dynamic audience examples looked exact;
- AP1's local wildcard redirect registration and the diagnostic-server negative
test shape were not explicit.
All findings were revised. Targeted re-review result: **PASS**, with no remaining
blocker, error, or warning.
### AP3 and AP4 technical review
Initial result: **NEEDS REVISION**
Material findings:
- AP3 incorrectly placed the ID token in
`OAuth2AuthorizedClientService`; the corrected text separates access/refresh
token storage from the ID-token-derived OIDC principal in `SecurityContext`;
- AP4 was initially grouped with server-side session cookies and was assigned
persistent refresh-token custody; the corrected text describes the configured
minimal client-side cookie, absence of a shared server store, and the
unverified refresh lifecycle;
- the AP3 handler was named `updatePreferences` instead of the actual
`updatePreference`;
- the cross-site test was described beyond its exact assertion, which only
checks that `AP3_SESSION` is absent from the request.
All findings were revised. Targeted re-review result: **PASS**, with no adjacent
regression found.
### Reader, logic, evidence, and procedure review
Initial result: **PASS WITH ONE WARNING**
The only warning was that “oauth2-proxy manages the Keycloak session” could
confuse the IdP SSO session with AP4's proxy session. The sentence now says that
oauth2-proxy owns OIDC code exchange and `AP4_SESSION` verification while Nginx
owns upstream request and identity-header construction.
The reviewer confirmed that:
- all four patterns contain a complete
`input → transformation → next hop → output` trace;
- test-defined contracts remain separate from fresh execution claims;
- hidden source metadata does not leak into reader prose;
- destructive volume reset is surrounded by prerequisites, stop conditions,
backup, and recovery guidance;
- each choice includes context, rationale, alternative, accepted cost,
guardrail, and evidence boundary.
## Validation performed
- Brief and 48-entry SourcePack runtime validation: **PASS**
- Deterministic preliminary outline generation: **PASS**
- Refined outline contract: **PASS**, 8 required intents in order
- Every refined-outline evidence ID resolves in the SourcePack: **PASS**
- Reader/provenance separation and hidden-citation leakage lint: **PASS**
- Final deterministic document lint: **PASS**, 100.0/100, 0 issues
- ClariDoc unit and integration suite: **PASS**, 41 tests
- Target repository after inspection: clean `develop`
- Four remote pattern refs re-resolved to the reviewed Git tips: **PASS**
- Earlier read-only manifest/ref audit: 39 declared feature refs exist and are
reachable from their declared target branches
## Validation deliberately not performed
The pattern verification scripts rebuild their stacks after deleting Docker
volumes. They were not run during this documentation task. The article therefore
describes committed acceptance contracts rather than claiming a fresh runtime
PASS.
The repository-provided branch audit still depends on a branch-note inventory
outside the available local path. The separate read-only Git reachability check
does not substitute for those missing note files.
The ClariDoc `scripts/verify.sh` workflow was not run because this worktree
already contains extensive user changes and that workflow removes or rebuilds
distribution and generated demo artifacts. The non-destructive 41-test suite,
contract validation, outline validation, and final lint were run instead.
## Remaining evidence boundaries
- AP1's E2E does not directly assert the token-request `code_verifier`, automatic
silent renewal, exact IdP cookie flags, CORS preflight, invalid signature, or
expired-token negative cases. Its local realm uses wildcard redirects.
- AP2 does not implement one-time consumption and does not verify expiry-driven
refresh, logout, durable session/token storage, or handoff replay rejection.
- AP3 does not implement a shared session/token store, token-at-rest encryption,
coordinated logout, downstream failure mapping, or user-scoped persistence
for the preference example.
- AP4's minimal cookie does not establish persistent refresh-token custody. Role
propagation, generalized endpoint enforcement, state-changing-request CSRF,
multi-replica cookie-secret lifecycle, and internal secret rotation remain
outside the verified contract.
- The Google harness uses a controllable mock identity provider. Real external
accounts and public-HTTPS acceptance remain separate.
- Performance, load, high availability, recovery, and long-duration session
behavior are outside the verified scope.