22 KiB
Keycloak Branch-note 설계 일관성 리뷰
일자 / Date: 2026-07-18
범위 / Scope: raw/branch-notes에서 파일명 또는 본문에 keycloak이 있는 38개 파일, 10,649줄
Verdict: PARTIAL — derived from controller-verification.md
요청 언어 / User language: ko
이 verdict는 controller-verification.md의 gate 결과에서 자동 산출되었다.
0. Source roots
해당 없음 / N/A. 인용한 source는 모두 현재 workspace 안에 있다.
1. 한눈 요약 / Executive Summary
38개 branch-note를 38/38 READ_FULL로 판독했으며 원문은 수정하지 않았다. 1차 finding 60개를 인용 158줄로 확인한 뒤 적대 리뷰에서 KEEP 21, DOWNGRADE 27, REJECT 12로 정리했고, 최종 High는 10개다. 가장 큰 실행 위험은 audience 값, container issuer 도달성, SPA endpoint origin, Caddy path strip, account-link hard-reject 범위, SPA Direct와 TMB 경계다. 결정론 checker는 Keycloak 범위에서 BARE_DECISION_REF 8건을 찾았고 dangling 또는 exact dual-ownership finding은 내지 않았다. 문서 전문 판독은 끝났지만 Claims Extracted가 38개 중 2개에만 있고 298 logical reference edge 중 의미 대조는 고위험 후보 20건으로 제한했으므로 원천 Claim 및 전체 edge 수준에서는 추가 검증이 남는다.
2. Evidence Matrix
| Path | Status | Evidence | Extracted facts |
|---|---|---|---|
| raw/branch-notes/experiment-nplus1-highlight-feed.md | READ_FULL | L1-L233 | Keycloak은 예정 sibling 주제로만 등장한다. |
| raw/branch-notes/feature-authentication-authorization-contract.md | READ_FULL | L1-L341 | raw role과 permission registry 경계. |
| raw/branch-notes/feature-boundary-validation-mapping-contract.md | READ_FULL | L1-L407 | Keycloak은 sample seed 설명에 등장한다. |
| raw/branch-notes/feature-keycloak-account-linking-spa-ux.md | READ_FULL | L1-L228 | account-link UX, First Broker Login, unlink, CIAL. |
| raw/branch-notes/feature-keycloak-account-linking-sub-vs-email.md | READ_FULL | L1-L279 | sub key, collision, re-auth, unlink, Sync Mode. |
| raw/branch-notes/feature-keycloak-bff-vs-spa-direct.md | READ_FULL | L1-L274 | SPA Direct와 BFF 선택. |
| raw/branch-notes/feature-keycloak-docker-compose-stack.md | READ_FULL | L1-L287 | Compose topology, import, issuer/network. |
| raw/branch-notes/feature-keycloak-edge-forwardauth-google-federation.md | READ_FULL | L1-L325 | P1B brokering과 child ownership. |
| raw/branch-notes/feature-keycloak-edge-forwardauth-no-google.md | READ_FULL | L1-L316 | P1A ForwardAuth와 cookie session. |
| raw/branch-notes/feature-keycloak-federation-spa-zero-change.md | READ_FULL | L1-L193 | P2A→P2B login-path zero-change. |
| raw/branch-notes/feature-keycloak-first-broker-login-flow.md | READ_FULL | L1-L261 | Confirm Link와 silent-link policy. |
| raw/branch-notes/feature-keycloak-google-claim-attribute-mapping.md | READ_FULL | L1-L238 | attribute mapping과 IMPORT. |
| raw/branch-notes/feature-keycloak-google-redirect-uri-policy.md | READ_FULL | L1-L261 | redirect URI와 JavaScript origins. |
| raw/branch-notes/feature-keycloak-header-spoofing-defense.md | READ_FULL | L1-L255 | trusted header 방어 경계. |
| raw/branch-notes/feature-keycloak-https-termination-caddy-nginx.md | READ_FULL | L1-L284 | TLS termination과 HSTS. |
| raw/branch-notes/feature-keycloak-idp-brokering-google-client.md | READ_FULL | L1-L251 | Google IdP client와 trustEmail. |
| raw/branch-notes/feature-keycloak-idp-mappers-claim-to-role.md | READ_FULL | L1-L148 | role mapping, FORCE, email verification. |
| raw/branch-notes/feature-keycloak-internal-spa-direct-google-federation.md | READ_FULL | L1-L512 | P2B composition hub와 foreign detail. |
| raw/branch-notes/feature-keycloak-internal-spa-direct-no-google.md | READ_FULL | L1-L416 | P2A SPA Direct와 token storage. |
| raw/branch-notes/feature-keycloak-iss-claim-hostname-mismatch.md | READ_FULL | L1-L287 | issuer/JWKS 대안과 owner conflict. |
| raw/branch-notes/feature-keycloak-nginx-auth-request-integration.md | READ_FULL | L1-L306 | auth_request body와 failure routing. |
| raw/branch-notes/feature-keycloak-oauth2-proxy-oidc-flow.md | READ_FULL | L1-L275 | OIDC flow와 discovery dependency. |
| raw/branch-notes/feature-keycloak-patterns.md | READ_FULL | L1-L205 | pattern taxonomy와 naming. |
| raw/branch-notes/feature-keycloak-pkce-flow-stages.md | READ_FULL | L1-L167 | PKCE S256와 Admin terminology. |
| raw/branch-notes/feature-keycloak-public-domain-tunneling.md | READ_FULL | L1-L220 | quick/named tunnel과 hostname. |
| raw/branch-notes/feature-keycloak-realm-client-export.md | READ_FULL | L1-L238 | realm import와 credential export. |
| raw/branch-notes/feature-keycloak-refresh-rotation-and-logout.md | READ_FULL | L1-L254 | rotation demonstration과 logout. |
| raw/branch-notes/feature-keycloak-refresh-token-rotation.md | READ_FULL | L1-L284 | rotation contract와 receiver scope. |
| raw/branch-notes/feature-keycloak-reverse-proxy-headers.md | READ_FULL | L1-L297 | proxy headers와 Caddy path. |
| raw/branch-notes/feature-keycloak-single-ec2-google-federation.md | READ_FULL | L1-L370 | integration parent와 tunnel/proxy delegation. |
| raw/branch-notes/feature-keycloak-single-ec2-no-google.md | READ_FULL | L1-L342 | base topology와 component ownership. |
| raw/branch-notes/feature-keycloak-spa-token-storage-tradeoff.md | READ_FULL | L1-L256 | token storage, TMB, CSRF. |
| raw/branch-notes/feature-keycloak-spring-rs-audience-validator.md | READ_FULL | L1-L268 | audience owner와 validator 선택. |
| raw/branch-notes/feature-keycloak-spring-rs-role-mapping.md | READ_FULL | L1-L231 | RBAC와 audience delegation. |
| raw/branch-notes/feature-keycloak-three-leg-trust-chain.md | READ_FULL | L1-L229 | federation/API validation hop. |
| raw/branch-notes/feature-keycloak-traefik-forwardauth-alternative.md | READ_FULL | L1-L237 | Traefik ForwardAuth와 pattern attribution. |
| raw/branch-notes/feature-keycloak-vanilla-js-spa-pkce.md | READ_FULL | L1-L257 | oidc-client-ts/manual PKCE와 endpoint URL. |
| raw/branch-notes/feature-security-operational-baseline.md | READ_FULL | L1-L417 | auth code, CORS, JWT, public-path contract. |
3. Controller Recomputed Coverage
모든 값은 controller가 disk의 source, lane, matrix, proof, adversarial artifact에서 다시 계산했다.
| Metric | Command | Observed |
|---|---|---|
| N scope files | controller_verify.py: content match enumeration | 38 |
| Source lines | controller_verify.py: splitlines sum | 10,649 |
| M matrix rows | controller_verify.py: evidence row parse | 38 |
| R READ_FULL | controller_verify.py: status count | 38 |
| B BLOCKED | controller_verify.py: status count | 0 |
| Missing / extra / duplicate / nonexistent paths | controller_verify.py: set reconciliation | 0 / 0 / 0 / 0 |
| P per-file index sections | controller_verify.py: section parse | 38 |
| T unique lane finding IDs | controller_verify.py: heading parse | 60 |
| Finding schema failures | controller_verify.py: source, severity, falsification, action check | 0 |
| Quote proof rows | controller_verify.py: sed-proofs parse | 60 |
| Quote commands / failed | verify_quotes.py | 107 / 0 |
| Verified quote output lines | verify_quotes.py | 158 |
| A adversarial rows / generic rows | controller_verify.py | 60 / 0 |
| Priority unresolved IDs | controller_verify.py | 0 |
| Broken internal links | controller_verify.py | 0 |
| Forbidden term hits in controller-generated prose | controller_verify.py | 0 |
| Decision Evidence Map files | controller_verify.py | 38 |
| Claims Extracted files / missing | controller_verify.py | 2 / 36 |
| UNSUPPORTED_DECISION files / occurrences | controller_verify.py | 32 / 125 |
| BROKEN_CLAIM_REFERENCE literal labels | controller_verify.py | 0 |
$ python3 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/verify_quotes.py
inventory_rows=38
inventory_unique=38
read_full=38
finding_ids=60
expected_finding_ids=60
commands_passed=107
commands_failed=0
verified_output_lines=158
findings_without_commands=0
3-1. Verdict Calculation
Coverage 식은 N=38, M=38, R=38, P=38, T=60, G=60으로 M==N, P==R, G==T를 만족한다. 9-gate controller에서는 claim source 역추적 미완료를 finding integrity에 포함했고, Claims Extracted가 2/38이므로 finding_gate만 FAIL이다. scope_gate와 matrix_gate는 PASS이고 source first reads도 완료되어 계산 결과는 PARTIAL이다.
Failed Gates from controller-verification.md
- finding_gate: 60개 finding의 local source quote와 schema는 충족했지만 36개 파일에 Claims Extracted가 없어 raw Claim 의미까지의 traceability가 완료되지 않았다.
4. 파일별 발견 사항 / Per-File Findings
파일별 index: per-file-findings.md
인용 proof: sed-proofs.md
lane 상세: lane 01, lane 02, lane 03, lane 04
아래는 60개 finding registry다. 각 finding의 원문 quote, 가정, 반증 조건, action은 연결된 lane이 소유하며 quote status는 모두 VERIFIED다.
L1-F01 — ROLE_*와 raw-role registry 입력
- Adversarial: KEEP → Medium · Evidence: lane 01 · Quote: VERIFIED
L1-F02 — unlink guard evidence status
- Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED
L1-F03 — delegated email_verified decision 복제
- Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED
L1-F04 — password re-auth와 email verification profile
- Adversarial: DOWNGRADE → Medium · Evidence: lane 01 · Quote: VERIFIED
L1-F05 — IMPORT 선택 이유 stale
- Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED
L1-F06 — sub key와 collision locator
- Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED
L1-F07 — OAuth 2.1 BFF 조건 요약
- Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED
L1-F08 — localhost issuer와 bridge reachability
- Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED
L1-F09 — Google sub key dual owner
- Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED
L1-F10 — P1A/P1B backend trust
- Adversarial: KEEP → High · Evidence: lane 01 · Quote: VERIFIED
L1-F11 — oauth2-proxy와 Traefik 선택축
- Adversarial: DOWNGRADE → Medium · Evidence: lane 01 · Quote: VERIFIED
L1-F12 — browser token custody 표현
- Adversarial: DOWNGRADE → Low · Evidence: lane 01 · Quote: VERIFIED
L1-F13 — zero-change scope
- Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED
L1-F14 — zero-change audience ambiguity
- Adversarial: REJECT → N/A · Evidence: lane 01 · Quote: VERIFIED
L2-F01 — Confirm Link version gate
- Adversarial: REJECT → N/A · Evidence: lane 02 · Quote: VERIFIED
L2-F02 — silent-link prevention과 hard-reject
- Adversarial: KEEP → High · Evidence: lane 02 · Quote: VERIFIED
L2-F03 — IMPORT와 FORCE scope
- Adversarial: DOWNGRADE → Low · Evidence: lane 02 · Quote: VERIFIED
L2-F04 — Google basic-scope test-user 설명
- Adversarial: KEEP → Low · Evidence: lane 02 · Quote: VERIFIED
L2-F05 — JavaScript origins
- Adversarial: DOWNGRADE → Low · Evidence: lane 02 · Quote: VERIFIED
L2-F06 — Caddy HSTS default
- Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED
L2-F07 — Reference-Only와 foreign detail
- Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED
L2-F08 — brokering zero-change ownership
- Adversarial: KEEP → Medium · Evidence: lane 02 · Quote: VERIFIED
L2-F09 — SPA Direct 안의 BFF variant
- Adversarial: REJECT → N/A · Evidence: lane 02 · Quote: VERIFIED
L3-F01 — auth_request body 설명
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F02 — sign-in TODO 적용 범위
- Adversarial: REJECT → N/A · Evidence: lane 03 · Quote: VERIFIED
L3-F03 — token introspection 용어
- Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED
L3-F04 — bare decision reference
- Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED
L3-F05 — retired numbered naming
- Adversarial: DOWNGRADE → Low · Evidence: lane 03 · Quote: VERIFIED
L3-F06 — PKCE S256 D-row 중복
- Adversarial: REJECT → N/A · Evidence: lane 03 · Quote: VERIFIED
L3-F07 — PKCE Admin label
- Adversarial: KEEP → Low · Evidence: lane 03 · Quote: VERIFIED
L3-F08 — quick tunnel hostname
- Adversarial: KEEP → High · Evidence: lane 03 · Quote: VERIFIED
L3-F09 — realm import wiring scope
- Adversarial: DOWNGRADE → Low · Evidence: lane 03 · Quote: VERIFIED
L3-F10 — credential export certainty
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F11 — rotation contract와 execution
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F12 — back-channel receiver owner
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F13 — Max Reuse semantics
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F14 — Caddy prefix strip
- Adversarial: KEEP → High · Evidence: lane 03 · Quote: VERIFIED
L3-F15 — tunnel provider dual owner
- Adversarial: KEEP → Medium · Evidence: lane 03 · Quote: VERIFIED
L3-F16 — parent proxy bundle ownership
- Adversarial: DOWNGRADE → Medium · Evidence: lane 03 · Quote: VERIFIED
L4-F01 — localhost와 extra_hosts 대안
- Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED
L4-F02 — audience owner pointer stale
- Adversarial: KEEP → Medium · Evidence: lane 04 · Quote: VERIFIED
L4-F03 — PKCE manual-first 대 library-first
- Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED
L4-F04 — SPA Direct와 TMB 경계
- Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED
L4-F05 — evidence status stale
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F06 — cookie-CSRF owner gap
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F07 — custom validator와 property-first
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F08 — backend audience와 spa-client
- Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED
L4-F09 — role note의 audience 재명세
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F10 — realm-role-only 전제
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F11 — 3-leg taxonomy
- Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED
L4-F12 — nonce 자동 처리 evidence
- Adversarial: KEEP → Medium · Evidence: lane 04 · Quote: VERIFIED
L4-F13 — trust-chain foreign summary
- Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED
L4-F14 — P3A pattern misattribution
- Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED
L4-F15 — 302 생성 주체
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F16 — relative SPA endpoint origin
- Adversarial: KEEP → High · Evidence: lane 04 · Quote: VERIFIED
L4-F17 — oidc-client-ts storage default
- Adversarial: DOWNGRADE → Low · Evidence: lane 04 · Quote: VERIFIED
L4-F18 — automaticSilentRenew mechanism
- Adversarial: REJECT → N/A · Evidence: lane 04 · Quote: VERIFIED
L4-F19 — Phase C2 active table
- Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED
L4-F20 — JWT decoder와 clock skew
- Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED
L4-F21 — public-path verification contract
- Adversarial: DOWNGRADE → Medium · Evidence: lane 04 · Quote: VERIFIED
4-1. 적대 리뷰 결과 / Adversarial Review Results
| Metric | Count |
|---|---|
| Reviewed | 60 |
| KEEP | 21 |
| DOWNGRADE | 27 |
| REJECT | 12 |
| Final High | 10 |
| Final Medium | 18 |
| Final Low | 20 |
| Controller override | 0 |
Controller는 60개 권고를 모두 수용했다. REJECT는 중복 또는 active contradiction 전제 붕괴를 뜻하며 원문 상태의 무결함을 뜻하지 않는다.
5. 우선순위 권고 / Priority Recommendations
상세 Decision Conditions와 fix-plan: priority-recommendations.md
| Rank | Finding | Action | Verification |
|---|---|---|---|
| 1 | L4-F08 | API audience symbol과 owner를 하나로 고정 | realm export, token aud, 정상 및 wrong-audience test |
| 2 | L1-F08 | issuer identity와 container retrieval address를 실행 profile 하나로 종결 | rendered Compose, discovery와 JWKS log |
| 3 | L4-F16 | relative SPA endpoint를 same-origin proxy 또는 runtime absolute URL 중 하나로 선택 | browser와 access logs |
| 4 | L3-F14 | Caddy와 Keycloak path prefix 전략을 맞춤 | caddy adapt와 upstream path |
| 5 | L2-F02 | silent-link와 hard-reject policy를 분리 | flow export, SPI artifact, negative E2E |
| 6 | L4-F04 | pure SPA와 TMB variant를 분리 | refresh endpoint, CSRF, rotation E2E |
| 7 | L1-F10 | P1A와 P1B의 backend trust를 한 invariant로 확정 | SecurityFilterChain과 forwarding diff |
| 8 | L4-F14 | deployment 축과 authentication pattern 축을 분리 | pattern matrix와 component flow |
| 9 | L3-F08 | quick tunnel과 managed static hostname을 분리 | restart hostname과 redirect E2E |
| 10 | L1-F09 | Google sub key의 mutable owner를 하나로 선택 | owner map과 inbound references |
6. 후속 작업 / Follow-Up
- 사용자 승인 전 branch-note 원문 수정은 하지 않는다.
- High 10건은 개별 승인 단위로, L3-F04의 reference syntax 8건은 low-risk 묶음 승인 단위로 제안한다.
- logical edge 298건 전체 의미 대조가 필요하면 20건 이하 lane으로 분할하는 별도 sync round가 필요하다.
- Claims Extracted 36개 누락과 raw Claim target 검증은 migrate-claims 또는 전용 traceability audit로 분리한다.
- runtime 미검증과 code/canonical 범위는 unresolved-risk-register.md에 기록했다.
7. 검증 / Verification
7.1 Self-grep proof
- Finding T=60
- Finding별 proof row G=60
- 실행 command=107, 실패=0
- command stdout의 verified quote lines=158
- 미검증 finding=0
- 명령과 observed output은 sed-proofs.md와 각 lane에 있다.
7.2 실행한 검증
$ python3 .claude/hooks/wiki_consistency_check.py --all
repository files=102
repository findings=144
BARE_OWNER_REF=74
BARE_DECISION_REF=70
Keycloak-scope BARE_DECISION_REF=8
Keycloak-scope DANGLING_DECISION_REF=0
Keycloak-scope DANGLING_SECTION_REF=0
Keycloak-scope exact DUAL_OWNERSHIP=0
$ python3 docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/controller_verify.py
raw_file_count=38
matrix_rows=38
read_full_rows=38
blocked_rows=0
missing_paths=0
extra_paths=0
duplicate_paths=0
nonexistent_paths=0
malformed_matrix_rows=0
lane_finding_count=60
unique_finding_ids=60
duplicate_finding_ids=0
missing_finding_ids=0
finding_schema_failures=0
per_file_sections=38
sed_proof_rows=60
adversarial_rows=60
adversarial_generic_hits=0
unresolved_priority_ids=0
broken_internal_links=0
forbidden_word_hits=0
missing_required_artifacts=0
decision_evidence_map_files=38
claims_extracted_files=2
missing_claims_extracted=36
unsupported_decision_occurrences=125
8. Generated Artifacts
| Artifact | Path |
|---|---|
| Master | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-report.md |
| Controller verification | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-controller-verification.md |
| Adversarial entry | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency-adversarial-review.md |
| Evidence matrix | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/evidence-matrix.md |
| Per-file index | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/per-file-findings.md |
| Quote proofs | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/sed-proofs.md |
| Priority and fix-plan | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/priority-recommendations.md |
| Risk register | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/unresolved-risk-register.md |
| Adversarial matrix | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/adversarial-review.md |
| Lane 01 | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-01-keycloak-sorted-01-10.md |
| Lane 02 | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-02-keycloak-sorted-11-20.md |
| Lane 03 | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-03-keycloak-sorted-21-30.md |
| Lane 04 | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-04-keycloak-sorted-31-38.md |
| Semantic sample | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/lanes/lane-05-semantic-risk-sample.md |
| Process plan | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/implementation_plan.md |
| Process task | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/task.md |
| Process walkthrough | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/walkthrough.md |
| Controller script | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/controller_verify.py |
| Quote script | docs/superpowers/specs/2026-07-18-keycloak-branch-note-consistency/process/verify_quotes.py |