2 lines
217 KiB
JSON
2 lines
217 KiB
JSON
{"audit_request":{"assertions":[{"assertion_id":"AST-001","condition":"always","line_end":127,"line_start":127,"modality":"must","object":"diagram-standards v2 (minimalist) — 5초/30초 룰, 정점 ≤ 10, 간선 ≤ 8, callout ≤ 1, 80% 회색/흰색 + 강조 색 1~2","predicate":"has_threshold","quote":"> 6개 패턴 각각의 컴포넌트 구성도. **`templates/diagram-standards.md` v2 (minimalist) 준수** — 5초/30초 룰, 정점 ≤ 10, 간선 ≤ 8, callout ≤ 1, 80% 회색/흰색 + 강조 색 1~2 정도.","scope":"§3-1 아키텍처 다이어그램 6종","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"keycloak-patterns 시스템 아키텍처 다이어그램"},{"assertion_id":"AST-002","condition":"시스템 아키텍처 다이어그램 작성 시","line_end":129,"line_start":129,"modality":"must_not","object":"Mermaid graph TD 사용 (Mermaid 는 시퀀스/ER 다이어그램 전용)","predicate":"forbids","quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용.","scope":"§3-1 아키텍처 다이어그램","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"시스템 아키텍처 다이어그램 작성"},{"assertion_id":"AST-003","condition":"시스템 아키텍처 다이어그램 작성 시","line_end":129,"line_start":129,"modality":"must","object":"draw.io (.drawio 파일, 저장 경로 raw/diagrams/keycloak-patterns/)","predicate":"uses","quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용.","scope":"§3-1 아키텍처 다이어그램","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"시스템 아키텍처 다이어그램 작성"},{"assertion_id":"AST-004","condition":"P1A Edge ForwardAuth 패턴","line_end":160,"line_start":160,"modality":"must","object":"OIDC 인증 게이트 — 인증 안 된 요청을 Keycloak 으로 redirect","predicate":"owns","quote":"| Edge Proxy | OIDC 인증 게이트 — 인증 안 된 요청을 Keycloak으로 redirect | oauth2-proxy 또는 Traefik ForwardAuth |","scope":"P1A 컴포넌트 책임","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"Edge Proxy (P1A)"},{"assertion_id":"AST-005","condition":"P1A Edge ForwardAuth 패턴","line_end":161,"line_start":161,"modality":"must","object":"인증 검증 → Edge proxy (backend 는 비즈니스 로직만, 헤더로 사용자 식별, Spring Security 미사용)","predicate":"delegates","quote":"| Backend API | 비즈니스 로직만. 인증 검증은 proxy에 위임. 헤더로 사용자 식별 | Spring Boot 3.x (Spring Security 미사용) |","scope":"P1A 컴포넌트 책임","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"Backend API (P1A)"},{"assertion_id":"AST-006","condition":"P1A Edge ForwardAuth 패턴","line_end":162,"line_start":162,"modality":"must","object":"Authorization Server 역할 — 사용자 DB + OIDC discovery","predicate":"owns","quote":"| Keycloak | Authorization Server. 사용자 DB + OIDC discovery | Keycloak 25.x + PostgreSQL 16 |","scope":"P1A 컴포넌트 책임","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"Keycloak (P1A)"},{"assertion_id":"AST-007","condition":"ingress 우회 경로 존재 시","line_end":154,"line_start":153,"modality":"observed","object":"ingress 우회 경로 존재 시 X-Forwarded-User 위조 가능 — 방어는 NetworkPolicy(k8s)/SG(AWS) 격리 + 가능하면 mTLS","predicate":"has_failure_behavior","quote":"- backend 가 `X-Forwarded-User` 헤더만으로 사용자 식별 → ingress 우회 경로 존재 시 위조 가능\n- 해결: NetworkPolicy (k8s) 또는 SG (AWS) 로 proxy → backend 만 통과시키고, 가능하면 mTLS 추가","scope":"P1A 핵심 함정 (헤더 spoofing)","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P1A backend 헤더 신뢰 모델"},{"assertion_id":"AST-008","condition":"Google IdP brokering 사용 시 (email-match auto-linking 방지)","line_end":189,"line_start":189,"modality":"must","object":"Confirm Link Existing Account 강제 + email_verified=true 필수","predicate":"requires","quote":"- 해결: First Broker Login Flow 에서 `Confirm Link Existing Account` 강제 + `email_verified=true` 필수","scope":"P1B/P2B Google federation","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"First Broker Login Flow (Google federation)"},{"assertion_id":"AST-009","condition":"P1A 에 Google federation 을 추가할 때","line_end":193,"line_start":193,"modality":"observed","object":"Backend/proxy 코드 변경 0줄 — Keycloak Realm 설정만 추가","predicate":"has_cardinality","quote":"- Backend / proxy 코드는 변경 0줄 — Keycloak Realm 설정만 추가","scope":"P1B","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P1B Google federation 추가"},{"assertion_id":"AST-010","condition":"P2A SPA-direct 패턴","line_end":222,"line_start":222,"modality":"must","object":"JWT (iss, aud, exp, signature) — Spring Security 6.x Resource Server 로 직접 검증 코드 보유","predicate":"validates","quote":"- Backend 가 JWT validator 코드 보유 (`iss`, `aud`, `exp`, signature) — Spring Security 6.x Resource Server","scope":"P2A","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"Backend (P2A)"},{"assertion_id":"AST-011","condition":"KC_HOSTNAME 미설정 시","line_end":278,"line_start":277,"modality":"observed","object":"browser 는 public hostname 으로 호출 (iss=public host), backend 는 localhost:8180 JWKS 조회 → iss mismatch → 401","predicate":"has_failure_behavior","quote":"- Browser 는 EC2 public hostname 으로 Keycloak 호출 → JWT 의 `iss` claim = public host\n- Backend 는 `localhost:8180` 로 JWKS 조회 → `iss` 비교 시 mismatch → 401","scope":"P3A 핵심 함정 (KC_HOSTNAME)","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P3A Keycloak hostname 설정"},{"assertion_id":"AST-012","condition":"iss mismatch 401 방지","line_end":279,"line_start":279,"modality":"must","object":"KC_HOSTNAME=<public-host> + KC_HTTP_ENABLED=true 명시","predicate":"requires","quote":"- 해결: docker-compose 에 `KC_HOSTNAME=<public-host>` + `KC_HTTP_ENABLED=true` 명시","scope":"P3A","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P3A docker-compose 구성"},{"assertion_id":"AST-013","condition":"redirect_uri mismatch 방지","line_end":283,"line_start":282,"modality":"must","object":"등록 hostname 과 browser 접근 hostname 의 1:1 일치 (또는 둘 다 등록)","predicate":"requires","quote":"- Keycloak client 의 Valid Redirect URIs 등록 시 `localhost` 만 등록 / browser 가 `127.0.0.1` 접근 → mismatch\n- 해결: 등록과 접근 hostname 1:1 일치 또는 둘 다 등록","scope":"P3A 부차 함정 (redirect_uri)","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"Keycloak client Valid Redirect URIs"},{"assertion_id":"AST-014","condition":"single EC2 topology 사용 시","line_end":287,"line_start":287,"modality":"observed","object":"SPoF — EC2 1대 다운 = 전체 정지 (운영급은 P2A + Keycloak HA cluster)","predicate":"has_failure_behavior","quote":"- 단점: SPoF — EC2 1대 다운 = 전체 정지. 운영급은 P2A + Keycloak HA cluster.","scope":"P3A 트레이드오프","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P3A single EC2 배포"},{"assertion_id":"AST-015","condition":"Google federation 사용 시","line_end":312,"line_start":312,"modality":"must","object":"redirect_uri 와 Keycloak issuer 모두 공개 HTTPS host","predicate":"requires","quote":"- Google 이 검증하는 `redirect_uri` 와 Keycloak issuer 가 모두 공개 HTTPS host 여야 함","scope":"P3B 핵심 함정 (KC_HOSTNAME 공개 hostname 강제)","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"P3B Google federation"},{"assertion_id":"AST-016","condition":"AP2·AP3 다이어그램 미작성 상태","line_end":328,"line_start":328,"modality":"must","object":"needs-diagram — placeholder 는 백틱 코드로 비활성 유지, 사용자가 draw.io 작성 후 활성 임베드로 전환 (활성 임베드 방치 시 9a 린터 BROKEN_LINK)","predicate":"other","quote":"> 신 primary 축의 AP2·AP3 은 기존 6 `.drawio`(P1A~P3B = AP1 배포 변형 + AP4)에 대응 아키텍처 다이어그램이 없다. **needs-diagram** — 사용자가 draw.io 로 작성 후 아래 백틱을 풀어 활성 임베드로 전환한다. (미작성 파일을 활성 임베드로 두면 9a 린터가 `BROKEN_LINK` 로 잡으므로 placeholder 는 백틱 코드로 비활성.)","scope":"§3-1-7","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"AP2·AP3 아키텍처 다이어그램"},{"assertion_id":"AST-017","condition":"AP2·AP3 다이어그램 작성 시","line_end":333,"line_start":333,"modality":"must","object":"wiki-diagram-reviewer ≥95 (게이트는 존재만 판정, 품질 ≥95 는 사용자가 별도 실행)","predicate":"has_threshold","quote":"작성 시 `rules/diagram-standards.md` v2 (minimalist) 준수 + `wiki-diagram-reviewer` ≥95 별도 확인(게이트는 존재만 판정, 품질 ≥95 는 사용자가 별도 실행).","scope":"§3-1-7","source_surface":"SURF-1FB5A68428F1BD7348C2","subject":"AP2·AP3 다이어그램 품질"},{"assertion_id":"AST-018","condition":"always","line_end":375,"line_start":375,"modality":"observed","object":"AP1 (SPA-direct + Resource Server) 의 single-EC2 배포","predicate":"maps_to","quote":"> 위 P3A 시퀀스 = **AP1**(SPA-direct + Resource Server)의 single-EC2 배포. 아래는 나머지 3 패턴의 핵심 시퀀스(happy + error path).","scope":"§3-2 P3A/AP1 대응","source_surface":"SURF-A16A70A9C563B8192465","subject":"P3A 시퀀스"},{"assertion_id":"AST-019","condition":"로그인 시작 시","line_end":352,"line_start":352,"modality":"must","object":"PKCE code_verifier + code_challenge=SHA256(verifier)","predicate":"produces","quote":" SPA->>SPA: PKCE code_verifier 생성, code_challenge=SHA256(verifier)","scope":"P3A/AP1 시퀀스","source_surface":"SURF-A16A70A9C563B8192465","subject":"vanilla JS SPA (P3A/AP1)"},{"assertion_id":"AST-020","condition":"자격 증명 유효 분기","line_end":358,"line_start":357,"modality":"must","object":"Keycloak 의 302 redirect authorization code 수령","predicate":"runs_after","quote":" KC-->>SPA: 302 redirect with authorization code\n SPA->>KC: POST /token (code + code_verifier)","scope":"P3A/AP1 시퀀스","source_surface":"SURF-A16A70A9C563B8192465","subject":"SPA 의 POST /token (code + code_verifier) 교환"},{"assertion_id":"AST-021","condition":"Bearer access_token 으로 API 호출 시","line_end":361,"line_start":361,"modality":"must","object":"JWT — iss, aud, exp, signature (JWKS 사용)","predicate":"validates","quote":" API->>API: JWT 검증 (iss, aud, exp, signature with JWKS)","scope":"P3A/AP1 시퀀스","source_surface":"SURF-A16A70A9C563B8192465","subject":"Spring Boot Resource Server (P3A/AP1)"},{"assertion_id":"AST-022","condition":"aud claim mismatch 시","line_end":366,"line_start":365,"modality":"must","object":"aud claim mismatch → 401 Unauthorized {error: invalid_token}","predicate":"has_failure_behavior","quote":" else aud claim mismatch\n API-->>SPA: 401 Unauthorized {error: invalid_token}","scope":"P3A/AP1 시퀀스 error path","source_surface":"SURF-A16A70A9C563B8192465","subject":"Spring Boot Resource Server (P3A/AP1)"},{"assertion_id":"AST-023","condition":"시퀀스 다이어그램 작성 시","line_end":338,"line_start":338,"modality":"must","object":"templates/project-template.md §4 표준 — autonumber, actor vs participant 구분, alt/opt/loop 블록, Note over 비자명 동작","predicate":"requires","quote":"> 토큰 교환 흐름은 패턴마다 다름. happy path + 주요 error path 함께. `templates/project-template.md` §4 표준 준수 — `autonumber`, `actor` vs `participant` 구분, alt/opt/loop 블록, `Note over` 비자명한 동작.","scope":"§3-2 전체","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"§3-2 시퀀스 다이어그램"},{"assertion_id":"AST-024","condition":"AP2 Token-Mediating 패턴","line_end":395,"line_start":395,"modality":"must_not","object":"refresh_token 의 브라우저 전달 (백엔드만 보유)","predicate":"forbids","quote":" Note over BE: refresh_token 은 백엔드만 보유 (브라우저 미전달)","scope":"AP2 시퀀스","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP2 Backend (confidential client)"},{"assertion_id":"AST-025","condition":"로그인 성공 시","line_end":396,"line_start":396,"modality":"must","object":"access_token 만 브라우저에 전달","predicate":"returns","quote":" BE-->>B: access_token 만 전달","scope":"AP2 시퀀스","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP2 Backend (confidential client)"},{"assertion_id":"AST-026","condition":"access_token 만료 시","line_end":399,"line_start":399,"modality":"must","object":"백엔드 경유 refresh (백엔드 보유 refresh_token 으로 refresh_grant)","predicate":"delegates","quote":" else access_token 만료 (재발급은 백엔드 경유)","scope":"AP2 시퀀스 error path","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP2 access_token 재발급"},{"assertion_id":"AST-027","condition":"AP3 BFF 패턴","line_end":408,"line_start":408,"modality":"must","object":"토큰 0개 — session cookie 만 보유","predicate":"has_cardinality","quote":"### AP3: Backend-for-Frontend (BFF) — 토큰 0개, session cookie 만","scope":"AP3 시퀀스","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP3 BFF 패턴의 브라우저"},{"assertion_id":"AST-028","condition":"로그인 성공 시","line_end":428,"line_start":428,"modality":"must","object":"Set-Cookie: SESSION (httpOnly) — 브라우저에 토큰 없음","predicate":"returns","quote":" BFF-->>B: Set-Cookie: SESSION (httpOnly) — 브라우저에 토큰 없음","scope":"AP3 시퀀스","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"BFF (Spring oauth2Login)"},{"assertion_id":"AST-029","condition":"cookie 자동첨부 악용 CSRF 시도 시","line_end":435,"line_start":435,"modality":"must","object":"CSRF 위조 요청 → 403 (SameSite=Lax + CSRF token 검증 실패로 차단)","predicate":"has_failure_behavior","quote":" BFF-->>B: 403 (SameSite=Lax + CSRF token 검증 실패로 차단)","scope":"AP3 시퀀스 error path","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"BFF (Spring oauth2Login)"},{"assertion_id":"AST-030","condition":"ingress 우회 + network 격리 실패 시","line_end":460,"line_start":460,"modality":"observed","object":"network 격리 실패 시 ingress 우회 X-Forwarded-User 직접 주입이 200 으로 위조 성공","predicate":"has_failure_behavior","quote":" API-->>User: 200 (❌ network 격리 실패 시 위조 성공)","scope":"AP4 시퀀스 error path (signature 함정)","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP4 Backend API"},{"assertion_id":"AST-031","condition":"X-Forwarded-User 헤더 위조 방어","line_end":461,"line_start":461,"modality":"must","object":"NetworkPolicy/SG 로 proxy→API 만 통과 (+ mTLS)","predicate":"requires","quote":" Note over API: 방어 = NetworkPolicy/SG 로 proxy→API 만 통과 (+ mTLS)","scope":"AP4 시퀀스","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"AP4 Backend API 보호"},{"assertion_id":"AST-032","condition":"always","line_end":467,"line_start":467,"modality":"observed","object":"AP1~AP4 어디에도 코드 0줄로 얹히는 cross-cutting — 상세 다이어그램은 각 sub-branch 에 위임","predicate":"other","quote":"(Google brokering 은 AP1~AP4 어디에도 코드 0줄로 얹히는 cross-cutting. 상세 다이어그램은 각 sub-branch — [[raw/branch-notes/feature-keycloak-edge-forwardauth-google-federation]], [[raw/branch-notes/feature-keycloak-internal-spa-direct-google-federation]] — 에서.)","scope":"cross-cutting Google federation","source_surface":"SURF-BC8F97AEBA340930FBF1","subject":"Google IdP brokering"},{"assertion_id":"AST-033","condition":"현 phase 포함 범위","line_end":487,"line_start":487,"modality":"must","object":"AP1~AP4 4 패턴 실 구현 — single-EC2 로컬 스택 위 E2E(locally-verified) + signature 함정 재현→해결","predicate":"requires","quote":"- **4 인증-아키텍처 패턴(AP1~AP4) 실 구현** — 모두 single-EC2 로컬 스택 위에서 E2E(`locally-verified`) + signature 함정 재현→해결 (§1 성공기준, §8.0 branch 분해).","scope":"§5 포함 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 포함 범위"},{"assertion_id":"AST-034","condition":"현 phase 포함 범위","line_end":488,"line_start":488,"modality":"must","object":"Google IdP brokering cross-cutting 변형 1회 실 구현 + SPA/Backend 코드 0줄 변경 검증","predicate":"requires","quote":"- **Google IdP brokering** 을 cross-cutting 변형으로 1회 실 구현(어느 패턴에 얹어도 SPA/Backend 코드 0줄 변경 검증 포함).","scope":"§5 포함 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 포함 범위"},{"assertion_id":"AST-035","condition":"현 phase 포함 범위","line_end":489,"line_start":489,"modality":"must","object":"4 패턴 통합 trade-off 매트릭스 (토큰 위치 / 검증 주체 / XSS·CSRF surface / 선택 기준 / keycloak 설정)","predicate":"produces","quote":"- 4 패턴 통합 trade-off 매트릭스 (토큰 위치 / 검증 주체 / XSS·CSRF surface / 선택 기준 / keycloak 설정).","scope":"§5 포함 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 포함 범위"},{"assertion_id":"AST-036","condition":"현 phase","line_end":495,"line_start":495,"modality":"must_not","object":"cluster-internal / edge 배포 토폴로지의 별도 k8s/Traefik 환경 구축 (hostname·issuer·network 차이 문서화만 허용)","predicate":"forbids","quote":"- **배포 토폴로지 별도 구현**: 인증 아키텍처는 single-EC2 로 실 구현하고, cluster-internal / edge 는 hostname·issuer·network 차이만 문서화(별도 k8s/Traefik 환경 구축 안 함 — §2.2 cross-cutting).","scope":"§5 제외 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 제외 범위"},{"assertion_id":"AST-037","condition":"현 phase","line_end":496,"line_start":496,"modality":"must_not","object":"GitHub / Auth0 / Cognito 등 다른 OIDC Provider federation (Google 만 허용)","predicate":"forbids","quote":"- 다른 OIDC Provider(GitHub / Auth0 / Cognito) federation. Google만.","scope":"§5 제외 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 제외 범위"},{"assertion_id":"AST-038","condition":"현 phase","line_end":497,"line_start":497,"modality":"must_not","object":"React/Vue 등 SPA 프레임워크 도입 (vanilla JS 유지)","predicate":"forbids","quote":"- React/Vue 등 SPA 프레임워크 (vanilla JS 유지).","scope":"§5 제외 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 제외 범위"},{"assertion_id":"AST-039","condition":"현 phase","line_end":499,"line_start":499,"modality":"must_not","object":"mTLS, FAPI(Financial-grade API), DPoP 등 고급 보안 옵션 구현","predicate":"forbids","quote":"- mTLS, FAPI(Financial-grade API), DPoP 등 고급 보안 옵션.","scope":"§5 제외 범위","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"프로젝트 제외 범위"},{"assertion_id":"AST-040","condition":"4 client-integration 패턴 E2E 완료 전 (현 phase)","line_end":503,"line_start":503,"modality":"must","object":"본 프로젝트 현 phase 의 out-of-scope 이되 폐기가 아니라 후속 학습 트랙으로 예약","predicate":"other","quote":"> 사용자 확정: 4 client-integration 패턴 E2E 를 먼저 끝낸 뒤 별도 학습 트랙으로 착수. \"keycloak 다 알기\" 의 나머지 절반(server/운영 측면)이며, **본 프로젝트 현 phase 의 out-of-scope 이되 폐기가 아니라 후속 트랙으로 예약**한다.","scope":"§5 Deferred 트랙","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"keycloak SERVER-side 심화 트랙 (SPI/HA/multi-realm/Admin API/LDAP/token revocation)"},{"assertion_id":"AST-041","condition":"현 phase","line_end":514,"line_start":514,"modality":"must","object":"현 phase 명시적 out-of-scope (본 4 패턴은 authN 토큰 흐름 집중; 씨앗 feature-keycloak-idp-mappers-claim-to-role 존재, 4 패턴 E2E 후 각 패턴에 얹음, 폐기 아님)","predicate":"other","quote":"- **인가(Authorization) — keycloak roles → Spring `@PreAuthorize`**: 본 4 패턴은 authN(인증) 토큰 흐름에 집중한다. RBAC 인가는 별개 관심사이며 기존 씨앗 `feature-keycloak-idp-mappers-claim-to-role` 존재 — 4 패턴 E2E 후 각 패턴에 얹음(현 phase 명시적 out-of-scope, 폐기 아님).","scope":"§5 인접 관심사 커버리지 note","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"인가(Authorization) RBAC — keycloak roles → Spring @PreAuthorize"},{"assertion_id":"AST-042","condition":"현 phase","line_end":515,"line_start":515,"modality":"must","object":"refresh rotation + logout 후 session·token 무효화 커버리지 (§8.0 registry)","predicate":"owns","quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소).","scope":"§5 인접 관심사 커버리지 note — Logout / session termination","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-007 (feature-keycloak-refresh-rotation-and-logout)"},{"assertion_id":"AST-043","condition":"현 phase","line_end":515,"line_start":515,"modality":"must","object":"deferred — logout 관심사 중 이 심화만 후속으로 이월 (2026-07-23 경계 명확화, §8.0 WI-007 과의 이중 서술 해소)","predicate":"other","quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소).","scope":"§5 인접 관심사 커버리지 note — Logout / session termination","source_surface":"SURF-C73BCB1F8B2541AA5D7D","subject":"통합 front/back-channel logout 흐름 심화"},{"assertion_id":"AST-044","condition":"Status active","line_end":553,"line_start":553,"modality":"must","object":"AP1~AP4 인증 통합 아키텍처 + cross-cutting 변형이 canonical 분류축","predicate":"other","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"canonical 분류축 (DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1)"},{"assertion_id":"AST-045","condition":"always","line_end":553,"line_start":553,"modality":"must","object":"DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001 (안정 결정 레지스트리 Owner 열)","predicate":"owns","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"raw/project-notes/keycloak-patterns-overview"},{"assertion_id":"AST-046","condition":"Status active","line_end":554,"line_start":554,"modality":"must","object":"public client + Authorization Code + PKCE","predicate":"uses","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"AP1 (DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1)"},{"assertion_id":"AST-047","condition":"Status active","line_end":555,"line_start":555,"modality":"must","object":"token 은 backend session 에 저장, browser 에는 cookie 만","predicate":"uses","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"AP3 (DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1)"},{"assertion_id":"AST-048","condition":"Status active","line_end":556,"line_start":556,"modality":"must","object":"token 을 획득하고 access token 만 browser 에 전달","predicate":"returns","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"AP2 backend (DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1)"},{"assertion_id":"AST-049","condition":"Status active","line_end":557,"line_start":557,"modality":"must","object":"oauth2-proxy ForwardAuth","predicate":"uses","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"AP4 (DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1)"},{"assertion_id":"AST-050","condition":"Status active","line_end":558,"line_start":558,"modality":"must","object":"Keycloak IdP brokering + hardened First Broker Login","predicate":"uses","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"Google federation (DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1)"},{"assertion_id":"AST-051","condition":"Status documented-only","line_end":559,"line_start":559,"modality":"must","object":"E2E success + signature security failure 재현·해결 evidence","predicate":"has_threshold","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"done-bar (DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1)"},{"assertion_id":"AST-052","condition":"Status documented-only","line_end":560,"line_start":560,"modality":"must","object":"단일 realm keycloak-patterns + 인증 패턴별 client 분리","predicate":"has_cardinality","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"Keycloak realm/client 구성 (DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1)"},{"assertion_id":"AST-053","condition":"Status documented-only","line_end":561,"line_start":561,"modality":"must_not","object":"commit·realm export 평문 (env var 주입만 허용)","predicate":"forbids","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"confidential client secret (DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1)"},{"assertion_id":"AST-054","condition":"Status documented-only","line_end":562,"line_start":562,"modality":"must","object":"single-EC2 docker-compose","predicate":"uses","quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |","scope":"§6.1 안정 결정 레지스트리","source_surface":"SURF-E8D20E10C18A20571CB3","subject":"AP1~AP4 E2E 구현 topology (DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1)"},{"assertion_id":"AST-055","condition":"완료 조건 (측정가능)","line_end":569,"line_start":569,"modality":"must","object":"Keycloak·PostgreSQL·nginx·Spring 4 containers healthy + admin console 접속","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-001 (feature-keycloak-docker-compose-stack)"},{"assertion_id":"AST-056","condition":"완료 조건 (측정가능)","line_end":570,"line_start":570,"modality":"must","object":"realm import + client 4개 등록 후 unauthenticated protected endpoint 401 + export 재현","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-002 (feature-keycloak-realm-client-export)"},{"assertion_id":"AST-057","condition":"완료 조건 (측정가능)","line_end":572,"line_start":572,"modality":"must","object":"foreign audience token 수용 실패 재현 + audience validator 적용 후 401","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-004 (feature-keycloak-spring-rs-audience-validator)"},{"assertion_id":"AST-058","condition":"완료 조건 (측정가능)","line_end":573,"line_start":573,"modality":"must","object":"hostname 미설정 iss mismatch 401 재현 + 설정 후 복구 log 존재","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-005 (feature-keycloak-iss-claim-hostname-mismatch)"},{"assertion_id":"AST-059","condition":"현 phase 실행계획 (§8.0 registry, Status planned)","line_end":575,"line_start":575,"modality":"must","object":"refresh rotation + logout 후 session·token 무효화 검증","predicate":"owns","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-007 (feature-keycloak-refresh-rotation-and-logout)"},{"assertion_id":"AST-060","condition":"실행계획 의존 순서","line_end":575,"line_start":575,"modality":"must","object":"WI-KEYCLOAK-PATTERNS-OVERVIEW-004 (Dependencies 열)","predicate":"runs_after","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-007"},{"assertion_id":"AST-061","condition":"완료 조건 (측정가능)","line_end":577,"line_start":577,"modality":"must_not","object":"refresh token 이 network response 에 존재 (browser 는 access token 으로만 API 200)","predicate":"forbids","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-009 (feature-keycloak-token-mediating-access-handoff)"},{"assertion_id":"AST-062","condition":"완료 조건 (측정가능)","line_end":578,"line_start":578,"modality":"must","object":"browser token 0개 + SESSION cookie 만으로 BFF proxy API 200 재현","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-010 (feature-keycloak-bff-oauth2login-session)"},{"assertion_id":"AST-063","condition":"완료 조건 (측정가능)","line_end":579,"line_start":579,"modality":"must","object":"CSRF 재현 + SameSite·CSRF token 적용 후 403 검증","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-011 (feature-keycloak-bff-csrf-samesite-defense)"},{"assertion_id":"AST-064","condition":"완료 조건 (측정가능)","line_end":582,"line_start":582,"modality":"must","object":"forwarded-user spoofing 우회 재현 + network isolation 후 차단","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-014 (feature-keycloak-header-spoofing-defense)"},{"assertion_id":"AST-065","condition":"완료 조건 (측정가능)","line_end":583,"line_start":583,"modality":"must","object":"Google login·Keycloak user mapping 200 + application diff 0줄","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-015 (feature-keycloak-idp-brokering-google-client)"},{"assertion_id":"AST-066","condition":"완료 조건 (측정가능)","line_end":584,"line_start":584,"modality":"must","object":"unsafe auto-linking 재현 + Confirm Link Existing Account 로 차단","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-016 (feature-keycloak-first-broker-login-flow)"},{"assertion_id":"AST-067","condition":"완료 조건 (측정가능)","line_end":587,"line_start":587,"modality":"must","object":"4패턴 비교표의 모든 cell 이 구현 WI evidence 를 가리킴","predicate":"validates","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-019 (feature-keycloak-four-pattern-tradeoff-matrix)"},{"assertion_id":"AST-068","condition":"Status in-progress","line_end":588,"line_start":588,"modality":"must","object":"project governance hub 의 AP1~AP4 taxonomy + child progress index 유지","predicate":"owns","quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-020` | `feature-keycloak-patterns` | project governance hub가 AP1~AP4 taxonomy와 child progress index를 유지한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1` | - | `in-progress` |","scope":"§8.0 실행계획","source_surface":"SURF-814F7A1C82815A20329F","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-020 (feature-keycloak-patterns)"}],"candidate_manifest_sha256":"6c74f856c6cffc9f7574a7511c76af11d1beacf98a5b79be6590852b0a79052c","candidates":[{"assertion_a":"AST-002","assertion_b":"AST-003","candidate_id":"SEM-6600FD028F0536F1BBB8","grouping_key":{"condition":"시스템 아키텍처 다이어그램 작성 시","predicate":"","scope":"§3-1 아키텍처 다이어그램","subject":"시스템 아키텍처 다이어그램 작성"},"rule_ids":["C6"]},{"assertion_a":"AST-002","assertion_b":"AST-016","candidate_id":"SEM-D1AD3A2B8516203F4A17","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-003","assertion_b":"AST-016","candidate_id":"SEM-F92EC646EB253B4504FE","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-010","assertion_b":"AST-011","candidate_id":"SEM-F700AEF872C6C378FC7F","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-033","assertion_b":"AST-034","candidate_id":"SEM-B3D8AE86049A278AD732","grouping_key":{"condition":"현 phase 포함 범위","predicate":"requires","scope":"§5 포함 범위","subject":"프로젝트 포함 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-036","assertion_b":"AST-037","candidate_id":"SEM-D334450CDFE0A09FA751","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-036","assertion_b":"AST-038","candidate_id":"SEM-0F2741688668CC614518","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-036","assertion_b":"AST-039","candidate_id":"SEM-94B3E2F2A8A9CA63621C","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-037","assertion_b":"AST-038","candidate_id":"SEM-D4484B37545F9BB2FBE1","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-037","assertion_b":"AST-039","candidate_id":"SEM-4931ECCACA4FB2FAE9C5","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-038","assertion_b":"AST-039","candidate_id":"SEM-DC81578FC3411866911F","grouping_key":{"condition":"현 phase","predicate":"forbids","scope":"§5 제외 범위","subject":"프로젝트 제외 범위"},"rule_ids":["BASE"]},{"assertion_a":"AST-042","assertion_b":"AST-043","candidate_id":"SEM-5B6A15B5AB438AAB7EAD","grouping_key":{"condition":"현 phase","predicate":"","scope":"§5 인접 관심사 커버리지 note — Logout / session termination","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-042","assertion_b":"AST-059","candidate_id":"SEM-115B7FF0C551C680BB28","grouping_key":{"condition":"","predicate":"owns","scope":"","subject":"WI-KEYCLOAK-PATTERNS-OVERVIEW-007 (feature-keycloak-refresh-rotation-and-logout)"},"rule_ids":["C6","C7"]},{"assertion_a":"AST-042","assertion_b":"AST-060","candidate_id":"SEM-5B908411BE1B26B04E30","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-043","assertion_b":"AST-059","candidate_id":"SEM-372FC6A91DE4B5065FAA","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-043","assertion_b":"AST-060","candidate_id":"SEM-73AC46EA340E3418FBEA","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-044","assertion_b":"AST-045","candidate_id":"SEM-EFAC1683114D8A76829D","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-044","assertion_b":"AST-046","candidate_id":"SEM-CDD13510F0944F27EDD2","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-047","candidate_id":"SEM-373290D0CC8A29BC6B34","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-048","candidate_id":"SEM-B1A75DAF846CA8CFE6F7","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-049","candidate_id":"SEM-7F6304EEF83657423EB0","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-050","candidate_id":"SEM-A14756621054A5E06850","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-051","candidate_id":"SEM-47732CBFE25DEF1366B0","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-052","candidate_id":"SEM-9C0BEF549F3A3477D096","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-053","candidate_id":"SEM-8F7A005DD1F671A40996","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-044","assertion_b":"AST-054","candidate_id":"SEM-E7B7DD04EF645D5B6127","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-046","candidate_id":"SEM-49C5D5981D4DCA1BCB87","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-047","candidate_id":"SEM-3BB9DAD68B7E76FA28CF","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-048","candidate_id":"SEM-D34FD2B9B890960CC986","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-049","candidate_id":"SEM-27F7C811BC2B11C6FC87","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-050","candidate_id":"SEM-7BABE1B9659CB22333B1","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-051","candidate_id":"SEM-4E311540F3876464AD51","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-052","candidate_id":"SEM-294A1FF49036015C7627","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-053","candidate_id":"SEM-6F4859E16BFE0E592DFE","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-045","assertion_b":"AST-054","candidate_id":"SEM-D27CDC9689843D6B98B9","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-047","candidate_id":"SEM-0DCA49C6BA21CE3D548C","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-048","candidate_id":"SEM-5E55EB47DC95CAEE8CAF","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-049","candidate_id":"SEM-AEFA638BF1EA91CA9F4A","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-050","candidate_id":"SEM-464A04537C2309E9EFF0","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-051","candidate_id":"SEM-0AB20255931BC152272C","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-052","candidate_id":"SEM-A0DD8D7A975890CFA26B","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-053","candidate_id":"SEM-4A712AA1B00D16E28F48","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-046","assertion_b":"AST-054","candidate_id":"SEM-C7BA299E7ACE0D09B02F","grouping_key":{"condition":"","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-048","candidate_id":"SEM-3AE8A28C79055F6E6B07","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-049","candidate_id":"SEM-D38CEF2802BC4535202A","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-050","candidate_id":"SEM-57E7EE61DB971EE22B85","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-051","candidate_id":"SEM-CE264E78D639AA8C61F6","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-052","candidate_id":"SEM-668195507F86AA080C78","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-053","candidate_id":"SEM-55CF44DF2761E825D2BE","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-047","assertion_b":"AST-054","candidate_id":"SEM-6C2AD6B8F6C6A0D7BABF","grouping_key":{"condition":"","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-049","candidate_id":"SEM-D90DBAE92266EE8F8773","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-050","candidate_id":"SEM-EE43E65390258B2C9FAB","grouping_key":{"condition":"Status active","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-051","candidate_id":"SEM-AFEFC559C0C84C97D1BF","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-052","candidate_id":"SEM-F12970F8F18E7752F859","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-053","candidate_id":"SEM-99926B853F87BCB2D987","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-048","assertion_b":"AST-054","candidate_id":"SEM-BD744E3B9BD9AEB50CCE","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-049","assertion_b":"AST-050","candidate_id":"SEM-D8B040C148E00B01F942","grouping_key":{"condition":"Status active","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-049","assertion_b":"AST-051","candidate_id":"SEM-CE7AC7157951453497F5","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-049","assertion_b":"AST-052","candidate_id":"SEM-8641A4A7F256C07DA7B6","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-049","assertion_b":"AST-053","candidate_id":"SEM-FB8BA0A63CCA5F99FAB3","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-049","assertion_b":"AST-054","candidate_id":"SEM-B03048811E3FC48B722D","grouping_key":{"condition":"","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-050","assertion_b":"AST-051","candidate_id":"SEM-96D2660A29B2FAC7F62D","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-050","assertion_b":"AST-052","candidate_id":"SEM-C72764B291007A541DBF","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-050","assertion_b":"AST-053","candidate_id":"SEM-C33AF647F13F02C346BF","grouping_key":{"condition":"","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-050","assertion_b":"AST-054","candidate_id":"SEM-1BC69208BAA345BFD102","grouping_key":{"condition":"","predicate":"uses","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-051","assertion_b":"AST-052","candidate_id":"SEM-9D34F4FD531A9EDDA75A","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-051","assertion_b":"AST-053","candidate_id":"SEM-5A57BF9F7B89B3F8278E","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-051","assertion_b":"AST-054","candidate_id":"SEM-AB359C96472305420200","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-052","assertion_b":"AST-053","candidate_id":"SEM-AFFE2ADB7A738B261B6B","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-052","assertion_b":"AST-054","candidate_id":"SEM-8CB63BB397B41D88C86D","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-053","assertion_b":"AST-054","candidate_id":"SEM-43C1AAC054EE44DB110E","grouping_key":{"condition":"Status documented-only","predicate":"","scope":"§6.1 안정 결정 레지스트리","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-056","candidate_id":"SEM-7CA8B3746E85BF0EF07F","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-055","assertion_b":"AST-057","candidate_id":"SEM-725074413CD1C1B46EDA","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-058","candidate_id":"SEM-A06767A5BE6442243ACC","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-059","candidate_id":"SEM-B2C126D5040F86F9C2E4","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-060","candidate_id":"SEM-45CC87251A44AFA1870B","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-061","candidate_id":"SEM-1DE6C42746BD55E2D04F","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-062","candidate_id":"SEM-308EB22F6B5158353E25","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-064","candidate_id":"SEM-1C78AE3373E7C0CE0F88","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-065","candidate_id":"SEM-3F5E08114F44402F6DAF","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-055","assertion_b":"AST-066","candidate_id":"SEM-5B62B7317476A93B5C66","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-057","candidate_id":"SEM-78F2C3D56AFFCF031B00","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-058","candidate_id":"SEM-D5F502B5583D77833296","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-059","candidate_id":"SEM-7E109A23033679DCDC8E","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-060","candidate_id":"SEM-B377CB40FC3DE47BE38C","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-061","candidate_id":"SEM-FA7F907EB949EE99FD09","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-062","candidate_id":"SEM-A2F6B82A2F4EE8DDD20D","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-056","assertion_b":"AST-064","candidate_id":"SEM-3CB1805F9989DAD18595","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-065","candidate_id":"SEM-EA2F6DE3EEF13A69FAF7","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-056","assertion_b":"AST-066","candidate_id":"SEM-AC15659D8B8B6F8E652E","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-057","assertion_b":"AST-058","candidate_id":"SEM-39D42D30D5D274C99F98","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-059","candidate_id":"SEM-E01FD267AFB0D09E0738","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-060","candidate_id":"SEM-D05D80EC17634079BD73","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-061","candidate_id":"SEM-6D8C2A7A87A67AEE2F16","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-062","candidate_id":"SEM-578E32783A1678B3DBBC","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-057","assertion_b":"AST-063","candidate_id":"SEM-AB59B5A9BDAFC5F92A25","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-064","candidate_id":"SEM-AA1BD7C986770975F340","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-065","candidate_id":"SEM-302DA97B5C7602EE50CC","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-066","candidate_id":"SEM-2FB183D6C83A1470B5E2","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-057","assertion_b":"AST-067","candidate_id":"SEM-FF83BA41C6684BBBA76F","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-059","candidate_id":"SEM-78654167EF9F7C98D04D","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-060","candidate_id":"SEM-FDC36471814C8C12A824","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-061","candidate_id":"SEM-C4BD58078F748311B193","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-062","candidate_id":"SEM-03AEB30B3355925EBE99","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-058","assertion_b":"AST-063","candidate_id":"SEM-07789639D1F2362C0158","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-064","candidate_id":"SEM-F5FC0853419192407FDF","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-065","candidate_id":"SEM-52D49C58AE4A24CD66AC","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-066","candidate_id":"SEM-FDB692877FD427EF8C80","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-058","assertion_b":"AST-067","candidate_id":"SEM-02F7435CAC4A941935D0","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-060","candidate_id":"SEM-70BFED08088BDAB2CBCD","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-061","candidate_id":"SEM-11193138E582CDBEC453","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-062","candidate_id":"SEM-7DD6DBF820D3610A9395","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-059","assertion_b":"AST-063","candidate_id":"SEM-B00A2AC8177B81A0897D","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-064","candidate_id":"SEM-DD21684FE7A71D3B3C53","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-065","candidate_id":"SEM-A686886BB14B99297D2A","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-059","assertion_b":"AST-066","candidate_id":"SEM-CA58880C2C8A07ED043B","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-059","assertion_b":"AST-067","candidate_id":"SEM-79AB637B4CCF8675BC66","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-060","assertion_b":"AST-061","candidate_id":"SEM-6BEB4483F009D001B250","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-060","assertion_b":"AST-062","candidate_id":"SEM-C78A4B2C2AF1032CBFB9","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-060","assertion_b":"AST-063","candidate_id":"SEM-9539158D088A995B316E","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-060","assertion_b":"AST-064","candidate_id":"SEM-2AA14D43E3613806E5F1","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-060","assertion_b":"AST-065","candidate_id":"SEM-9E1CB005F3C8240E6192","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-060","assertion_b":"AST-066","candidate_id":"SEM-5232B25B6F9DEE41D7B9","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-060","assertion_b":"AST-067","candidate_id":"SEM-DB5DB2B801EB5161AC53","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-061","assertion_b":"AST-062","candidate_id":"SEM-B127608B69CA99DF6168","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-061","assertion_b":"AST-063","candidate_id":"SEM-B6560DA725D2F73B0919","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-061","assertion_b":"AST-064","candidate_id":"SEM-536E0823FEF47053D8B6","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-061","assertion_b":"AST-065","candidate_id":"SEM-AA58E70DCA9A33A31E99","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-061","assertion_b":"AST-066","candidate_id":"SEM-DC1484D0789BAA959A7D","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-061","assertion_b":"AST-067","candidate_id":"SEM-85456713A7E8934DFD2B","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-062","assertion_b":"AST-063","candidate_id":"SEM-02B9C013D556A7742630","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-062","assertion_b":"AST-064","candidate_id":"SEM-709F0ADDDE14D22AB176","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-062","assertion_b":"AST-065","candidate_id":"SEM-1D5ED665717E4934283D","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-062","assertion_b":"AST-066","candidate_id":"SEM-3C7F27165E8C4A233E4B","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-062","assertion_b":"AST-067","candidate_id":"SEM-BA950A14365A96DC1E84","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-063","assertion_b":"AST-064","candidate_id":"SEM-AE9F277B599EAF8174E3","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-063","assertion_b":"AST-066","candidate_id":"SEM-B06A53AE62FE692E33C5","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-063","assertion_b":"AST-067","candidate_id":"SEM-D86E2A4E6A492773BF89","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-063","assertion_b":"AST-068","candidate_id":"SEM-C8407A369946294AF6BE","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-064","assertion_b":"AST-065","candidate_id":"SEM-37C32CDC353FA36CE8BD","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6"]},{"assertion_a":"AST-064","assertion_b":"AST-066","candidate_id":"SEM-69982C9429B019457A5A","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-064","assertion_b":"AST-067","candidate_id":"SEM-BAD6A733E159E46D1762","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-065","assertion_b":"AST-066","candidate_id":"SEM-2D058C88F8C0B09CB440","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-065","assertion_b":"AST-067","candidate_id":"SEM-F31700236352DB675D2F","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-066","assertion_b":"AST-067","candidate_id":"SEM-146D3EF46F352E783F1E","grouping_key":{"condition":"완료 조건 (측정가능)","predicate":"validates","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]},{"assertion_a":"AST-067","assertion_b":"AST-068","candidate_id":"SEM-CA85D6DB9D14288D7C25","grouping_key":{"condition":"","predicate":"","scope":"§8.0 실행계획","subject":""},"rule_ids":["C6","C7"]}],"coverage":{"assertions":68,"candidate_pairs":146,"eligible_surfaces":9,"processed_surfaces":9},"document_sha256":"22a1555bc2e32ed99e8951a5b0e21c7b9a0028da969bcbbd6dcaa7a25d1fccab","explicit_blocking":[],"mode":"hub","ontology_sha256":"76d41a29233c830e1940ebb3244263e2b9bfb8dd6a01f2a1d1c51ce5a1b10468","output_schema":"semantic-audit-result/v1","schema_version":"semantic-verdict-request/v1","subject":"raw/project-notes/keycloak-patterns-overview.md"},"audit_request_sha256":"26c59e9751dd60e8b117924870b52961625314bcb7d9ce788756c98407f17c38","audit_result":{"auditor":{"contract_version":"semantic-coherence/v1","model_id":"claude-opus-4-8","run_id":"branch-spec-2026-07-23-hub2"},"mode":"hub","request_sha256":"26c59e9751dd60e8b117924870b52961625314bcb7d9ce788756c98407f17c38","schema_version":"semantic-audit-result/v1","subject":"raw/project-notes/keycloak-patterns-overview.md","verdicts":[{"candidate_id":"SEM-6600FD028F0536F1BBB8","evidence_a":{"line_end":129,"line_start":129,"quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용."},"evidence_b":{"line_end":129,"line_start":129,"quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용."},"proof_manifest":null,"rationale":"The Mermaid graph TD prohibition and the draw.io mandate are two facets of the same §3-1 tooling decision — the ban names the excluded tool while the mandate names the required one.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D1AD3A2B8516203F4A17","evidence_a":{"line_end":129,"line_start":129,"quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용."},"evidence_b":{"line_end":328,"line_start":328,"quote":"> 신 primary 축의 AP2·AP3 은 기존 6 `.drawio`(P1A~P3B = AP1 배포 변형 + AP4)에 대응 아키텍처 다이어그램이 없다. **needs-diagram** — 사용자가 draw.io 로 작성 후 아래 백틱을 풀어 활성 임베드로 전환한다. (미작성 파일을 활성 임베드로 두면 9a 린터가 `BROKEN_LINK` 로 잡으므로 placeholder 는 백틱 코드로 비활성.)"},"proof_manifest":null,"rationale":"The AP2·AP3 needs-diagram backtick-placeholder lifecycle adds a compatible detail alongside the Mermaid graph TD prohibition for architecture diagrams; neither claim overrides the other.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F92EC646EB253B4504FE","evidence_a":{"line_end":129,"line_start":129,"quote":"> 작성 도구: **draw.io** (`.drawio` 파일, 저장 경로 `raw/diagrams/keycloak-patterns/`). Mermaid `graph TD` 는 시스템 아키텍처용으로 사용 금지 — Mermaid 는 시퀀스/ER 다이어그램 전용."},"evidence_b":{"line_end":328,"line_start":328,"quote":"> 신 primary 축의 AP2·AP3 은 기존 6 `.drawio`(P1A~P3B = AP1 배포 변형 + AP4)에 대응 아키텍처 다이어그램이 없다. **needs-diagram** — 사용자가 draw.io 로 작성 후 아래 백틱을 풀어 활성 임베드로 전환한다. (미작성 파일을 활성 임베드로 두면 9a 린터가 `BROKEN_LINK` 로 잡으므로 placeholder 는 백틱 코드로 비활성.)"},"proof_manifest":null,"rationale":"The AP2·AP3 placeholder policy presumes the same draw.io authoring mandate and adds an activation-lifecycle detail for not-yet-written diagrams; no conflict.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F700AEF872C6C378FC7F","evidence_a":{"line_end":222,"line_start":222,"quote":"- Backend 가 JWT validator 코드 보유 (`iss`, `aud`, `exp`, signature) — Spring Security 6.x Resource Server"},"evidence_b":{"line_end":278,"line_start":277,"quote":"- Browser 는 EC2 public hostname 으로 Keycloak 호출 → JWT 의 `iss` claim = public host\n- Backend 는 `localhost:8180` 로 JWKS 조회 → `iss` 비교 시 mismatch → 401"},"proof_manifest":null,"rationale":"AST-011 supplies a deployment-specific failure mode (iss mismatch when KC_HOSTNAME is unset) of the same backend JWT validation duty that AST-010 states; compatible detail, no takeover.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B3D8AE86049A278AD732","evidence_a":{"line_end":487,"line_start":487,"quote":"- **4 인증-아키텍처 패턴(AP1~AP4) 실 구현** — 모두 single-EC2 로컬 스택 위에서 E2E(`locally-verified`) + signature 함정 재현→해결 (§1 성공기준, §8.0 branch 분해)."},"evidence_b":{"line_end":488,"line_start":488,"quote":"- **Google IdP brokering** 을 cross-cutting 변형으로 1회 실 구현(어느 패턴에 얹어도 SPA/Backend 코드 0줄 변경 검증 포함)."},"proof_manifest":null,"rationale":"Two distinct in-scope items in the same §5 inclusion list (AP1~AP4 pattern implementation vs the Google brokering cross-cutting variant); no overlap or tension.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D334450CDFE0A09FA751","evidence_a":{"line_end":495,"line_start":495,"quote":"- **배포 토폴로지 별도 구현**: 인증 아키텍처는 single-EC2 로 실 구현하고, cluster-internal / edge 는 hostname·issuer·network 차이만 문서화(별도 k8s/Traefik 환경 구축 안 함 — §2.2 cross-cutting)."},"evidence_b":{"line_end":496,"line_start":496,"quote":"- 다른 OIDC Provider(GitHub / Auth0 / Cognito) federation. Google만."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (deployment-topology environment construction vs non-Google OIDC provider federation); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-0F2741688668CC614518","evidence_a":{"line_end":495,"line_start":495,"quote":"- **배포 토폴로지 별도 구현**: 인증 아키텍처는 single-EC2 로 실 구현하고, cluster-internal / edge 는 hostname·issuer·network 차이만 문서화(별도 k8s/Traefik 환경 구축 안 함 — §2.2 cross-cutting)."},"evidence_b":{"line_end":497,"line_start":497,"quote":"- React/Vue 등 SPA 프레임워크 (vanilla JS 유지)."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (deployment-topology environment construction vs SPA framework adoption); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-94B3E2F2A8A9CA63621C","evidence_a":{"line_end":495,"line_start":495,"quote":"- **배포 토폴로지 별도 구현**: 인증 아키텍처는 single-EC2 로 실 구현하고, cluster-internal / edge 는 hostname·issuer·network 차이만 문서화(별도 k8s/Traefik 환경 구축 안 함 — §2.2 cross-cutting)."},"evidence_b":{"line_end":499,"line_start":499,"quote":"- mTLS, FAPI(Financial-grade API), DPoP 등 고급 보안 옵션."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (deployment-topology environment construction vs advanced security options (mTLS/FAPI/DPoP)); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D4484B37545F9BB2FBE1","evidence_a":{"line_end":496,"line_start":496,"quote":"- 다른 OIDC Provider(GitHub / Auth0 / Cognito) federation. Google만."},"evidence_b":{"line_end":497,"line_start":497,"quote":"- React/Vue 등 SPA 프레임워크 (vanilla JS 유지)."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (non-Google OIDC provider federation vs SPA framework adoption); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-4931ECCACA4FB2FAE9C5","evidence_a":{"line_end":496,"line_start":496,"quote":"- 다른 OIDC Provider(GitHub / Auth0 / Cognito) federation. Google만."},"evidence_b":{"line_end":499,"line_start":499,"quote":"- mTLS, FAPI(Financial-grade API), DPoP 등 고급 보안 옵션."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (non-Google OIDC provider federation vs advanced security options (mTLS/FAPI/DPoP)); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-DC81578FC3411866911F","evidence_a":{"line_end":497,"line_start":497,"quote":"- React/Vue 등 SPA 프레임워크 (vanilla JS 유지)."},"evidence_b":{"line_end":499,"line_start":499,"quote":"- mTLS, FAPI(Financial-grade API), DPoP 등 고급 보안 옵션."},"proof_manifest":null,"rationale":"Distinct exclusion items in the same §5 out-of-scope list (SPA framework adoption vs advanced security options (mTLS/FAPI/DPoP)); the two prohibitions target different objects and coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-5B6A15B5AB438AAB7EAD","evidence_a":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"evidence_b":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"proof_manifest":null,"rationale":"The differing phase treatment is explained by the named sub-scope split on line 515: rotation + post-logout session·token invalidation is current-phase (WI-007) while only the integrated front/back-channel logout deep-dive sub-scope is deferred.","verdict":"CONTEXTUAL_VARIANT"},{"candidate_id":"SEM-115B7FF0C551C680BB28","evidence_a":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The clarified §5 line 515 note and the §8.0 registry row both assign refresh rotation + logout 후 session·token 무효화 to WI-KEYCLOAK-PATTERNS-OVERVIEW-007 as current-phase work, and the note explicitly cites the §8.0 registry as its source, so the prior authority ambiguity is resolved into agreement.","verdict":"CONSISTENT"},{"candidate_id":"SEM-5B908411BE1B26B04E30","evidence_a":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The WI-004 dependency ordering for WI-007 is a compatible plan detail alongside the §5 note's current-phase coverage claim for the same work item.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-372FC6A91DE4B5065FAA","evidence_a":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The deferred claim is scoped solely to the integrated front/back-channel logout deep-dive, while WI-007's current-phase registry scope is refresh rotation + post-logout invalidation — the differing sub-scope explains the phase difference.","verdict":"CONTEXTUAL_VARIANT"},{"candidate_id":"SEM-73AC46EA340E3418FBEA","evidence_a":{"line_end":515,"line_start":515,"quote":"- **Logout / session termination (front/back-channel)**: AP3 BFF session 종료 · AP1 토큰 만료로 부분 커버. refresh rotation + logout 후 session·token 무효화는 `WI-KEYCLOAK-PATTERNS-OVERVIEW-007`(`feature-keycloak-refresh-rotation-and-logout`, §8.0 registry)이 **현 phase** 로 커버한다. **통합 front/back-channel logout 흐름 심화**만 deferred (2026-07-23 경계 명확화 — §8.0 WI-007 과의 이중 서술 해소)."},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's WI-004 dependency ordering does not intersect the deferred integrated front/back-channel logout deep-dive scope; the two details coexist.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-EFAC1683114D8A76829D","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"proof_manifest":null,"rationale":"Decision content and the Owner-column ownership are two facets of the same §6.1 registry row; the hub owning the auth-taxonomy decision does not conflict with the decision statement itself.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-CDD13510F0944F27EDD2","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs AP1); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-373290D0CC8A29BC6B34","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs AP3); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B1A75DAF846CA8CFE6F7","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs AP2 backend); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7F6304EEF83657423EB0","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs AP4); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-A14756621054A5E06850","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-47732CBFE25DEF1366B0","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-9C0BEF549F3A3477D096","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-8F7A005DD1F671A40996","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-E7B7DD04EF645D5B6127","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (canonical 분류축 vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-49C5D5981D4DCA1BCB87","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs AP1); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3BB9DAD68B7E76FA28CF","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs AP3); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D34FD2B9B890960CC986","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs AP2 backend); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-27F7C811BC2B11C6FC87","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs AP4); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7BABE1B9659CB22333B1","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-4E311540F3876464AD51","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-294A1FF49036015C7627","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-6F4859E16BFE0E592DFE","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D27CDC9689843D6B98B9","evidence_a":{"line_end":553,"line_start":553,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001` | 1 | `auth-taxonomy` | canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §2; §기술 결정 `분류 primary 축`; F1 |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (the hub Owner-column claim for the auth-taxonomy decision vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-0DCA49C6BA21CE3D548C","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs AP3); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-5E55EB47DC95CAEE8CAF","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs AP2 backend); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AEFA638BF1EA91CA9F4A","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs AP4); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-464A04537C2309E9EFF0","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-0AB20255931BC152272C","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-A0DD8D7A975890CFA26B","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-4A712AA1B00D16E28F48","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C7BA299E7ACE0D09B02F","evidence_a":{"line_end":554,"line_start":554,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001` | 1 | `spa-client` | AP1은 public client와 Authorization Code + PKCE를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP1 SPA client 유형`; [[raw/official-docs/oauth2-pkce-rfc-7636]] |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP1 vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3AE8A28C79055F6E6B07","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"proof_manifest":null,"rationale":"Browser-side token placement differs by pattern scope: the AP3 (BFF) decision keeps tokens in the backend session with cookie only, whereas the AP2 (token-mediating) decision hands the access token to the browser.","verdict":"CONTEXTUAL_VARIANT"},{"candidate_id":"SEM-D38CEF2802BC4535202A","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs AP4); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-57E7EE61DB971EE22B85","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-CE264E78D639AA8C61F6","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-668195507F86AA080C78","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-55CF44DF2761E825D2BE","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-6C2AD6B8F6C6A0D7BABF","evidence_a":{"line_end":555,"line_start":555,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001` | 1 | `bff-session` | AP3는 token을 backend session에 두고 browser에는 cookie만 둔다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP3 BFF 토큰 위치`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP3 vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D90DBAE92266EE8F8773","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs AP4); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-EE43E65390258B2C9FAB","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AFEFC559C0C84C97D1BF","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F12970F8F18E7752F859","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-99926B853F87BCB2D987","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-BD744E3B9BD9AEB50CCE","evidence_a":{"line_end":556,"line_start":556,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001` | 1 | `token-mediating` | AP2 backend가 token을 획득하고 access token만 browser에 전달한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP2 Token-Mediating Backend`; [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP2 backend vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D8B040C148E00B01F942","evidence_a":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"evidence_b":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP4 vs Google federation); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-CE7AC7157951453497F5","evidence_a":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP4 vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-8641A4A7F256C07DA7B6","evidence_a":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP4 vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FB8BA0A63CCA5F99FAB3","evidence_a":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP4 vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B03048811E3FC48B722D","evidence_a":{"line_end":557,"line_start":557,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001` | 1 | `edge-forwardauth` | AP4는 oauth2-proxy ForwardAuth를 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `AP4 Edge forward-auth`; [[raw/official-docs/oauth2-proxy-keycloak-oidc-provider-official]] |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (AP4 vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-96D2660A29B2FAC7F62D","evidence_a":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"evidence_b":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Google federation vs done-bar); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C72764B291007A541DBF","evidence_a":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Google federation vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C33AF647F13F02C346BF","evidence_a":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Google federation vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-1BC69208BAA345BFD102","evidence_a":{"line_end":558,"line_start":558,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001` | 1 | `idp-brokering` | Google federation은 Keycloak IdP brokering과 hardened First Broker Login을 사용한다 | `active` | [[raw/project-notes/keycloak-patterns-overview]] | §기술 결정 `Google federation`; [[raw/official-docs/keycloak-first-broker-login-flow]] |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Google federation vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-9D34F4FD531A9EDDA75A","evidence_a":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"evidence_b":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (done-bar vs Keycloak realm/client 구성); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-5A57BF9F7B89B3F8278E","evidence_a":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (done-bar vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AB359C96472305420200","evidence_a":{"line_end":559,"line_start":559,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001` | 1 | `acceptance` | done-bar는 E2E success와 signature security failure 재현·해결 evidence다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F2; §1 성공 기준 |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (done-bar vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AFFE2ADB7A738B261B6B","evidence_a":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"evidence_b":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Keycloak realm/client 구성 vs confidential client secret); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-8CB63BB397B41D88C86D","evidence_a":{"line_end":560,"line_start":560,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001` | 1 | `realm-client` | 단일 realm keycloak-patterns에서 인증 패턴별 client를 분리한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F3; §4 stack |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (Keycloak realm/client 구성 vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-43C1AAC054EE44DB110E","evidence_a":{"line_end":561,"line_start":561,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001` | 1 | `secret-boundary` | confidential client secret은 env var로 주입하고 commit·realm export 평문을 금지한다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F4 |"},"evidence_b":{"line_end":562,"line_start":562,"quote":"| `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001` | 1 | `deployment` | AP1~AP4 E2E 구현 topology는 single-EC2 docker-compose다 | `documented-only` | [[raw/project-notes/keycloak-patterns-overview]] | F5; §2.2; §5 |"},"proof_manifest":null,"rationale":"Sibling §6.1 decision-registry rows governing distinct concerns (confidential client secret vs AP1~AP4 E2E 구현 topology); no shared contract property takes conflicting values.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7CA8B3746E85BF0EF07F","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-002); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-725074413CD1C1B46EDA","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-004); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-A06767A5BE6442243ACC","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-005); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B2C126D5040F86F9C2E4","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-001 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-45CC87251A44AFA1870B","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-001 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-1DE6C42746BD55E2D04F","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-009); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-308EB22F6B5158353E25","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-010); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-1C78AE3373E7C0CE0F88","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3F5E08114F44402F6DAF","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-5B62B7317476A93B5C66","evidence_a":{"line_end":569,"line_start":569,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `feature-keycloak-docker-compose-stack` | Keycloak·PostgreSQL·nginx·Spring 4 containers가 healthy이고 admin console에 접속된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-DEPLOYMENT-001@1` | - | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-001 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-78F2C3D56AFFCF031B00","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-004); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D5F502B5583D77833296","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-005); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7E109A23033679DCDC8E","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-002 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B377CB40FC3DE47BE38C","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-002 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FA7F907EB949EE99FD09","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-009); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-A2F6B82A2F4EE8DDD20D","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-010); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3CB1805F9989DAD18595","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-EA2F6DE3EEF13A69FAF7","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AC15659D8B8B6F8E652E","evidence_a":{"line_end":570,"line_start":570,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `feature-keycloak-realm-client-export` | realm import와 client 4개 등록 후 unauthenticated protected endpoint가 401이고 export가 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-REALM-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-001` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-002 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-39D42D30D5D274C99F98","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-005); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-E01FD267AFB0D09E0738","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-004 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D05D80EC17634079BD73","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-004 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-6D8C2A7A87A67AEE2F16","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-009); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-578E32783A1678B3DBBC","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-010); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AB59B5A9BDAFC5F92A25","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-011); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AA1BD7C986770975F340","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-302DA97B5C7602EE50CC","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-2FB183D6C83A1470B5E2","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FF83BA41C6684BBBA76F","evidence_a":{"line_end":572,"line_start":572,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `feature-keycloak-spring-rs-audience-validator` | foreign audience token 수용 실패를 재현하고 validator 적용 후 401을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-004 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-78654167EF9F7C98D04D","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-005 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FDC36471814C8C12A824","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-005 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C4BD58078F748311B193","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-009); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-03AEB30B3355925EBE99","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-010); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-07789639D1F2362C0158","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-011); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F5FC0853419192407FDF","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-52D49C58AE4A24CD66AC","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FDB692877FD427EF8C80","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-02F7435CAC4A941935D0","evidence_a":{"line_end":573,"line_start":573,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-005` | `feature-keycloak-iss-claim-hostname-mismatch` | hostname 미설정 iss mismatch 401과 설정 후 복구 log가 존재한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-005 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-70BFED08088BDAB2CBCD","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"proof_manifest":null,"rationale":"Both come from the same WI-007 registry row — the ownership of the rotation+logout-invalidation verification scope plus its WI-004 dependency ordering; the ordering detail complements the ownership claim.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-11193138E582CDBEC453","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-009 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7DD6DBF820D3610A9395","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-010 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B00A2AC8177B81A0897D","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-011 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-DD21684FE7A71D3B3C53","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-014 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-A686886BB14B99297D2A","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-015 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-CA58880C2C8A07ED043B","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-016 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-79AB637B4CCF8675BC66","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"WI-007's ownership of rotation+logout-invalidation verification and the WI-KEYCLOAK-PATTERNS-OVERVIEW-019 entry are distinct sibling plan items; no overlap of responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-6BEB4483F009D001B250","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-009 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C78A4B2C2AF1032CBFB9","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-010 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-9539158D088A995B316E","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-011 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-2AA14D43E3613806E5F1","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-014 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-9E1CB005F3C8240E6192","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-015 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-5232B25B6F9DEE41D7B9","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-016 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-DB5DB2B801EB5161AC53","evidence_a":{"line_end":575,"line_start":575,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-007` | `feature-keycloak-refresh-rotation-and-logout` | refresh rotation과 logout 후 session·token 무효화가 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-004` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"The WI-007 dependency-ordering detail and the WI-KEYCLOAK-PATTERNS-OVERVIEW-019 entry are compatible sibling details in the §8.0 plan; no shared property conflicts.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B127608B69CA99DF6168","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"proof_manifest":null,"rationale":"Browser token cardinality differs by pattern scope: WI-009 verifies the AP2 contract (access token in browser, refresh token withheld) while WI-010 verifies the AP3 contract (zero browser tokens, SESSION cookie only).","verdict":"CONTEXTUAL_VARIANT"},{"candidate_id":"SEM-B6560DA725D2F73B0919","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-009 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-011); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-536E0823FEF47053D8B6","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-009 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AA58E70DCA9A33A31E99","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-009 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-DC1484D0789BAA959A7D","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-009 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-85456713A7E8934DFD2B","evidence_a":{"line_end":577,"line_start":577,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-009` | `feature-keycloak-token-mediating-access-handoff` | browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-008` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-009 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-02B9C013D556A7742630","evidence_a":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"evidence_b":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-010 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-011); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-709F0ADDDE14D22AB176","evidence_a":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-010 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-1D5ED665717E4934283D","evidence_a":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-010 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3C7F27165E8C4A233E4B","evidence_a":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-010 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-BA950A14365A96DC1E84","evidence_a":{"line_end":578,"line_start":578,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `feature-keycloak-bff-oauth2login-session` | browser token 0개와 SESSION cookie만으로 BFF proxy API 200이 재현된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-SECRET-BOUNDARY-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-002` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-010 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AE9F277B599EAF8174E3","evidence_a":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"evidence_b":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-011 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-014); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-B06A53AE62FE692E33C5","evidence_a":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-011 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D86E2A4E6A492773BF89","evidence_a":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-011 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-C8407A369946294AF6BE","evidence_a":{"line_end":579,"line_start":579,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-011` | `feature-keycloak-bff-csrf-samesite-defense` | CSRF를 재현하고 SameSite와 CSRF token 적용 후 403을 검증한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-BFF-SESSION-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-010` | `in-progress` |"},"evidence_b":{"line_end":588,"line_start":588,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-020` | `feature-keycloak-patterns` | project governance hub가 AP1~AP4 taxonomy와 child progress index를 유지한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1` | - | `in-progress` |"},"proof_manifest":null,"rationale":"WI-020's governance-hub maintenance responsibility and the WI-KEYCLOAK-PATTERNS-OVERVIEW-011 entry are distinct sibling plan items; no ownership overlap.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-37C32CDC353FA36CE8BD","evidence_a":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"evidence_b":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-014 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-015); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-69982C9429B019457A5A","evidence_a":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-014 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-BAD6A733E159E46D1762","evidence_a":{"line_end":582,"line_start":582,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-014` | `feature-keycloak-header-spoofing-defense` | forwarded-user spoofing 우회를 재현하고 network isolation 후 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-EDGE-FORWARDAUTH-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-014 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-2D058C88F8C0B09CB440","evidence_a":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-015 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-016); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F31700236352DB675D2F","evidence_a":{"line_end":583,"line_start":583,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `feature-keycloak-idp-brokering-google-client` | Google login·Keycloak user mapping 200과 application diff 0줄이 검증된다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-015 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-146D3EF46F352E783F1E","evidence_a":{"line_end":584,"line_start":584,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-016` | `feature-keycloak-first-broker-login-flow` | unsafe auto-linking을 재현하고 Confirm Link Existing Account로 차단한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-IDP-BROKERING-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-015` | `planned` |"},"evidence_b":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"proof_manifest":null,"rationale":"Sibling §8.0 work items with distinct measurable completion conditions (WI-KEYCLOAK-PATTERNS-OVERVIEW-016 vs WI-KEYCLOAK-PATTERNS-OVERVIEW-019); compatible plan entries with no conflicting shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-CA85D6DB9D14288D7C25","evidence_a":{"line_end":587,"line_start":587,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-019` | `feature-keycloak-four-pattern-tradeoff-matrix` | 4패턴 비교표의 모든 cell이 구현 WI evidence를 가리킨다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1`, `DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1` | `WI-KEYCLOAK-PATTERNS-OVERVIEW-003`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-008`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-010`, `WI-KEYCLOAK-PATTERNS-OVERVIEW-012` | `in-progress` |"},"evidence_b":{"line_end":588,"line_start":588,"quote":"| `WI-KEYCLOAK-PATTERNS-OVERVIEW-020` | `feature-keycloak-patterns` | project governance hub가 AP1~AP4 taxonomy와 child progress index를 유지한다 | `DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1` | - | `in-progress` |"},"proof_manifest":null,"rationale":"WI-020's governance-hub maintenance responsibility and the WI-KEYCLOAK-PATTERNS-OVERVIEW-019 entry are distinct sibling plan items; no ownership overlap.","verdict":"COMPLEMENTARY"}]},"auditor":{"contract_version":"semantic-coherence/v1","model_id":"claude-opus-4-8","run_id":"branch-spec-2026-07-23-hub2"},"auditor_contract_sha256":"1cbc67c27e5183a272687f635e3682a26d56785a1cf144da562eb7edd8f6cbce","coverage":{"candidate_pairs":146,"dropped_pairs":0,"eligible_surfaces":9,"processed_pairs":146,"processed_surfaces":9},"document_id":"0d0f80e31b5f216f8511a295ffae4b8745ab8821dfc6e49c6a234f006b93c33f","document_sha256":"22a1555bc2e32ed99e8951a5b0e21c7b9a0028da969bcbbd6dcaa7a25d1fccab","findings":{"blocking":0,"readiness_blocking":0,"verified":0},"mode":"hub","ontology_sha256":"5d601b96f0ca4d75eea89e9086c38e3acf2c4f0c7833846ef58c6a5719603126","policy_sha256":"0465598e9c1c4f2c3400ba51bf4719aa4890d60d56dc83304fb2224e660562b7","proof_manifest_sha256":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","schema_version":"semantic-certificate/v1","semantic_audit_sha256":"da484b5f13d42756189081bfcd1e324cb5e90355ecff336f82d187d1a587dbfb","subject":"raw/project-notes/keycloak-patterns-overview.md","typed_contract_graph_sha256":"481fc3335a494c454ab13ad1d6a6ddccdec99aa8e083f6720ff8886bfa19cc89","verdict":"PASS"}
|