Files
llm-wiki/docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-report.md
T

22 KiB

Keycloak Branch-note 설계 일관성 리뷰

일자 / Date: 2026-07-18
범위 / Scope: raw/branch-notes에서 파일명 또는 본문에 keycloak이 있는 38개 파일, 10,649줄
Verdict: PARTIAL — derived from controller-verification.md
요청 언어 / User language: ko

이 verdict는 controller-verification.md의 gate 결과에서 자동 산출되었다.

0. Source roots

해당 없음 / N/A. 인용한 source는 모두 현재 workspace 안에 있다.

1. 한눈 요약 / Executive Summary

38개 branch-note를 38/38 READ_FULL로 판독했으며 원문은 수정하지 않았다. 1차 finding 60개를 인용 158줄로 확인한 뒤 적대 리뷰에서 KEEP 21, DOWNGRADE 27, REJECT 12로 정리했고, 최종 High는 10개다. 가장 큰 실행 위험은 audience 값, container issuer 도달성, SPA endpoint origin, Caddy path strip, account-link hard-reject 범위, SPA Direct와 TMB 경계다. 결정론 checker는 Keycloak 범위에서 BARE_DECISION_REF 8건을 찾았고 dangling 또는 exact dual-ownership finding은 내지 않았다. 문서 전문 판독은 끝났지만 Claims Extracted가 38개 중 2개에만 있고 298 logical reference edge 중 의미 대조는 고위험 후보 20건으로 제한했으므로 원천 Claim 및 전체 edge 수준에서는 추가 검증이 남는다.

2. Evidence Matrix

정본: evidence-matrix.md

