merge: Keycloak branch governance index
This commit is contained in:
@@ -5,3 +5,6 @@
|
||||
|
||||
backend/target/
|
||||
build/
|
||||
e2e/node_modules/
|
||||
frontend/node_modules/
|
||||
frontend/dist/
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Keycloak Authentication Patterns
|
||||
|
||||
The 39-branch implementation registry is documented in
|
||||
[`docs/keycloak-branch-index.md`](docs/keycloak-branch-index.md).
|
||||
|
||||
Keycloak을 중심으로 네 가지 브라우저 인증 통합 패턴을 같은 로컬
|
||||
인프라에서 비교하는 학습 프로젝트입니다.
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Keycloak branch implementation index
|
||||
|
||||
The source inventory contains 39 `feature-keycloak-*.md` branch notes. This
|
||||
repository preserves one local Git feature branch for every note and merges it
|
||||
with `--no-ff` into either the common `develop` baseline or one of the four
|
||||
authentication-pattern branches.
|
||||
|
||||
| Target | Meaning |
|
||||
|---|---|
|
||||
| `common` | Shared realm, federation, deployment, or governance contract. Merge into `develop`, then propagate to AP1–AP4. |
|
||||
| `ap1` | Browser-based OAuth client: vanilla SPA, Authorization Code + PKCE, Resource Server. |
|
||||
| `ap2` | Token-mediating confidential backend: browser receives access token only. |
|
||||
| `ap3` | BFF: backend owns every OAuth token and browser owns only a session cookie. |
|
||||
| `ap4` | Edge forward-auth: oauth2-proxy/Nginx owns login and backend trusts an isolated identity header. |
|
||||
|
||||
The machine-readable registry is
|
||||
[`keycloak-branch-manifest.tsv`](keycloak-branch-manifest.tsv). Run:
|
||||
|
||||
```bash
|
||||
./scripts/audit-keycloak-branches.sh
|
||||
```
|
||||
|
||||
The audit succeeds only when all 39 note names have matching local feature
|
||||
branches and each feature tip is reachable from its declared target branch.
|
||||
|
||||
Google credentials are never committed. The default local acceptance harness
|
||||
uses a second Keycloak realm as a controllable OIDC provider so claim mapping
|
||||
and unsafe-linking failure paths can be reproduced. A real Google login remains
|
||||
an explicit credentialed/public-HTTPS verification profile.
|
||||
@@ -0,0 +1,40 @@
|
||||
branch target delivery
|
||||
feature/keycloak-account-linking-spa-ux ap1 documented-and-contract-tested
|
||||
feature/keycloak-account-linking-sub-vs-email common documented-and-contract-tested
|
||||
feature/keycloak-bff-csrf-samesite-defense ap3 locally-verified
|
||||
feature/keycloak-bff-oauth2login-session ap3 locally-verified
|
||||
feature/keycloak-bff-vs-spa-direct ap3 documented
|
||||
feature/keycloak-docker-compose-stack common locally-verified
|
||||
feature/keycloak-edge-forwardauth-google-federation ap4 documented-and-config-tested
|
||||
feature/keycloak-edge-forwardauth-no-google ap4 documented-and-config-tested
|
||||
feature/keycloak-federation-spa-zero-change ap1 contract-tested
|
||||
feature/keycloak-first-broker-login-flow common locally-verified-with-mock-idp
|
||||
feature/keycloak-four-pattern-tradeoff-matrix common documented-and-evidence-linked
|
||||
feature/keycloak-google-claim-attribute-mapping common locally-verified-with-mock-idp
|
||||
feature/keycloak-google-redirect-uri-policy common config-tested
|
||||
feature/keycloak-header-spoofing-defense ap4 locally-verified
|
||||
feature/keycloak-https-termination-caddy-nginx common config-tested
|
||||
feature/keycloak-idp-brokering-google-client common locally-verified-with-mock-idp
|
||||
feature/keycloak-idp-mappers-claim-to-role common locally-verified-with-mock-idp
|
||||
feature/keycloak-internal-spa-direct-google-federation ap1 documented-and-contract-tested
|
||||
feature/keycloak-internal-spa-direct-no-google ap1 documented-and-contract-tested
|
||||
feature/keycloak-iss-claim-hostname-mismatch ap1 locally-verified
|
||||
feature/keycloak-nginx-auth-request-integration ap4 locally-verified
|
||||
feature/keycloak-oauth2-proxy-oidc-flow ap4 locally-verified
|
||||
feature/keycloak-patterns common governance
|
||||
feature/keycloak-pkce-flow-stages ap1 contract-tested
|
||||
feature/keycloak-public-domain-tunneling common config-tested
|
||||
feature/keycloak-realm-client-export common locally-verified
|
||||
feature/keycloak-refresh-rotation-and-logout ap1 locally-verified
|
||||
feature/keycloak-refresh-token-rotation ap1 contract-tested
|
||||
feature/keycloak-reverse-proxy-headers common config-tested
|
||||
feature/keycloak-single-ec2-google-federation ap1 documented-and-config-tested
|
||||
feature/keycloak-single-ec2-no-google ap1 documented-and-contract-tested
|
||||
feature/keycloak-spa-token-storage-tradeoff ap1 locally-verified
|
||||
feature/keycloak-spring-rs-audience-validator ap1 locally-verified
|
||||
feature/keycloak-spring-rs-role-mapping ap1 locally-verified
|
||||
feature/keycloak-three-leg-trust-chain ap1 documented-and-contract-tested
|
||||
feature/keycloak-token-mediating-access-handoff ap2 locally-verified
|
||||
feature/keycloak-token-mediating-confidential-client ap2 locally-verified
|
||||
feature/keycloak-traefik-forwardauth-alternative ap4 config-tested
|
||||
feature/keycloak-vanilla-js-spa-pkce ap1 locally-verified
|
||||
|
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
manifest="${1:-docs/keycloak-branch-manifest.tsv}"
|
||||
notes_dir="${KEYCLOAK_BRANCH_NOTES_DIR:-/home/donghyeon/workspace/ai-tools/llm-wiki/raw/branch-notes}"
|
||||
|
||||
expected_count="$(awk 'NR > 1 { count += 1 } END { print count + 0 }' "$manifest")"
|
||||
if [ "$expected_count" -ne 39 ]; then
|
||||
echo "manifest must contain exactly 39 Keycloak branches; found $expected_count" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
note_count="$(find "$notes_dir" -maxdepth 1 -type f -name 'feature-keycloak-*.md' | wc -l)"
|
||||
if [ "$note_count" -ne 39 ]; then
|
||||
echo "branch-note inventory must contain exactly 39 files; found $note_count" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
missing=0
|
||||
unmerged=0
|
||||
tab="$(printf '\t')"
|
||||
|
||||
while IFS="$tab" read -r branch target delivery; do
|
||||
[ "$branch" = "branch" ] && continue
|
||||
|
||||
note_name="$(printf '%s\n' "$branch" |
|
||||
sed 's#^feature/keycloak-#feature-keycloak-#').md"
|
||||
if [ ! -f "$notes_dir/$note_name" ]; then
|
||||
echo "missing branch note: $note_name" >&2
|
||||
missing=$((missing + 1))
|
||||
fi
|
||||
|
||||
if ! git show-ref --verify --quiet "refs/heads/$branch"; then
|
||||
echo "missing local branch: $branch" >&2
|
||||
missing=$((missing + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
common) target_branch="develop" ;;
|
||||
ap1) target_branch="develop-keycloak-pattern1" ;;
|
||||
ap2) target_branch="develop-keycloak-pattern2" ;;
|
||||
ap3) target_branch="develop-keycloak-pattern3" ;;
|
||||
ap4) target_branch="develop-keycloak-pattern4" ;;
|
||||
*)
|
||||
echo "unknown target '$target' for $branch ($delivery)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! git merge-base --is-ancestor "$branch" "$target_branch"; then
|
||||
echo "feature tip is not merged: $branch -> $target_branch" >&2
|
||||
unmerged=$((unmerged + 1))
|
||||
fi
|
||||
done < "$manifest"
|
||||
|
||||
if [ "$missing" -ne 0 ] || [ "$unmerged" -ne 0 ]; then
|
||||
echo "Keycloak branch audit failed: missing=$missing unmerged=$unmerged" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Keycloak branch audit passed: 39/39 branches exist and are merged"
|
||||
Reference in New Issue
Block a user