Path Status Evidence Extracted facts
raw/branch-notes/experiment-nplus1-highlight-feed.md READ_FULL L1-L233 Keycloak은 예정 sibling 주제로만 등장한다.
raw/branch-notes/feature-authentication-authorization-contract.md READ_FULL L1-L341 raw role과 permission registry 경계.
raw/branch-notes/feature-boundary-validation-mapping-contract.md READ_FULL L1-L407 Keycloak은 sample seed 설명에 등장한다.
raw/branch-notes/feature-keycloak-account-linking-spa-ux.md READ_FULL L1-L228 account-link UX, First Broker Login, unlink, CIAL.
raw/branch-notes/feature-keycloak-account-linking-sub-vs-email.md READ_FULL L1-L279 sub key, collision, re-auth, unlink, Sync Mode.
raw/branch-notes/feature-keycloak-bff-vs-spa-direct.md READ_FULL L1-L274 SPA Direct와 BFF 선택.
raw/branch-notes/feature-keycloak-docker-compose-stack.md READ_FULL L1-L287 Compose topology, import, issuer/network.
raw/branch-notes/feature-keycloak-edge-forwardauth-google-federation.md READ_FULL L1-L325 P1B brokering과 child ownership.
raw/branch-notes/feature-keycloak-edge-forwardauth-no-google.md READ_FULL L1-L316 P1A ForwardAuth와 cookie session.
raw/branch-notes/feature-keycloak-federation-spa-zero-change.md READ_FULL L1-L193 P2A→P2B login-path zero-change.
raw/branch-notes/feature-keycloak-first-broker-login-flow.md READ_FULL L1-L261 Confirm Link와 silent-link policy.
raw/branch-notes/feature-keycloak-google-claim-attribute-mapping.md READ_FULL L1-L238 attribute mapping과 IMPORT.
raw/branch-notes/feature-keycloak-google-redirect-uri-policy.md READ_FULL L1-L261 redirect URI와 JavaScript origins.
raw/branch-notes/feature-keycloak-header-spoofing-defense.md READ_FULL L1-L255 trusted header 방어 경계.
raw/branch-notes/feature-keycloak-https-termination-caddy-nginx.md READ_FULL L1-L284 TLS termination과 HSTS.
raw/branch-notes/feature-keycloak-idp-brokering-google-client.md READ_FULL L1-L251 Google IdP client와 trustEmail.
raw/branch-notes/feature-keycloak-idp-mappers-claim-to-role.md READ_FULL L1-L148 role mapping, FORCE, email verification.
raw/branch-notes/feature-keycloak-internal-spa-direct-google-federation.md READ_FULL L1-L512 P2B composition hub와 foreign detail.
raw/branch-notes/feature-keycloak-internal-spa-direct-no-google.md READ_FULL L1-L416 P2A SPA Direct와 token storage.
raw/branch-notes/feature-keycloak-iss-claim-hostname-mismatch.md READ_FULL L1-L287 issuer/JWKS 대안과 owner conflict.
raw/branch-notes/feature-keycloak-nginx-auth-request-integration.md READ_FULL L1-L306 auth_request body와 failure routing.
raw/branch-notes/feature-keycloak-oauth2-proxy-oidc-flow.md READ_FULL L1-L275 OIDC flow와 discovery dependency.
raw/branch-notes/feature-keycloak-patterns.md READ_FULL L1-L205 pattern taxonomy와 naming.
raw/branch-notes/feature-keycloak-pkce-flow-stages.md READ_FULL L1-L167 PKCE S256와 Admin terminology.
raw/branch-notes/feature-keycloak-public-domain-tunneling.md READ_FULL L1-L220 quick/named tunnel과 hostname.
raw/branch-notes/feature-keycloak-realm-client-export.md READ_FULL L1-L238 realm import와 credential export.
raw/branch-notes/feature-keycloak-refresh-rotation-and-logout.md READ_FULL L1-L254 rotation demonstration과 logout.
raw/branch-notes/feature-keycloak-refresh-token-rotation.md READ_FULL L1-L284 rotation contract와 receiver scope.
raw/branch-notes/feature-keycloak-reverse-proxy-headers.md READ_FULL L1-L297 proxy headers와 Caddy path.
raw/branch-notes/feature-keycloak-single-ec2-google-federation.md READ_FULL L1-L370 integration parent와 tunnel/proxy delegation.
raw/branch-notes/feature-keycloak-single-ec2-no-google.md READ_FULL L1-L342 base topology와 component ownership.
raw/branch-notes/feature-keycloak-spa-token-storage-tradeoff.md READ_FULL L1-L256 token storage, TMB, CSRF.
raw/branch-notes/feature-keycloak-spring-rs-audience-validator.md READ_FULL L1-L268 audience owner와 validator 선택.
raw/branch-notes/feature-keycloak-spring-rs-role-mapping.md READ_FULL L1-L231 RBAC와 audience delegation.
raw/branch-notes/feature-keycloak-three-leg-trust-chain.md READ_FULL L1-L229 federation/API validation hop.
raw/branch-notes/feature-keycloak-traefik-forwardauth-alternative.md READ_FULL L1-L237 Traefik ForwardAuth와 pattern attribution.
raw/branch-notes/feature-keycloak-vanilla-js-spa-pkce.md READ_FULL L1-L257 oidc-client-ts/manual PKCE와 endpoint URL.
raw/branch-notes/feature-security-operational-baseline.md READ_FULL L1-L417 auth code, CORS, JWT, public-path contract.

3. Controller Recomputed Coverage

모든 값은 controller가 disk의 source, lane, matrix, proof, adversarial artifact에서 다시 계산했다.

Metric Command Observed
N scope files controller_verify.py: content match enumeration 38
Source lines controller_verify.py: splitlines sum 10,649
M matrix rows controller_verify.py: evidence row parse 38
R READ_FULL controller_verify.py: status count 38
B BLOCKED controller_verify.py: status count 0
Missing / extra / duplicate / nonexistent paths controller_verify.py: set reconciliation 0 / 0 / 0 / 0
P per-file index sections controller_verify.py: section parse 38
T unique lane finding IDs controller_verify.py: heading parse 60
Finding schema failures controller_verify.py: source, severity, falsification, action check 0
Quote proof rows controller_verify.py: sed-proofs parse 60
Quote commands / failed verify_quotes.py 107 / 0
Verified quote output lines verify_quotes.py 158
A adversarial rows / generic rows controller_verify.py 60 / 0
Priority unresolved IDs controller_verify.py 0
Broken internal links controller_verify.py 0
Forbidden term hits in controller-generated prose controller_verify.py 0
Decision Evidence Map files controller_verify.py 38
Claims Extracted files / missing controller_verify.py 2 / 36
UNSUPPORTED_DECISION files / occurrences controller_verify.py 32 / 125
BROKEN_CLAIM_REFERENCE literal labels controller_verify.py 0
$ python3 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/verify_quotes.py
inventory_rows=38
inventory_unique=38
read_full=38
finding_ids=60
expected_finding_ids=60
commands_passed=107
commands_failed=0
verified_output_lines=158
findings_without_commands=0

3-1. Verdict Calculation

Coverage 식은 N=38, M=38, R=38, P=38, T=60, G=60으로 M==N, P==R, G==T를 만족한다. 9-gate controller에서는 claim source 역추적 미완료를 finding integrity에 포함했고, Claims Extracted가 2/38이므로 finding_gate만 FAIL이다. scope_gate와 matrix_gate는 PASS이고 source first reads도 완료되어 계산 결과는 PARTIAL이다.

Failed Gates from controller-verification.md

  • finding_gate: 60개 finding의 local source quote와 schema는 충족했지만 36개 파일에 Claims Extracted가 없어 raw Claim 의미까지의 traceability가 완료되지 않았다.

4. 파일별 발견 사항 / Per-File Findings

파일별 index: per-file-findings.md
인용 proof: sed-proofs.md
lane 상세: lane 01, lane 02, lane 03, lane 04

아래는 60개 finding registry다. 각 finding의 원문 quote, 가정, 반증 조건, action은 연결된 lane이 소유하며 quote status는 모두 VERIFIED다.

L1-F01 — ROLE_*와 raw-role registry 입력

  • Adversarial: KEEP → Medium · Evidence: lane 01 · Quote: VERIFIED
  • Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED

L1-F03 — delegated email_verified decision 복제

  • Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED

L1-F04 — password re-auth와 email verification profile

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 01 · Quote: VERIFIED

L1-F05 — IMPORT 선택 이유 stale

  • Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED

L1-F06 — sub key와 collision locator

  • Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED

L1-F07 — OAuth 2.1 BFF 조건 요약

  • Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED

L1-F08 — localhost issuer와 bridge reachability

  • Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED

L1-F09 — Google sub key dual owner

  • Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED

L1-F10 — P1A/P1B backend trust

  • Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED

L1-F11 — oauth2-proxy와 Traefik 선택축

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 01 · Quote: VERIFIED

L1-F12 — browser token custody 표현

  • Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED

L1-F13 — zero-change scope

  • Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED

L1-F14 — zero-change audience ambiguity

  • Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED
  • Adversarial: REJECT → N/A · Evidence: lane 02 · Quote: VERIFIED
  • Adversarial: KEEP → High · Evidence: lane 02 · Quote: VERIFIED

L2-F03 — IMPORT와 FORCE scope

  • Adversarial: DOWNGRADE → Low · Evidence: lane 02 · Quote: VERIFIED

L2-F04 — Google basic-scope test-user 설명

  • Adversarial: KEEP → Low · Evidence: lane 02 · Quote: VERIFIED

L2-F05 — JavaScript origins

  • Adversarial: DOWNGRADE → Low · Evidence: lane 02 · Quote: VERIFIED

L2-F06 — Caddy HSTS default

  • Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED

L2-F07 — Reference-Only와 foreign detail

  • Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED

L2-F08 — brokering zero-change ownership

  • Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED

L2-F09 — SPA Direct 안의 BFF variant

  • Adversarial: REJECT → N/A · Evidence: lane 02 · Quote: VERIFIED

L3-F01 — auth_request body 설명

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F02 — sign-in TODO 적용 범위

  • Adversarial: REJECT → N/A · Evidence: lane 03 · Quote: VERIFIED

L3-F03 — token introspection 용어

  • Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED

L3-F04 — bare decision reference

  • Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED

L3-F05 — retired numbered naming

  • Adversarial: DOWNGRADE → Low · Evidence: lane 03 · Quote: VERIFIED

L3-F06 — PKCE S256 D-row 중복

  • Adversarial: REJECT → N/A · Evidence: lane 03 · Quote: VERIFIED

L3-F07 — PKCE Admin label

  • Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED

L3-F08 — quick tunnel hostname

  • Adversarial: KEEP → High · Evidence: lane 03 · Quote: VERIFIED

L3-F09 — realm import wiring scope

  • Adversarial: DOWNGRADE → Low · Evidence: lane 03 · Quote: VERIFIED

L3-F10 — credential export certainty

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F11 — rotation contract와 execution

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F12 — back-channel receiver owner

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F13 — Max Reuse semantics

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F14 — Caddy prefix strip

  • Adversarial: KEEP → High · Evidence: lane 03 · Quote: VERIFIED

L3-F15 — tunnel provider dual owner

  • Adversarial: KEEP → Medium · Evidence: lane 03 · Quote: VERIFIED

L3-F16 — parent proxy bundle ownership

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED

L4-F01 — localhost와 extra_hosts 대안

  • Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED

L4-F02 — audience owner pointer stale

  • Adversarial: KEEP → Medium · Evidence: lane 04 · Quote: VERIFIED

L4-F03 — PKCE manual-first 대 library-first

  • Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED

L4-F04 — SPA Direct와 TMB 경계

  • Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED

L4-F05 — evidence status stale

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F07 — custom validator와 property-first

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F08 — backend audience와 spa-client

  • Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED

L4-F09 — role note의 audience 재명세

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F10 — realm-role-only 전제

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F11 — 3-leg taxonomy

  • Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED

L4-F12 — nonce 자동 처리 evidence

  • Adversarial: KEEP → Medium · Evidence: lane 04 · Quote: VERIFIED

L4-F13 — trust-chain foreign summary

  • Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED

L4-F14 — P3A pattern misattribution

  • Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED

L4-F15 — 302 생성 주체

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F16 — relative SPA endpoint origin

  • Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED

L4-F17 — oidc-client-ts storage default

  • Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED

L4-F18 — automaticSilentRenew mechanism

  • Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED

L4-F19 — Phase C2 active table

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED

L4-F20 — JWT decoder와 clock skew

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED

L4-F21 — public-path verification contract

  • Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED

4-1. 적대 리뷰 결과 / Adversarial Review Results

정본: adversarial-review.md

Metric Count
Reviewed 60
KEEP 21
DOWNGRADE 27
REJECT 12
Final High 10
Final Medium 18
Final Low 20
Controller override 0

Controller는 60개 권고를 모두 수용했다. REJECT는 중복 또는 active contradiction 전제 붕괴를 뜻하며 원문 상태의 무결함을 뜻하지 않는다.

5. 우선순위 권고 / Priority Recommendations

상세 Decision Conditions와 fix-plan: priority-recommendations.md

Rank Finding Action Verification
1 L4-F08 API audience symbol과 owner를 하나로 고정 realm export, token aud, 정상 및 wrong-audience test
2 L1-F08 issuer identity와 container retrieval address를 실행 profile 하나로 종결 rendered Compose, discovery와 JWKS log
3 L4-F16 relative SPA endpoint를 same-origin proxy 또는 runtime absolute URL 중 하나로 선택 browser와 access logs
4 L3-F14 Caddy와 Keycloak path prefix 전략을 맞춤 caddy adapt와 upstream path
5 L2-F02 silent-link와 hard-reject policy를 분리 flow export, SPI artifact, negative E2E
6 L4-F04 pure SPA와 TMB variant를 분리 refresh endpoint, CSRF, rotation E2E
7 L1-F10 P1A와 P1B의 backend trust를 한 invariant로 확정 SecurityFilterChain과 forwarding diff
8 L4-F14 deployment 축과 authentication pattern 축을 분리 pattern matrix와 component flow
9 L3-F08 quick tunnel과 managed static hostname을 분리 restart hostname과 redirect E2E
10 L1-F09 Google sub key의 mutable owner를 하나로 선택 owner map과 inbound references

6. 후속 작업 / Follow-Up

  • 사용자 승인 전 branch-note 원문 수정은 하지 않는다.
  • High 10건은 개별 승인 단위로, L3-F04의 reference syntax 8건은 low-risk 묶음 승인 단위로 제안한다.
  • logical edge 298건 전체 의미 대조가 필요하면 20건 이하 lane으로 분할하는 별도 sync round가 필요하다.
  • Claims Extracted 36개 누락과 raw Claim target 검증은 migrate-claims 또는 전용 traceability audit로 분리한다.
  • runtime 미검증과 code/canonical 범위는 unresolved-risk-register.md에 기록했다.

7. 검증 / Verification

7.1 Self-grep proof

  • Finding T=60
  • Finding별 proof row G=60
  • 실행 command=107, 실패=0
  • command stdout의 verified quote lines=158
  • 미검증 finding=0
  • 명령과 observed output은 sed-proofs.md와 각 lane에 있다.

7.2 실행한 검증

$ python3 .claude/hooks/wiki_consistency_check.py --all
repository files=102
repository findings=144
BARE_OWNER_REF=74
BARE_DECISION_REF=70
Keycloak-scope BARE_DECISION_REF=8
Keycloak-scope DANGLING_DECISION_REF=0
Keycloak-scope DANGLING_SECTION_REF=0
Keycloak-scope exact DUAL_OWNERSHIP=0

$ python3 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/controller_verify.py
raw_file_count=38
matrix_rows=38
read_full_rows=38
blocked_rows=0
missing_paths=0
extra_paths=0
duplicate_paths=0
nonexistent_paths=0
malformed_matrix_rows=0
lane_finding_count=60
unique_finding_ids=60
duplicate_finding_ids=0
missing_finding_ids=0
finding_schema_failures=0
per_file_sections=38
sed_proof_rows=60
adversarial_rows=60
adversarial_generic_hits=0
unresolved_priority_ids=0
broken_internal_links=0
forbidden_word_hits=0
missing_required_artifacts=0
decision_evidence_map_files=38
claims_extracted_files=2
missing_claims_extracted=36
unsupported_decision_occurrences=125

8. Generated Artifacts

Artifact Path
Master docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-report.md
Controller verification docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-controller-verification.md
Adversarial entry docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-adversarial-review.md
Evidence matrix docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/evidence-matrix.md
Per-file index docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/per-file-findings.md
Quote proofs docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/sed-proofs.md
Priority and fix-plan docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/priority-recommendations.md
Risk register docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/unresolved-risk-register.md
Adversarial matrix docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/adversarial-review.md
Lane 01 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-01-keycloak-sorted-01-10.md
Lane 02 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-02-keycloak-sorted-11-20.md
Lane 03 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-03-keycloak-sorted-21-30.md
Lane 04 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-04-keycloak-sorted-31-38.md
Semantic sample docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-05-semantic-risk-sample.md
Process plan docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/implementation_plan.md
Process task docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/task.md
Process walkthrough docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/walkthrough.md
Controller script docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/controller_verify.py
Quote script docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/verify_quotes.py