From 95c0e680b5c23a030b770b046d677e92e76a4de5 Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Sat, 5 Sep 2026 11:50:33 +0900 Subject: [PATCH] docs(keycloak-session-store): take the sentences out of the diagram canvases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The skill says drawings carry names and sentences go in and the paragraph beside the figure. I put sentences in node details and edge labels instead, and 27 of the 28 diagrams shipped with prose inside the canvas — "예측 다섯 개가 틀렸다", "아홉 번 조용히 실패했다", "막혀서 닿지 않는다". Only label and details render on the canvas; description does not. So every sentence moved to a noun phrase and the meaning stays in description, which was already carrying it. 막혀서 닿지 않는다 -> 차단 아홉 번 조용히 실패했다 -> 조용한 실패 9건 예측 다섯 개가 틀렸다 -> 틀린 예측 5건 로그아웃이 정리하지 않는다 -> 로그아웃 미정리 볼륨이 없으면 여기까지다 -> 볼륨 없음 Three node labels were sentences too and became names: 세션 스냅샷, 예측 선기록, 대조군 확보. What stays is what the rules protect — identifiers, commands and measured values: PRIMARY KEY (client_registration_id, principal_name), ValidationFailedException: 1 changesets check sum, nginx -t && nginx -s reload, SET LOCAL synchronous_commit TO OFF. Those are names of things, not prose about them. 294 canvas strings across 28 diagrams, none matching a sentence ending, average 11 characters. All 28 still lint clean and re-rendered. Co-Authored-By: Claude Opus 5 --- .../scripts/check_prose.mjs | 9 ++- .../a1-transport-vs-discovery/spec.json | 8 +-- .../.techviz/a3-commit-to-disk-gap/spec.json | 4 +- .../.techviz/a4-two-node-losses/spec.json | 6 +- .../.techviz/a5-partition-asymmetry/spec.json | 4 +- .../a6-latency-multiplication/spec.json | 4 +- .../.techviz/a8-cache-vs-session/spec.json | 6 +- .../b2-primary-key-overwrite/spec.json | 6 +- .../.techviz/b3-rotation-contention/spec.json | 4 +- .../b4-header-trust-boundary/spec.json | 6 +- .../.techviz/b5-b6-storage-and-keys/spec.json | 10 +-- .../b7-cookie-session-tradeoff/spec.json | 12 ++-- .../c2-backchannel-both-sides/spec.json | 10 +-- .../cache-temperature-outcomes/spec.json | 8 +-- .../.techviz/d2-upgrade-direction/spec.json | 10 +-- .../.techviz/d3-secret-exposure/spec.json | 6 +- .../final/.techviz/d4a-hook-effect/spec.json | 2 +- .../.techviz/injection-verification/spec.json | 8 +-- .../.techviz/measurement-control/spec.json | 10 +-- .../not-applicable-conditions/spec.json | 8 +-- .../.techviz/observation-points/spec.json | 2 +- .../open-questions-answered/spec.json | 10 +-- .../.techviz/renewal-to-serving-gap/spec.json | 4 +- .../.techviz/reproducibility-gap/spec.json | 12 ++-- .../.techviz/session-sharing-path/spec.json | 9 +-- .../version-conditional-results/spec.json | 8 +-- .../.techviz/wrong-predictions/spec.json | 10 +-- .../a1-transport-vs-discovery.alt.md | 4 +- .../a1-transport-vs-discovery.d2 | 4 +- .../a1-transport-vs-discovery.dot | 4 +- .../a1-transport-vs-discovery.drawio | 22 +++--- .../a1-transport-vs-discovery.excalidraw | 46 ++++++------ .../a1-transport-vs-discovery.manifest.json | 2 +- .../a1-transport-vs-discovery.mmd | 4 +- .../a1-transport-vs-discovery.svg | 46 ++++++------ .../a3-commit-to-disk-gap.drawio | 4 +- .../a3-commit-to-disk-gap.excalidraw | 8 +-- .../a3-commit-to-disk-gap.manifest.json | 2 +- .../a3-commit-to-disk-gap.svg | 2 +- .../a4-two-node-losses.drawio | 6 +- .../a4-two-node-losses.excalidraw | 12 ++-- .../a4-two-node-losses.manifest.json | 2 +- .../a4-two-node-losses/a4-two-node-losses.svg | 6 +- .../a5-partition-asymmetry.alt.md | 2 +- .../a5-partition-asymmetry.d2 | 2 +- .../a5-partition-asymmetry.dot | 2 +- .../a5-partition-asymmetry.drawio | 4 +- .../a5-partition-asymmetry.excalidraw | 8 +-- .../a5-partition-asymmetry.manifest.json | 2 +- .../a5-partition-asymmetry.mmd | 2 +- .../a5-partition-asymmetry.svg | 6 +- .../a6-latency-multiplication.alt.md | 4 +- .../a6-latency-multiplication.d2 | 4 +- .../a6-latency-multiplication.dot | 4 +- .../a6-latency-multiplication.drawio | 4 +- .../a6-latency-multiplication.excalidraw | 12 ++-- .../a6-latency-multiplication.manifest.json | 2 +- .../a6-latency-multiplication.mmd | 4 +- .../a6-latency-multiplication.svg | 8 +-- .../a8-cache-vs-session.alt.md | 6 +- .../a8-cache-vs-session.d2 | 6 +- .../a8-cache-vs-session.dot | 6 +- .../a8-cache-vs-session.drawio | 6 +- .../a8-cache-vs-session.excalidraw | 16 ++--- .../a8-cache-vs-session.manifest.json | 2 +- .../a8-cache-vs-session.mmd | 6 +- .../a8-cache-vs-session.svg | 12 ++-- .../b2-primary-key-overwrite.alt.md | 6 +- .../b2-primary-key-overwrite.d2 | 6 +- .../b2-primary-key-overwrite.dot | 6 +- .../b2-primary-key-overwrite.drawio | 6 +- .../b2-primary-key-overwrite.excalidraw | 20 +++--- .../b2-primary-key-overwrite.manifest.json | 2 +- .../b2-primary-key-overwrite.mmd | 6 +- .../b2-primary-key-overwrite.svg | 12 ++-- .../b3-rotation-contention.alt.md | 2 +- .../b3-rotation-contention.d2 | 2 +- .../b3-rotation-contention.dot | 2 +- .../b3-rotation-contention.drawio | 6 +- .../b3-rotation-contention.excalidraw | 20 +++--- .../b3-rotation-contention.manifest.json | 2 +- .../b3-rotation-contention.mmd | 2 +- .../b3-rotation-contention.svg | 4 +- .../b4-header-trust-boundary.alt.md | 2 +- .../b4-header-trust-boundary.d2 | 2 +- .../b4-header-trust-boundary.dot | 2 +- .../b4-header-trust-boundary.drawio | 20 +++--- .../b4-header-trust-boundary.excalidraw | 42 +++++------ .../b4-header-trust-boundary.manifest.json | 2 +- .../b4-header-trust-boundary.mmd | 2 +- .../b4-header-trust-boundary.svg | 46 ++++++------ .../b5-b6-storage-and-keys.alt.md | 6 +- .../b5-b6-storage-and-keys.d2 | 6 +- .../b5-b6-storage-and-keys.dot | 6 +- .../b5-b6-storage-and-keys.drawio | 12 ++-- .../b5-b6-storage-and-keys.excalidraw | 32 ++++----- .../b5-b6-storage-and-keys.manifest.json | 2 +- .../b5-b6-storage-and-keys.mmd | 6 +- .../b5-b6-storage-and-keys.svg | 20 +++--- .../b7-cookie-session-tradeoff.alt.md | 6 +- .../b7-cookie-session-tradeoff.d2 | 6 +- .../b7-cookie-session-tradeoff.dot | 6 +- .../b7-cookie-session-tradeoff.drawio | 14 ++-- .../b7-cookie-session-tradeoff.excalidraw | 36 +++++----- .../b7-cookie-session-tradeoff.manifest.json | 2 +- .../b7-cookie-session-tradeoff.mmd | 6 +- .../b7-cookie-session-tradeoff.svg | 22 +++--- .../c2-backchannel-both-sides.alt.md | 6 +- .../c2-backchannel-both-sides.d2 | 6 +- .../c2-backchannel-both-sides.dot | 6 +- .../c2-backchannel-both-sides.drawio | 24 +++---- .../c2-backchannel-both-sides.excalidraw | 50 ++++++------- .../c2-backchannel-both-sides.manifest.json | 2 +- .../c2-backchannel-both-sides.mmd | 6 +- .../c2-backchannel-both-sides.svg | 46 ++++++------ .../cache-temperature-outcomes.alt.md | 4 +- .../cache-temperature-outcomes.d2 | 4 +- .../cache-temperature-outcomes.dot | 4 +- .../cache-temperature-outcomes.drawio | 10 +-- .../cache-temperature-outcomes.excalidraw | 32 ++++----- .../cache-temperature-outcomes.manifest.json | 2 +- .../cache-temperature-outcomes.mmd | 4 +- .../cache-temperature-outcomes.svg | 16 ++--- .../d2-upgrade-direction.alt.md | 6 +- .../d2-upgrade-direction.d2 | 6 +- .../d2-upgrade-direction.dot | 6 +- .../d2-upgrade-direction.drawio | 10 +-- .../d2-upgrade-direction.excalidraw | 20 +++--- .../d2-upgrade-direction.manifest.json | 2 +- .../d2-upgrade-direction.mmd | 6 +- .../d2-upgrade-direction.svg | 16 ++--- .../d3-secret-exposure.alt.md | 4 +- .../d3-secret-exposure/d3-secret-exposure.d2 | 4 +- .../d3-secret-exposure/d3-secret-exposure.dot | 4 +- .../d3-secret-exposure.drawio | 6 +- .../d3-secret-exposure.excalidraw | 12 ++-- .../d3-secret-exposure.manifest.json | 2 +- .../d3-secret-exposure/d3-secret-exposure.mmd | 4 +- .../d3-secret-exposure/d3-secret-exposure.svg | 10 +-- .../d4a-hook-effect/d4a-hook-effect.alt.md | 2 +- .../assets/d4a-hook-effect/d4a-hook-effect.d2 | 2 +- .../d4a-hook-effect/d4a-hook-effect.dot | 2 +- .../d4a-hook-effect/d4a-hook-effect.drawio | 2 +- .../d4a-hook-effect.excalidraw | 8 +-- .../d4a-hook-effect.manifest.json | 2 +- .../d4a-hook-effect/d4a-hook-effect.mmd | 2 +- .../d4a-hook-effect/d4a-hook-effect.svg | 4 +- .../injection-verification.alt.md | 4 +- .../injection-verification.d2 | 4 +- .../injection-verification.dot | 4 +- .../injection-verification.drawio | 12 ++-- .../injection-verification.excalidraw | 24 +++---- .../injection-verification.manifest.json | 2 +- .../injection-verification.mmd | 4 +- .../injection-verification.svg | 22 +++--- .../measurement-control.alt.md | 6 +- .../measurement-control.d2 | 6 +- .../measurement-control.dot | 6 +- .../measurement-control.drawio | 24 +++---- .../measurement-control.excalidraw | 64 ++++++++--------- .../measurement-control.manifest.json | 2 +- .../measurement-control.mmd | 6 +- .../measurement-control.svg | 46 ++++++------ .../not-applicable-conditions.alt.md | 6 +- .../not-applicable-conditions.d2 | 6 +- .../not-applicable-conditions.dot | 6 +- .../not-applicable-conditions.drawio | 8 +-- .../not-applicable-conditions.excalidraw | 16 ++--- .../not-applicable-conditions.manifest.json | 2 +- .../not-applicable-conditions.mmd | 6 +- .../not-applicable-conditions.svg | 14 ++-- .../observation-points.drawio | 6 +- .../observation-points.excalidraw | 22 +++--- .../observation-points.manifest.json | 2 +- .../observation-points/observation-points.svg | 12 ++-- .../open-questions-answered.alt.md | 8 +-- .../open-questions-answered.d2 | 8 +-- .../open-questions-answered.dot | 8 +-- .../open-questions-answered.drawio | 10 +-- .../open-questions-answered.excalidraw | 24 +++---- .../open-questions-answered.manifest.json | 2 +- .../open-questions-answered.mmd | 8 +-- .../open-questions-answered.svg | 16 ++--- .../renewal-to-serving-gap.alt.md | 2 +- .../renewal-to-serving-gap.d2 | 2 +- .../renewal-to-serving-gap.dot | 2 +- .../renewal-to-serving-gap.drawio | 10 +-- .../renewal-to-serving-gap.excalidraw | 40 +++++------ .../renewal-to-serving-gap.manifest.json | 2 +- .../renewal-to-serving-gap.mmd | 2 +- .../renewal-to-serving-gap.svg | 18 ++--- .../reproducibility-gap.alt.md | 8 +-- .../reproducibility-gap.d2 | 8 +-- .../reproducibility-gap.dot | 8 +-- .../reproducibility-gap.drawio | 24 +++---- .../reproducibility-gap.excalidraw | 48 ++++++------- .../reproducibility-gap.manifest.json | 2 +- .../reproducibility-gap.mmd | 8 +-- .../reproducibility-gap.svg | 46 ++++++------ .../session-sharing-path.drawio | 22 +++--- .../session-sharing-path.excalidraw | 72 +++++++++---------- .../session-sharing-path.manifest.json | 2 +- .../session-sharing-path.svg | 52 +++++++------- .../version-conditional-results.alt.md | 4 +- .../version-conditional-results.d2 | 4 +- .../version-conditional-results.dot | 4 +- .../version-conditional-results.drawio | 8 +-- .../version-conditional-results.excalidraw | 16 ++--- .../version-conditional-results.manifest.json | 2 +- .../version-conditional-results.mmd | 4 +- .../version-conditional-results.svg | 12 ++-- .../wrong-predictions.alt.md | 12 ++-- .../wrong-predictions/wrong-predictions.d2 | 6 +- .../wrong-predictions/wrong-predictions.dot | 6 +- .../wrong-predictions.drawio | 6 +- .../wrong-predictions.excalidraw | 12 ++-- .../wrong-predictions.manifest.json | 2 +- .../wrong-predictions/wrong-predictions.mmd | 6 +- .../wrong-predictions/wrong-predictions.svg | 10 +-- .../case/case-ap3-bff-session-csrf.md | 50 +++++++------ .../case/case-ap4-identity-header-trust.md | 66 ++++++++--------- 221 files changed, 1156 insertions(+), 1152 deletions(-) diff --git a/.agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs b/.agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs index 3f407ec..8a307b9 100644 --- a/.agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs +++ b/.agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs @@ -139,8 +139,13 @@ function positiveChecks(text, lines, docMode, rulesMode) { // 사건을 서술하는 대신 그것이 무엇인지 이름 붙이고 끝낸다. 「확인한 자리다」·「~하는 실례다」· // 「~라는 점이다」. 참고 여섯 편은 이 어미를 통틀어 세 번 쓴다(17386 1 · 22396 2). 한 문서에 // 이것이 몰려 있으면 사건을 적지 않고 분류만 한 것이다. - const namingEnd = [...text.matchAll(/[가-힣)\]`]\s*(자리|실례|경우|출발점|사실|이유|점|것|뿐|셈)(이다|입니다)[.!]?(?=\s|$)/g)]; - const alwaysBad = namingEnd.filter((m) => /(자리|실례|출발점)/.test(m[1])); + // 「자리다」·「실례다」·「경우다」는 받침이 없어 `이`가 붙지 않는다. `이다` 만 찾으면 정작 + // 가장 나쁜 세 개를 놓친다 — 처음 이 규칙을 넣었을 때 그렇게 됐다. + const namingEnd = [ + ...text.matchAll(/[가-힣)\]`]\s*(사실|이유|점|것|뿐|셈)(이다|입니다)[.!]?(?=\s|$)/g), + ...text.matchAll(/[가-힣)\]`]\s*(자리|실례|경우|출발점|사례|대목)(다|이다|입니다)[.!]?(?=\s|$)/g), + ]; + const alwaysBad = namingEnd.filter((m) => /(자리|실례|출발점|대목)/.test(m[1])); for (const m of alwaysBad) { out.push({ id: 'naming-instead-of-telling', sev: ERR, index: m.index, excerpt: text.slice(Math.max(0, m.index - 30), m.index + m[0].length), diff --git a/docs/keycloak-session-store/final/.techviz/a1-transport-vs-discovery/spec.json b/docs/keycloak-session-store/final/.techviz/a1-transport-vs-discovery/spec.json index 1f8ec2d..b3be89e 100644 --- a/docs/keycloak-session-store/final/.techviz/a1-transport-vs-discovery/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a1-transport-vs-discovery/spec.json @@ -54,7 +54,7 @@ "emphasis": "warning", "description": "무효화 통지가 지나는 길. NetworkPolicy 로 막았다.", "details": [ - "8080·9000 만 열고 누락시킨다" + "허용 포트 8080 · 9000" ], "evidence": [ { @@ -72,7 +72,7 @@ "emphasis": "primary", "description": "통지를 못 받아 세션이 죽은 것을 모른다.", "details": [ - "400 이어야 할 refresh 가 200" + "refresh 200 (기대 400)" ], "evidence": [ { @@ -120,7 +120,7 @@ "id": "t-k1", "from": "transport", "to": "k1", - "label": "막혀서 닿지 않는다", + "label": "차단", "kind": "blocked", "evidence": [ { @@ -134,7 +134,7 @@ "id": "k1-db", "from": "k1", "to": "db", - "label": "세션은 여기서 읽는다 — 7800 과 무관", + "label": "세션 SELECT", "kind": "read", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/a3-commit-to-disk-gap/spec.json b/docs/keycloak-session-store/final/.techviz/a3-commit-to-disk-gap/spec.json index 441f051..f44b1f8 100644 --- a/docs/keycloak-session-store/final/.techviz/a3-commit-to-disk-gap/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a3-commit-to-disk-gap/spec.json @@ -38,7 +38,7 @@ "emphasis": "primary", "description": "200 과 토큰을 받는다.", "details": [ - "로그인 153건 성공" + "성공 응답 153건" ], "evidence": [ { @@ -92,7 +92,7 @@ "emphasis": "primary", "description": "여기 닿아야 살아남는다.", "details": [ - "DB 에 실제로 존재 149건" + "DB 존재 149건" ], "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/a4-two-node-losses/spec.json b/docs/keycloak-session-store/final/.techviz/a4-two-node-losses/spec.json index afabb99..5214506 100644 --- a/docs/keycloak-session-store/final/.techviz/a4-two-node-losses/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a4-two-node-losses/spec.json @@ -54,7 +54,7 @@ "emphasis": "warning", "description": "traefik 과 API 서버. 잃으면 000 이다.", "details": [ - "kubectl 도 불통" + "kubectl 불통" ], "evidence": [ { @@ -72,7 +72,7 @@ "emphasis": "normal", "description": "4b 에서는 계속 돌고 있었다.", "details": [ - "도달할 수 없을 뿐이다" + "도달 불가" ], "evidence": [ { @@ -90,7 +90,7 @@ "emphasis": "warning", "description": "4a 에서 함께 죽는다. 잃으면 503 이다.", "details": [ - "local-path PVC 라 재배치 불가" + "local-path PVC · 재배치 불가" ], "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/a5-partition-asymmetry/spec.json b/docs/keycloak-session-store/final/.techviz/a5-partition-asymmetry/spec.json index fa49845..1a157c9 100644 --- a/docs/keycloak-session-store/final/.techviz/a5-partition-asymmetry/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a5-partition-asymmetry/spec.json @@ -92,7 +92,7 @@ "emphasis": "normal", "description": "비대칭 차단에서는 여기로 재연결한다.", "details": [ - "가르지 못한다" + "재연결 경로" ], "evidence": [ { @@ -122,7 +122,7 @@ "id": "f-k1", "from": "fwd", "to": "k1", - "label": "막혀서 닿지 않는다", + "label": "차단", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/a6-latency-multiplication/spec.json b/docs/keycloak-session-store/final/.techviz/a6-latency-multiplication/spec.json index 2d2b2e8..b79adfb 100644 --- a/docs/keycloak-session-store/final/.techviz/a6-latency-multiplication/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a6-latency-multiplication/spec.json @@ -108,7 +108,7 @@ "id": "i-r", "from": "inject", "to": "roundtrips", - "label": "왕복마다 더해진다", + "label": "왕복당 누적", "kind": "request", "evidence": [ { @@ -122,7 +122,7 @@ "id": "r-p", "from": "roundtrips", "to": "pool", - "label": "커넥션 점유가 길어진다", + "label": "커넥션 점유", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/a8-cache-vs-session/spec.json b/docs/keycloak-session-store/final/.techviz/a8-cache-vs-session/spec.json index 3bcf7dd..68b4326 100644 --- a/docs/keycloak-session-store/final/.techviz/a8-cache-vs-session/spec.json +++ b/docs/keycloak-session-store/final/.techviz/a8-cache-vs-session/spec.json @@ -108,7 +108,7 @@ "id": "r-c", "from": "restart", "to": "cache", - "label": "비운다", + "label": "캐시 초기화", "kind": "write", "evidence": [ { @@ -122,7 +122,7 @@ "id": "r-db", "from": "restart", "to": "db", - "label": "건드리지 않는다", + "label": "변경 없음", "kind": "read", "evidence": [ { @@ -136,7 +136,7 @@ "id": "db-rt", "from": "db", "to": "refresh", - "label": "세션이 남아 있어 통한다", + "label": "세션 조회", "kind": "read", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/b2-primary-key-overwrite/spec.json b/docs/keycloak-session-store/final/.techviz/b2-primary-key-overwrite/spec.json index 8e6c13d..fc415b7 100644 --- a/docs/keycloak-session-store/final/.techviz/b2-primary-key-overwrite/spec.json +++ b/docs/keycloak-session-store/final/.techviz/b2-primary-key-overwrite/spec.json @@ -104,7 +104,7 @@ "id": "s1-t", "from": "s1", "to": "token-row", - "label": "principal 이름으로 쓴다", + "label": "principal 이름", "kind": "write", "evidence": [ { @@ -118,7 +118,7 @@ "id": "s2-t", "from": "s2", "to": "token-row", - "label": "같은 키로 덮어쓴다", + "label": "같은 키 · 덮어쓰기", "kind": "write", "evidence": [ { @@ -132,7 +132,7 @@ "id": "t-l", "from": "token-row", "to": "leftover", - "label": "로그아웃이 정리하지 않는다", + "label": "로그아웃 미정리", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/b3-rotation-contention/spec.json b/docs/keycloak-session-store/final/.techviz/b3-rotation-contention/spec.json index de61443..5cd7c72 100644 --- a/docs/keycloak-session-store/final/.techviz/b3-rotation-contention/spec.json +++ b/docs/keycloak-session-store/final/.techviz/b3-rotation-contention/spec.json @@ -38,7 +38,7 @@ "emphasis": "primary", "description": "같은 refresh token 을 쓴다.", "details": [ - "& 와 wait 이 없으면 재현되지 않는다" + "& + wait 필요" ], "evidence": [ { @@ -132,7 +132,7 @@ "id": "cs-nt", "from": "client-session", "to": "new-token", - "label": "세션이 없으니 못 쓴다", + "label": "사용 불가", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/b4-header-trust-boundary/spec.json b/docs/keycloak-session-store/final/.techviz/b4-header-trust-boundary/spec.json index 4826d71..324bd9f 100644 --- a/docs/keycloak-session-store/final/.techviz/b4-header-trust-boundary/spec.json +++ b/docs/keycloak-session-store/final/.techviz/b4-header-trust-boundary/spec.json @@ -56,7 +56,7 @@ "emphasis": "warning", "description": "설정하지 않은 이름은 덮어쓰지 않는다.", "details": [ - "proxy_set_header ... \"\" 로 먼저 지워야 한다" + "proxy_set_header ... \"\"" ], "evidence": [ { @@ -92,7 +92,7 @@ "emphasis": "primary", "description": "헤더를 믿고 인가한다.", "details": [ - "세션은 로그인 시점의 스냅샷" + "로그인 시점 스냅샷" ], "evidence": [ { @@ -122,7 +122,7 @@ "id": "n-p", "from": "nginx", "to": "proxy", - "label": "지우지 않으면 그대로 지난다", + "label": "미삭제 시 통과", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/b5-b6-storage-and-keys/spec.json b/docs/keycloak-session-store/final/.techviz/b5-b6-storage-and-keys/spec.json index 800b943..6d5cfb6 100644 --- a/docs/keycloak-session-store/final/.techviz/b5-b6-storage-and-keys/spec.json +++ b/docs/keycloak-session-store/final/.techviz/b5-b6-storage-and-keys/spec.json @@ -56,7 +56,7 @@ "emphasis": "warning", "description": "컨테이너 파일시스템이다.", "details": [ - "appendonlydir 이 만들어졌다 버려진다" + "appendonlydir" ], "evidence": [ { @@ -74,7 +74,7 @@ "emphasis": "warning", "description": "죽으면 /data 도 같이 사라진다.", "details": [ - "볼륨이 없으면 여기까지다" + "볼륨 없음" ], "evidence": [ { @@ -106,7 +106,7 @@ "id": "c-d", "from": "config", "to": "datadir", - "label": "AOF 파일을 쓴다", + "label": "AOF 기록", "kind": "write", "evidence": [ { @@ -120,7 +120,7 @@ "id": "d-c", "from": "datadir", "to": "container", - "label": "컨테이너와 함께 죽는다", + "label": "컨테이너와 함께 소멸", "kind": "blocked", "evidence": [ { @@ -134,7 +134,7 @@ "id": "d-v", "from": "datadir", "to": "volume", - "label": "볼륨을 붙여야 남는다", + "label": "볼륨 마운트", "kind": "write", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/b7-cookie-session-tradeoff/spec.json b/docs/keycloak-session-store/final/.techviz/b7-cookie-session-tradeoff/spec.json index 32b0f2d..c4a6817 100644 --- a/docs/keycloak-session-store/final/.techviz/b7-cookie-session-tradeoff/spec.json +++ b/docs/keycloak-session-store/final/.techviz/b7-cookie-session-tradeoff/spec.json @@ -56,7 +56,7 @@ "emphasis": "warning", "description": "세션 id 와 복호화 키가 함께 암호화되어 있다.", "details": [ - "secret 을 바꾸면 못 푼다" + "secret 교체 시 복호화 불가" ], "evidence": [ { @@ -74,7 +74,7 @@ "emphasis": "warning", "description": "티켓을 못 풀면 어느 키인지도 모른다.", "details": [ - "고아로 남는다" + "고아 세션" ], "evidence": [ { @@ -92,7 +92,7 @@ "emphasis": "primary", "description": "요청으로 갱신되지 않아 생성 시각의 함수다.", "details": [ - "역산으로 고아를 고른다" + "생성 시각 역산" ], "evidence": [ { @@ -108,7 +108,7 @@ "id": "s-t", "from": "secret", "to": "ticket", - "label": "티켓을 암호화한다", + "label": "티켓 암호화", "kind": "write", "evidence": [ { @@ -122,7 +122,7 @@ "id": "t-r", "from": "ticket", "to": "redis-session", - "label": "키 이름을 만든다", + "label": "키 이름 생성", "kind": "read", "evidence": [ { @@ -136,7 +136,7 @@ "id": "r-ttl", "from": "redis-session", "to": "ttl", - "label": "생성 시각이 여기 남는다", + "label": "생성 시각", "kind": "read", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/c2-backchannel-both-sides/spec.json b/docs/keycloak-session-store/final/.techviz/c2-backchannel-both-sides/spec.json index 95bee25..70ed0fc 100644 --- a/docs/keycloak-session-store/final/.techviz/c2-backchannel-both-sides/spec.json +++ b/docs/keycloak-session-store/final/.techviz/c2-backchannel-both-sides/spec.json @@ -54,7 +54,7 @@ "emphasis": "warning", "description": "클라이언트 설정. 비어 있었다.", "details": [ - "Keycloak 은 부를 주소를 모른다" + "주소 없음" ], "evidence": [ { @@ -90,7 +90,7 @@ "emphasis": "warning", "description": "그대로 남는다.", "details": [ - "네트워크는 200 으로 닿는다" + "네트워크 도달 200" ], "evidence": [ { @@ -106,7 +106,7 @@ "id": "l-c", "from": "logout", "to": "kc-config", - "label": "통지할 주소를 찾는다", + "label": "통지 주소 조회", "kind": "request", "evidence": [ { @@ -120,7 +120,7 @@ "id": "c-e", "from": "kc-config", "to": "app-endpoint", - "label": "주소가 있어야 부른다", + "label": "호출 (주소 필요)", "kind": "blocked", "evidence": [ { @@ -134,7 +134,7 @@ "id": "e-s", "from": "app-endpoint", "to": "app-session", - "label": "받을 곳이 있어야 지운다", + "label": "세션 삭제 (엔드포인트 필요)", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/cache-temperature-outcomes/spec.json b/docs/keycloak-session-store/final/.techviz/cache-temperature-outcomes/spec.json index f82086c..16a3d76 100644 --- a/docs/keycloak-session-store/final/.techviz/cache-temperature-outcomes/spec.json +++ b/docs/keycloak-session-store/final/.techviz/cache-temperature-outcomes/spec.json @@ -72,7 +72,7 @@ "emphasis": "warning", "description": "refresh 만 쏘고 첫 번째만 쏜다.", "details": [ - "DEFAULT_SCOPE='f' — 선택적 스코프" + "DEFAULT_SCOPE='f'" ], "evidence": [ { @@ -90,7 +90,7 @@ "emphasis": "primary", "description": "세운 상태다. 여기 닿는 조회만 실패한다.", "details": [ - "캐시에 있으면 닿지 않는다" + "캐시 미스 시에만 도달" ], "evidence": [ { @@ -120,7 +120,7 @@ "id": "c-s", "from": "client-lookup", "to": "scope-lookup", - "label": "refresh 는 스코프도 다시 계산한다", + "label": "스코프 재계산", "kind": "read", "evidence": [ { @@ -134,7 +134,7 @@ "id": "s-db", "from": "scope-lookup", "to": "db", - "label": "캐시에 없으면 여기까지 간다", + "label": "캐시 미스", "kind": "read", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/d2-upgrade-direction/spec.json b/docs/keycloak-session-store/final/.techviz/d2-upgrade-direction/spec.json index 621e89b..a4c4114 100644 --- a/docs/keycloak-session-store/final/.techviz/d2-upgrade-direction/spec.json +++ b/docs/keycloak-session-store/final/.techviz/d2-upgrade-direction/spec.json @@ -72,7 +72,7 @@ "emphasis": "primary", "description": "첫 파드가 실패하면 거기서 멈춘다.", "details": [ - "나머지 파드는 건드리지 않는다" + "나머지 파드 유지" ], "evidence": [ { @@ -106,7 +106,7 @@ "emphasis": "primary", "description": "전후로 같으면 롤백된다.", "details": [ - "늘었으면 스키마가 움직였다" + "전후 행 수 비교" ], "evidence": [ { @@ -136,7 +136,7 @@ "id": "l-ro", "from": "liquibase", "to": "rolling", - "label": "실패가 여기서 멈춘다", + "label": "중단 지점", "kind": "blocked", "evidence": [ { @@ -150,7 +150,7 @@ "id": "ro-s", "from": "rolling", "to": "service", - "label": "남은 파드가 응답한다", + "label": "잔여 파드 응답", "kind": "request", "evidence": [ { @@ -164,7 +164,7 @@ "id": "l-cl", "from": "liquibase", "to": "changelog", - "label": "무엇을 보고 판단하나", + "label": "판단 기준", "kind": "read", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/d3-secret-exposure/spec.json b/docs/keycloak-session-store/final/.techviz/d3-secret-exposure/spec.json index 3fdd131..d6952a4 100644 --- a/docs/keycloak-session-store/final/.techviz/d3-secret-exposure/spec.json +++ b/docs/keycloak-session-store/final/.techviz/d3-secret-exposure/spec.json @@ -38,7 +38,7 @@ "emphasis": "warning", "description": "base64 로 담긴다.", "details": [ - "인코딩이지 암호화가 아니다" + "base64 인코딩" ], "evidence": [ { @@ -88,7 +88,7 @@ "id": "s-e", "from": "secret", "to": "etcd", - "label": "여기 저장된다", + "label": "저장", "kind": "write", "evidence": [ { @@ -102,7 +102,7 @@ "id": "s-p", "from": "secret", "to": "pod", - "label": "주입된다", + "label": "주입", "kind": "write", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/d4a-hook-effect/spec.json b/docs/keycloak-session-store/final/.techviz/d4a-hook-effect/spec.json index 2c2897c..063a0aa 100644 --- a/docs/keycloak-session-store/final/.techviz/d4a-hook-effect/spec.json +++ b/docs/keycloak-session-store/final/.techviz/d4a-hook-effect/spec.json @@ -134,7 +134,7 @@ "id": "w-s", "from": "worker", "to": "serving", - "label": "새 워커가 새 인증서를 읽는다", + "label": "새 인증서 적재", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/injection-verification/spec.json b/docs/keycloak-session-store/final/.techviz/injection-verification/spec.json index a56e856..082cf91 100644 --- a/docs/keycloak-session-store/final/.techviz/injection-verification/spec.json +++ b/docs/keycloak-session-store/final/.techviz/injection-verification/spec.json @@ -38,7 +38,7 @@ "emphasis": "primary", "description": "NetworkPolicy · tc · kill · iptables.", "details": [ - "아홉 번 조용히 실패했다" + "조용한 실패 9건" ], "evidence": [ { @@ -74,7 +74,7 @@ "emphasis": "primary", "description": "여기만 보면 두 상황이 같아 보인다.", "details": [ - "주입 실패 = 영향 없음 으로 읽힌다" + "실패 · 무영향 구별 불가" ], "evidence": [ { @@ -90,7 +90,7 @@ "id": "i-v", "from": "inject", "to": "verify", - "label": "걸렸는가를 먼저 본다", + "label": "상태 확인", "kind": "request", "evidence": [ { @@ -104,7 +104,7 @@ "id": "v-o", "from": "verify", "to": "observe", - "label": "걸린 뒤에만 결과를 읽는다", + "label": "결과 판독", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/measurement-control/spec.json b/docs/keycloak-session-store/final/.techviz/measurement-control/spec.json index 4ae48b3..dec1581 100644 --- a/docs/keycloak-session-store/final/.techviz/measurement-control/spec.json +++ b/docs/keycloak-session-store/final/.techviz/measurement-control/spec.json @@ -72,7 +72,7 @@ "emphasis": "primary", "description": "대조군과 대비될 때만 성립한다.", "details": [ - "대조군이 0 이므로 한 번도 갱신 탓" + "대조군 0 → 귀속 성립" ], "evidence": [ { @@ -90,7 +90,7 @@ "emphasis": "warning", "description": "대조군이 없으면 여기로 간다.", "details": [ - "76건 실패는 로컬 아티팩트였다" + "로컬 아티팩트 76건" ], "evidence": [ { @@ -106,7 +106,7 @@ "id": "b-o", "from": "baseline", "to": "observation", - "label": "비교 기준을 준다", + "label": "비교 기준", "kind": "read", "evidence": [ { @@ -120,7 +120,7 @@ "id": "o-a", "from": "observation", "to": "attribution", - "label": "대조가 있으면", + "label": "대조군 있음", "kind": "request", "evidence": [ { @@ -134,7 +134,7 @@ "id": "o-m", "from": "observation", "to": "misreport", - "label": "대조가 없으면", + "label": "대조군 없음", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/not-applicable-conditions/spec.json b/docs/keycloak-session-store/final/.techviz/not-applicable-conditions/spec.json index 8e8b58c..3294e2d 100644 --- a/docs/keycloak-session-store/final/.techviz/not-applicable-conditions/spec.json +++ b/docs/keycloak-session-store/final/.techviz/not-applicable-conditions/spec.json @@ -38,7 +38,7 @@ "emphasis": "warning", "description": "26 미만이면 세션의 거처가 다르다.", "details": [ - "A층 결론 중 셋이 뒤집힌다" + "A층 결론 3건 반전" ], "evidence": [ { @@ -106,7 +106,7 @@ "id": "v-c", "from": "version", "to": "cache", - "label": "버전이 먼저다", + "label": "선행 조건", "kind": "request", "evidence": [ { @@ -120,7 +120,7 @@ "id": "c-i", "from": "cache", "to": "instances", - "label": "그 다음", + "label": "다음 조건", "kind": "request", "evidence": [ { @@ -134,7 +134,7 @@ "id": "i-cl", "from": "instances", "to": "clock", - "label": "수치를 읽을 때", + "label": "수치 해석", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/observation-points/spec.json b/docs/keycloak-session-store/final/.techviz/observation-points/spec.json index 407822a..2976d8c 100644 --- a/docs/keycloak-session-store/final/.techviz/observation-points/spec.json +++ b/docs/keycloak-session-store/final/.techviz/observation-points/spec.json @@ -56,7 +56,7 @@ "emphasis": "normal", "description": "사용자가 겪는 것.", "details": [ - "분단돼도 200 이 나올 수 있다" + "분단 시에도 200" ], "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/open-questions-answered/spec.json b/docs/keycloak-session-store/final/.techviz/open-questions-answered/spec.json index 9240693..023fed0 100644 --- a/docs/keycloak-session-store/final/.techviz/open-questions-answered/spec.json +++ b/docs/keycloak-session-store/final/.techviz/open-questions-answered/spec.json @@ -74,7 +74,7 @@ "emphasis": "warning", "description": "덮어쓰기와 정리 누락은 여기가 원인이다.", "details": [ - "세션 id 가 키에 없다" + "키에 세션 id 없음" ], "evidence": [ { @@ -86,7 +86,7 @@ }, { "id": "snapshot", - "label": "세션은 스냅샷이다", + "label": "세션 스냅샷", "kind": "process", "role": "target", "emphasis": "warning", @@ -108,7 +108,7 @@ "id": "q-s", "from": "questions", "to": "store-choice", - "label": "먼저 여기를 본다", + "label": "1차 검토", "kind": "request", "evidence": [ { @@ -122,7 +122,7 @@ "id": "s-sc", "from": "store-choice", "to": "schema", - "label": "여기서 풀리지 않는 것", + "label": "미해결 잔여", "kind": "request", "evidence": [ { @@ -136,7 +136,7 @@ "id": "sc-sn", "from": "schema", "to": "snapshot", - "label": "남는 것", + "label": "최종 잔여", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/renewal-to-serving-gap/spec.json b/docs/keycloak-session-store/final/.techviz/renewal-to-serving-gap/spec.json index 97a695a..82e114e 100644 --- a/docs/keycloak-session-store/final/.techviz/renewal-to-serving-gap/spec.json +++ b/docs/keycloak-session-store/final/.techviz/renewal-to-serving-gap/spec.json @@ -56,7 +56,7 @@ "emphasis": "primary", "description": "심볼릭 링크. 경로는 그대로이고 가리키는 대상만 바뀐다.", "details": [ - "archive/cert2.pem 을 가리킨다" + "→ archive/cert2.pem" ], "evidence": [ { @@ -122,7 +122,7 @@ "id": "needs-reload", "from": "live-link", "to": "nginx", - "label": "reload 없이는 닿지 않는다", + "label": "reload 필요", "kind": "blocked", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/reproducibility-gap/spec.json b/docs/keycloak-session-store/final/.techviz/reproducibility-gap/spec.json index 5b7ed19..cb3f445 100644 --- a/docs/keycloak-session-store/final/.techviz/reproducibility-gap/spec.json +++ b/docs/keycloak-session-store/final/.techviz/reproducibility-gap/spec.json @@ -32,13 +32,13 @@ "nodes": [ { "id": "prose", - "label": "산문으로 적힌 측정 장치", + "label": "산문 상태의 측정 장치", "kind": "component", "role": "source", "emphasis": "warning", "description": "괄호와 설명으로 남아 있었다.", "details": [ - "( curl ... ) & 를 20개 띄우고 wait" + "부하 생성기 20건" ], "evidence": [ { @@ -90,7 +90,7 @@ "emphasis": "primary", "description": "실행까지 확인된 것만.", "details": [ - "상주 탐침으로 20/20" + "상주 탐침 20/20" ], "evidence": [ { @@ -106,7 +106,7 @@ "id": "p-c", "from": "prose", "to": "command", - "label": "바꿔 적는다", + "label": "명령화", "kind": "request", "evidence": [ { @@ -120,7 +120,7 @@ "id": "c-e", "from": "command", "to": "execute", - "label": "돌려본다", + "label": "실행", "kind": "request", "evidence": [ { @@ -134,7 +134,7 @@ "id": "e-v", "from": "execute", "to": "verified", - "label": "통과한 것만 남긴다", + "label": "통과분 채택", "kind": "request", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/session-sharing-path/spec.json b/docs/keycloak-session-store/final/.techviz/session-sharing-path/spec.json index 1f7c2c6..9ec70da 100644 --- a/docs/keycloak-session-store/final/.techviz/session-sharing-path/spec.json +++ b/docs/keycloak-session-store/final/.techviz/session-sharing-path/spec.json @@ -38,7 +38,7 @@ "emphasis": "primary", "description": "로그인을 처리하고 자기 sessions 캐시에만 엔트리를 남긴다.", "details": [ - "자기가 처리한 로그인만 캐시" + "자기 처리분만 캐시" ], "evidence": [ { @@ -56,7 +56,7 @@ "emphasis": "primary", "description": "OFFLINE_USER_SESSION 에 세션 행을 보관한다. 두 노드가 같은 행을 본다.", "details": [ - "offline_flag='0' 이 온라인 세션" + "offline_flag='0'" ], "evidence": [ { @@ -74,7 +74,7 @@ "emphasis": "primary", "description": "다른 노드가 만든 세션을 캐시로 받지 않고 데이터베이스에서 읽는다.", "details": [ - "refresh 요청을 받으면 DB 를 조회" + "refresh 시 DB 조회" ], "evidence": [ { @@ -97,7 +97,8 @@ "end_line": 46 } ], - "assumption": false + "assumption": false, + "details": [] } ], "edges": [ diff --git a/docs/keycloak-session-store/final/.techviz/version-conditional-results/spec.json b/docs/keycloak-session-store/final/.techviz/version-conditional-results/spec.json index 54f0804..e2df011 100644 --- a/docs/keycloak-session-store/final/.techviz/version-conditional-results/spec.json +++ b/docs/keycloak-session-store/final/.techviz/version-conditional-results/spec.json @@ -38,7 +38,7 @@ "emphasis": "primary", "description": "Keycloak 26 기본값.", "details": [ - "세션을 DB 에 쓴다" + "세션 → DB" ], "evidence": [ { @@ -56,7 +56,7 @@ "emphasis": "warning", "description": "24 이전 방식.", "details": [ - "세션이 메모리에만 있다" + "세션 → 메모리" ], "evidence": [ { @@ -108,7 +108,7 @@ "id": "p-to-db", "from": "persistent", "to": "db-session", - "label": "세션을 여기 쓴다", + "label": "세션 기록", "kind": "write", "evidence": [ { @@ -122,7 +122,7 @@ "id": "v-to-mem", "from": "volatile", "to": "memory-session", - "label": "세션이 여기 있다", + "label": "세션 보관", "kind": "write", "evidence": [ { diff --git a/docs/keycloak-session-store/final/.techviz/wrong-predictions/spec.json b/docs/keycloak-session-store/final/.techviz/wrong-predictions/spec.json index a298213..baf7482 100644 --- a/docs/keycloak-session-store/final/.techviz/wrong-predictions/spec.json +++ b/docs/keycloak-session-store/final/.techviz/wrong-predictions/spec.json @@ -32,13 +32,13 @@ "nodes": [ { "id": "predict", - "label": "예측을 먼저 적는다", + "label": "예측 선기록", "kind": "process", "role": "source", "emphasis": "primary", "description": "결과를 보고 나면 정직하게 쓸 수 없다.", "details": [ - "예측 다섯 개가 틀렸다" + "틀린 예측 5건" ], "evidence": [ { @@ -50,13 +50,13 @@ }, { "id": "verify", - "label": "주입이 걸렸는지 확인", + "label": "주입 검증", "kind": "process", "role": "control", "emphasis": "primary", "description": "아무 일도 없었다와 영향이 없다를 가른다.", "details": [ - "아홉 번 조용히 실패했다" + "조용한 실패 9건" ], "evidence": [ { @@ -68,7 +68,7 @@ }, { "id": "control", - "label": "대조군을 잡는다", + "label": "대조군 확보", "kind": "process", "role": "control", "emphasis": "warning", diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.alt.md b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.alt.md index d9e6379..e51fd6f 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.alt.md +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.alt.md @@ -18,5 +18,5 @@ ## Relationships - **keycloak-0 → TCP 7800:** 무효화 통지. Evidence: L186–L190. -- **keycloak-1 → PostgreSQL:** 세션은 여기서 읽는다 — 7800 과 무관. Evidence: L186–L189. -- **TCP 7800 → keycloak-1:** 막혀서 닿지 않는다. Evidence: L186–L190. +- **keycloak-1 → PostgreSQL:** 세션 SELECT. Evidence: L186–L189. +- **TCP 7800 → keycloak-1:** 차단. Evidence: L186–L190. diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.d2 b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.d2 index dd64f28..5865eb6 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.d2 +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.d2 @@ -14,5 +14,5 @@ n3: "PostgreSQL" { shape: cylinder } n0 -> n1: "무효화 통지" -n1 -> n2: "막혀서 닿지 않는다" -n2 -> n3: "세션은 여기서 읽는다 — 7800 과 무관" +n1 -> n2: "차단" +n2 -> n3: "세션 SELECT" diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.dot b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.dot index e1007d1..3c218e6 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.dot +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.dot @@ -7,6 +7,6 @@ digraph techviz { n2 [label="keycloak-1", shape=box, style="rounded,filled"]; n3 [label="PostgreSQL", shape=cylinder, style="rounded,filled"]; n0 -> n1 [label="무효화 통지", style=solid]; - n1 -> n2 [label="막혀서 닿지 않는다", style=solid]; - n2 -> n3 [label="세션은 여기서 읽는다 — 7800 과 무관", style=solid]; + n1 -> n2 [label="차단", style=solid]; + n2 -> n3 [label="세션 SELECT", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.drawio b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.drawio index 2017866..6dcdc94 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.drawio +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.drawio @@ -6,30 +6,30 @@ - + - - + + - - + + - + - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.excalidraw b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.excalidraw index 46f9a5d..57677d1 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.excalidraw +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.excalidraw @@ -6,7 +6,7 @@ { "id": "edge-k0-t", "type": "arrow", - "x": 167.5, + "x": 157.0, "y": 124.0, "width": 0.0, "height": 96.0, @@ -66,7 +66,7 @@ { "id": "edge-label-k0-t", "type": "text", - "x": 146.5, + "x": 136.0, "y": 160.0, "width": 90, "height": 24, @@ -105,7 +105,7 @@ { "id": "edge-k1-db", "type": "arrow", - "x": 167.5, + "x": 157.0, "y": 458.0, "width": 0.0, "height": 96.0, @@ -165,9 +165,9 @@ { "id": "edge-label-k1-db", "type": "text", - "x": 99.5, + "x": 136.0, "y": 494.0, - "width": 184, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,18 +193,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "세션은 여기서 읽는다 — 7800 과 무관", + "text": "세션 SELECT", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션은 여기서 읽는다 — 7800 과 무관", + "originalText": "세션 SELECT", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-t-k1", "type": "arrow", - "x": 167.5, + "x": 157.0, "y": 291.0, "width": 0.0, "height": 96.0, @@ -264,7 +264,7 @@ { "id": "edge-label-t-k1", "type": "text", - "x": 146.5, + "x": 136.0, "y": 327.0, "width": 90, "height": 24, @@ -292,18 +292,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "막혀서 닿지 않는다", + "text": "차단", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "막혀서 닿지 않는다", + "originalText": "차단", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-k0", "type": "rectangle", - "x": 92.5, + "x": 82.0, "y": 60.0, "width": 150.0, "height": 64.0, @@ -333,7 +333,7 @@ { "id": "node-label-k0", "type": "text", - "x": 102.5, + "x": 92.0, "y": 70.0, "width": 130.0, "height": 44.0, @@ -374,7 +374,7 @@ "type": "rectangle", "x": 80.5, "y": 220.0, - "width": 174.0, + "width": 153.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -404,7 +404,7 @@ "type": "text", "x": 90.5, "y": 230.0, - "width": 154.0, + "width": 133.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "TCP 7800\n8080·9000 만 열고 누락시킨다", + "text": "TCP 7800\n허용 포트 8080 · 9000", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "TCP 7800\n8080·9000 만 열고 누락시킨다", + "originalText": "TCP 7800\n허용 포트 8080 · 9000", "autoResize": true, "lineHeight": 1.25 }, @@ -443,7 +443,7 @@ "type": "rectangle", "x": 70.0, "y": 387.0, - "width": 195.0, + "width": 174.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -473,7 +473,7 @@ "type": "text", "x": 80.0, "y": 397.0, - "width": 175.0, + "width": 154.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -499,18 +499,18 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "keycloak-1\n400 이어야 할 refresh 가 200", + "text": "keycloak-1\nrefresh 200 (기대 400)", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "keycloak-1\n400 이어야 할 refresh 가 200", + "originalText": "keycloak-1\nrefresh 200 (기대 400)", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-db", "type": "rectangle", - "x": 91.0, + "x": 80.5, "y": 554.0, "width": 153.0, "height": 97.0, @@ -540,7 +540,7 @@ { "id": "node-label-db", "type": "text", - "x": 101.0, + "x": 90.5, "y": 564.0, "width": 133.0, "height": 77.0, diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.manifest.json b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.manifest.json index 9963901..ca703c3 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.manifest.json +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a1-transport-vs-discovery", "spec_version": "1.1", - "spec_sha256": "af42cd905290687548b620849f1e143752f9ab346de4de352701256cc6657e32", + "spec_sha256": "f54cae81276a31a8b73961148cadf3ae5cd256bdc38a9c002997fce63c243ebf", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.mmd b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.mmd index b7dbc6d..ff25260 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.mmd +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.mmd @@ -6,5 +6,5 @@ flowchart TB n2["keycloak-1"] n3[("PostgreSQL")] n0 -->|"무효화 통지"| n1 - n1 -->|"막혀서 닿지 않는다"| n2 - n2 -->|"세션은 여기서 읽는다 — 7800 과 무관"| n3 + n1 -->|"차단"| n2 + n2 -->|"세션 SELECT"| n3 diff --git a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.svg b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.svg index 96c40ce..3c5cb7b 100644 --- a/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.svg +++ b/docs/keycloak-session-store/final/assets/a1-transport-vs-discovery/a1-transport-vs-discovery.svg @@ -50,35 +50,35 @@ - - -무효화 통지 - - -세션은 여기서 읽는다 — 7800 과 무관 - - -막혀서 닿지 않는다 + + +무효화 통지 + + +세션 SELECT + + +차단 - -keycloak-0 + +keycloak-0 - -TCP 7800 - -8080·9000 만 열고 누락시킨다 + +TCP 7800 + +허용 포트 8080 · 9000 - -keycloak-1 - -400 이어야 할 refresh 가 200 + +keycloak-1 + +refresh 200 (기대 400) - -PostgreSQL - -교차 노드 refresh 200 + +PostgreSQL + +교차 노드 refresh 200 diff --git a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.drawio b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.drawio index 4a6aa39..341f831 100644 --- a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.drawio +++ b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.drawio @@ -5,7 +5,7 @@ - + @@ -14,7 +14,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.excalidraw b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.excalidraw index d8e3a4d..9a8214b 100644 --- a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.excalidraw +++ b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.excalidraw @@ -361,11 +361,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "클라이언트\n로그인 153건 성공", + "text": "클라이언트\n성공 응답 153건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "클라이언트\n로그인 153건 성공", + "originalText": "클라이언트\n성공 응답 153건", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "디스크의 WAL\nDB 에 실제로 존재 149건", + "text": "디스크의 WAL\nDB 존재 149건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "디스크의 WAL\nDB 에 실제로 존재 149건", + "originalText": "디스크의 WAL\nDB 존재 149건", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.manifest.json b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.manifest.json index fba0187..7e3ca3d 100644 --- a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.manifest.json +++ b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a3-commit-to-disk-gap", "spec_version": "1.1", - "spec_sha256": "29e279f39e07ba519e4e0685e5719d5d63b3ecf8b61a18816cbd5a1529baf854", + "spec_sha256": "1dfb52c8df3953df103ea2d515cf5a4f3cfed507d286e093fad31b583a851ce2", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.svg b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.svg index 34daa78..827c2d7 100644 --- a/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.svg +++ b/docs/keycloak-session-store/final/assets/a3-commit-to-disk-gap/a3-commit-to-disk-gap.svg @@ -79,6 +79,6 @@ 디스크의 WAL -DB 에 실제로 존재 149건 +DB 존재 149건 diff --git a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.drawio b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.drawio index bd798c6..ae1ad0a 100644 --- a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.drawio +++ b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.drawio @@ -8,13 +8,13 @@ - + - + - + diff --git a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.excalidraw b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.excalidraw index db14129..8d3004b 100644 --- a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.excalidraw +++ b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.excalidraw @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "진입 경로 (kc-lab-1)\nkubectl 도 불통", + "text": "진입 경로 (kc-lab-1)\nkubectl 불통", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "진입 경로 (kc-lab-1)\nkubectl 도 불통", + "originalText": "진입 경로 (kc-lab-1)\nkubectl 불통", "autoResize": true, "lineHeight": 1.25 }, @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "keycloak-0 (kc-lab-2)\n도달할 수 없을 뿐이다", + "text": "keycloak-0 (kc-lab-2)\n도달 불가", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "keycloak-0 (kc-lab-2)\n도달할 수 없을 뿐이다", + "originalText": "keycloak-0 (kc-lab-2)\n도달 불가", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "PostgreSQL (kc-lab-2)\nlocal-path PVC 라 재배치 불가", + "text": "PostgreSQL (kc-lab-2)\nlocal-path PVC · 재배치 불가", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "PostgreSQL (kc-lab-2)\nlocal-path PVC 라 재배치 불가", + "originalText": "PostgreSQL (kc-lab-2)\nlocal-path PVC · 재배치 불가", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.manifest.json b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.manifest.json index 968d372..6fe6de0 100644 --- a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.manifest.json +++ b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a4-two-node-losses", "spec_version": "1.1", - "spec_sha256": "788cb5ef3210d1bb16d41feb27bd35f4041e93fea3e9826e4463391b82ccee5e", + "spec_sha256": "3c9bc2fcbc853f176e8a38fc838062a36779083d1affe8e46a560484e230233b", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.svg b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.svg index 1578b12..a3e39b9 100644 --- a/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.svg +++ b/docs/keycloak-session-store/final/assets/a4-two-node-losses/a4-two-node-losses.svg @@ -67,18 +67,18 @@ 진입 경로 (kc-lab-1) -kubectl 도 불통 +kubectl 불통 keycloak-0 (kc-lab-2) -도달할 수 없을 뿐이다 +도달 불가 PostgreSQL (kc-lab-2) -local-path PVC 라 재배치 불가 +local-path PVC · 재배치 불가 diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.alt.md b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.alt.md index 592ccb8..23a2b4c 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.alt.md +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.alt.md @@ -17,6 +17,6 @@ JGroups 는 한 방향이 막혀도 열린 방향으로 재연결한다. 그래 ## Relationships -- **막은 방향 → keycloak-1:** 막혀서 닿지 않는다. Evidence: L226–L232. +- **막은 방향 → keycloak-1:** 차단. Evidence: L226–L232. - **keycloak-0 → 막은 방향:** JGroups 메시지. Evidence: L226–L232. - **keycloak-1 → 열린 반대 방향:** 반대 방향으로 재연결. Evidence: L226–L232. diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.d2 b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.d2 index 3740aba..5f8d418 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.d2 +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.d2 @@ -14,5 +14,5 @@ n3: "열린 반대 방향" { shape: rectangle } n0 -> n1: "JGroups 메시지" -n1 -> n2: "막혀서 닿지 않는다" +n1 -> n2: "차단" n2 -> n3: "반대 방향으로 재연결" diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.dot b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.dot index 9a1f7fe..0df4a23 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.dot +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.dot @@ -7,6 +7,6 @@ digraph techviz { n2 [label="keycloak-1", shape=box, style="rounded,filled"]; n3 [label="열린 반대 방향", shape=box, style="rounded,filled"]; n0 -> n1 [label="JGroups 메시지", style=solid]; - n1 -> n2 [label="막혀서 닿지 않는다", style=solid]; + n1 -> n2 [label="차단", style=solid]; n2 -> n3 [label="반대 방향으로 재연결", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.drawio b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.drawio index 65d1b90..05516d2 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.drawio +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.drawio @@ -14,10 +14,10 @@ - + - + diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.excalidraw b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.excalidraw index c4a336c..37c194e 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.excalidraw +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "막혀서 닿지 않는다", + "text": "차단", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "막혀서 닿지 않는다", + "originalText": "차단", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "열린 반대 방향\n가르지 못한다", + "text": "열린 반대 방향\n재연결 경로", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "열린 반대 방향\n가르지 못한다", + "originalText": "열린 반대 방향\n재연결 경로", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.manifest.json b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.manifest.json index b02a6cf..b9c433b 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.manifest.json +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a5-partition-asymmetry", "spec_version": "1.1", - "spec_sha256": "26b2dc620b94c979befdef3808475899361f52b7f622fc06a78b5c6c59cd72a7", + "spec_sha256": "9b10dfa9cfb1f24e5b105da13bc8fde85130cc1cca2ddad54cd57c32bc2dfcf5", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.mmd b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.mmd index 78b55ca..56a72bb 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.mmd +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.mmd @@ -6,5 +6,5 @@ flowchart TB n2["keycloak-1"] n3["열린 반대 방향"] n0 -->|"JGroups 메시지"| n1 - n1 -->|"막혀서 닿지 않는다"| n2 + n1 -->|"차단"| n2 n2 -->|"반대 방향으로 재연결"| n3 diff --git a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.svg b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.svg index 190a689..05a25ac 100644 --- a/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.svg +++ b/docs/keycloak-session-store/final/assets/a5-partition-asymmetry/a5-partition-asymmetry.svg @@ -51,8 +51,8 @@ - -막혀서 닿지 않는다 + +차단 JGroups 메시지 @@ -81,6 +81,6 @@ 열린 반대 방향 -가르지 못한다 +재연결 경로 diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.alt.md b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.alt.md index 945fda3..2ca53e8 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.alt.md +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.alt.md @@ -17,6 +17,6 @@ ## Relationships -- **주입한 지연 → 왕복 횟수만큼 누적:** 왕복마다 더해진다. Evidence: L253–L263. +- **주입한 지연 → 왕복 횟수만큼 누적:** 왕복당 누적. Evidence: L253–L263. - **커넥션 풀 대기 → readiness 실패:** 프로브도 타임아웃. Evidence: L264–L273. -- **왕복 횟수만큼 누적 → 커넥션 풀 대기:** 커넥션 점유가 길어진다. Evidence: L259–L268. +- **왕복 횟수만큼 누적 → 커넥션 풀 대기:** 커넥션 점유. Evidence: L259–L268. diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.d2 b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.d2 index de01ec1..1e228b5 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.d2 +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.d2 @@ -13,6 +13,6 @@ n2: "커넥션 풀 대기" { n3: "readiness 실패" { shape: rectangle } -n0 -> n1: "왕복마다 더해진다" -n1 -> n2: "커넥션 점유가 길어진다" +n0 -> n1: "왕복당 누적" +n1 -> n2: "커넥션 점유" n2 -> n3: "프로브도 타임아웃" diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.dot b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.dot index a4ddbd7..e15d09f 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.dot +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="왕복 횟수만큼 누적", shape=box, style="rounded,filled"]; n2 [label="커넥션 풀 대기", shape=box, style="rounded,filled"]; n3 [label="readiness 실패", shape=box, style="rounded,filled"]; - n0 -> n1 [label="왕복마다 더해진다", style=solid]; - n1 -> n2 [label="커넥션 점유가 길어진다", style=solid]; + n0 -> n1 [label="왕복당 누적", style=solid]; + n1 -> n2 [label="커넥션 점유", style=solid]; n2 -> n3 [label="프로브도 타임아웃", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.drawio b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.drawio index 08580b2..700ac58 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.drawio +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.drawio @@ -17,7 +17,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.excalidraw b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.excalidraw index ff88d78..38692b4 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.excalidraw +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "왕복마다 더해진다", + "text": "왕복당 누적", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "왕복마다 더해진다", + "originalText": "왕복당 누적", "autoResize": true, "lineHeight": 1.25 }, @@ -264,9 +264,9 @@ { "id": "edge-label-r-p", "type": "text", - "x": 122.5, + "x": 125.5, "y": 334.0, - "width": 96, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "커넥션 점유가 길어진다", + "text": "커넥션 점유", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "커넥션 점유가 길어진다", + "originalText": "커넥션 점유", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.manifest.json b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.manifest.json index 325ccaf..4ebfab2 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.manifest.json +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a6-latency-multiplication", "spec_version": "1.1", - "spec_sha256": "c9d669f597dc9b26d68636bb52e7239c266a8c5985c73d51c3fe0b7ebd7ff231", + "spec_sha256": "0b2994cb0a306f6fc1bd7fb2dae907ed79b6fe0bb6e908dba8509b0db1ca9f2b", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.mmd b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.mmd index 5f4aced..7d2fedc 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.mmd +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.mmd @@ -5,6 +5,6 @@ flowchart TB n1["왕복 횟수만큼 누적"] n2["커넥션 풀 대기"] n3["readiness 실패"] - n0 -->|"왕복마다 더해진다"| n1 - n1 -->|"커넥션 점유가 길어진다"| n2 + n0 -->|"왕복당 누적"| n1 + n1 -->|"커넥션 점유"| n2 n2 -->|"프로브도 타임아웃"| n3 diff --git a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.svg b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.svg index fbadbfa..780b3fa 100644 --- a/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.svg +++ b/docs/keycloak-session-store/final/assets/a6-latency-multiplication/a6-latency-multiplication.svg @@ -51,14 +51,14 @@ - -왕복마다 더해진다 + +왕복당 누적 프로브도 타임아웃 - -커넥션 점유가 길어진다 + +커넥션 점유 주입한 지연 diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.alt.md b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.alt.md index 6c617ca..a7792a9 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.alt.md +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.alt.md @@ -17,6 +17,6 @@ ## Relationships -- **PostgreSQL 세션 행 → 재시작 전 발급한 refresh token:** 세션이 남아 있어 통한다. Evidence: L270–L278. -- **롤링 재시작 → Infinispan sessions 캐시:** 비운다. Evidence: L270–L278. -- **롤링 재시작 → PostgreSQL 세션 행:** 건드리지 않는다. Evidence: L270–L278. +- **PostgreSQL 세션 행 → 재시작 전 발급한 refresh token:** 세션 조회. Evidence: L270–L278. +- **롤링 재시작 → Infinispan sessions 캐시:** 캐시 초기화. Evidence: L270–L278. +- **롤링 재시작 → PostgreSQL 세션 행:** 변경 없음. Evidence: L270–L278. diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.d2 b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.d2 index 3d72a52..4bf938d 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.d2 +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.d2 @@ -13,6 +13,6 @@ n2: "PostgreSQL 세션 행" { n3: "재시작 전 발급한 refresh token" { shape: rectangle } -n0 -> n1: "비운다" -n0 -> n2: "건드리지 않는다" -n2 -> n3: "세션이 남아 있어 통한다" +n0 -> n1: "캐시 초기화" +n0 -> n2: "변경 없음" +n2 -> n3: "세션 조회" diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.dot b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.dot index eb201e2..6c1b4d7 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.dot +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="Infinispan sessions 캐시", shape=box, style="rounded,filled"]; n2 [label="PostgreSQL 세션 행", shape=cylinder, style="rounded,filled"]; n3 [label="재시작 전 발급한 refresh token", shape=box, style="rounded,filled"]; - n0 -> n1 [label="비운다", style=solid]; - n0 -> n2 [label="건드리지 않는다", style=solid]; - n2 -> n3 [label="세션이 남아 있어 통한다", style=solid]; + n0 -> n1 [label="캐시 초기화", style=solid]; + n0 -> n2 [label="변경 없음", style=solid]; + n2 -> n3 [label="세션 조회", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.drawio b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.drawio index 06499ab..dd06b14 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.drawio +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.drawio @@ -17,17 +17,17 @@ - + - + - + diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.excalidraw b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.excalidraw index 8cb2582..f35695b 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.excalidraw +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.excalidraw @@ -66,9 +66,9 @@ { "id": "edge-label-db-rt", "type": "text", - "x": 279.0, + "x": 286.0, "y": 332.0, - "width": 104, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "세션이 남아 있어 통한다", + "text": "세션 조회", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션이 남아 있어 통한다", + "originalText": "세션 조회", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "비운다", + "text": "캐시 초기화", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "비운다", + "originalText": "캐시 초기화", "autoResize": true, "lineHeight": 1.25 }, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "건드리지 않는다", + "text": "변경 없음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "건드리지 않는다", + "originalText": "변경 없음", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.manifest.json b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.manifest.json index a701ef2..61a881d 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.manifest.json +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "a8-cache-vs-session", "spec_version": "1.1", - "spec_sha256": "60ae0f0551684a3d013de2a0eca5a41d5edf858f99511c29441388c02f7310c2", + "spec_sha256": "02e971c0aedba252dce01773d7896eb2a751cd8752eb14d643b43e8f96646102", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.mmd b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.mmd index d5dfc18..468eb36 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.mmd +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.mmd @@ -5,6 +5,6 @@ flowchart TB n1["Infinispan sessions 캐시"] n2[("PostgreSQL 세션 행")] n3["재시작 전 발급한 refresh token"] - n0 -->|"비운다"| n1 - n0 -->|"건드리지 않는다"| n2 - n2 -->|"세션이 남아 있어 통한다"| n3 + n0 -->|"캐시 초기화"| n1 + n0 -->|"변경 없음"| n2 + n2 -->|"세션 조회"| n3 diff --git a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.svg b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.svg index 5e44f09..59fda91 100644 --- a/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.svg +++ b/docs/keycloak-session-store/final/assets/a8-cache-vs-session/a8-cache-vs-session.svg @@ -51,14 +51,14 @@ - -세션이 남아 있어 통한다 + +세션 조회 - -비운다 + +캐시 초기화 - -건드리지 않는다 + +변경 없음 롤링 재시작 diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.alt.md b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.alt.md index 6adfc39..d87fef0 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.alt.md +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.alt.md @@ -17,6 +17,6 @@ ## Relationships -- **브라우저 A 세션 → 토큰 행:** principal 이름으로 쓴다. Evidence: L370–L377. -- **브라우저 B 세션 → 토큰 행:** 같은 키로 덮어쓴다. Evidence: L370–L377. -- **토큰 행 → 로그아웃 후 남는 것:** 로그아웃이 정리하지 않는다. Evidence: L378–L384. +- **브라우저 A 세션 → 토큰 행:** principal 이름. Evidence: L370–L377. +- **브라우저 B 세션 → 토큰 행:** 같은 키 · 덮어쓰기. Evidence: L370–L377. +- **토큰 행 → 로그아웃 후 남는 것:** 로그아웃 미정리. Evidence: L378–L384. diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.d2 b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.d2 index 586e729..d7164d6 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.d2 +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.d2 @@ -13,6 +13,6 @@ n2: "토큰 행" { n3: "로그아웃 후 남는 것" { shape: cylinder } -n0 -> n2: "principal 이름으로 쓴다" -n1 -> n2: "같은 키로 덮어쓴다" -n2 -> n3: "로그아웃이 정리하지 않는다" +n0 -> n2: "principal 이름" +n1 -> n2: "같은 키 · 덮어쓰기" +n2 -> n3: "로그아웃 미정리" diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.dot b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.dot index f6c8951..43a995b 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.dot +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="브라우저 B 세션", shape=box, style="rounded,filled"]; n2 [label="토큰 행", shape=cylinder, style="rounded,filled"]; n3 [label="로그아웃 후 남는 것", shape=cylinder, style="rounded,filled"]; - n0 -> n2 [label="principal 이름으로 쓴다", style=solid]; - n1 -> n2 [label="같은 키로 덮어쓴다", style=solid]; - n2 -> n3 [label="로그아웃이 정리하지 않는다", style=solid]; + n0 -> n2 [label="principal 이름", style=solid]; + n1 -> n2 [label="같은 키 · 덮어쓰기", style=solid]; + n2 -> n3 [label="로그아웃 미정리", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.drawio b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.drawio index 8e9cc76..76c4193 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.drawio +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.drawio @@ -17,17 +17,17 @@ - + - + - + diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.excalidraw b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.excalidraw index 9e2481f..d62ece6 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.excalidraw +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.excalidraw @@ -66,9 +66,9 @@ { "id": "edge-label-s1-t", "type": "text", - "x": 125.0, + "x": 145.0, "y": 132.0, - "width": 136, + "width": 96, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "principal 이름으로 쓴다", + "text": "principal 이름", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "principal 이름으로 쓴다", + "originalText": "principal 이름", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "같은 키로 덮어쓴다", + "text": "같은 키 · 덮어쓰기", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "같은 키로 덮어쓴다", + "originalText": "같은 키 · 덮어쓰기", "autoResize": true, "lineHeight": 1.25 }, @@ -264,9 +264,9 @@ { "id": "edge-label-t-l", "type": "text", - "x": 218.0, + "x": 229.0, "y": 353.0, - "width": 112, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "로그아웃이 정리하지 않는다", + "text": "로그아웃 미정리", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "로그아웃이 정리하지 않는다", + "originalText": "로그아웃 미정리", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.manifest.json b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.manifest.json index 81ac1de..321ac3f 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.manifest.json +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "b2-primary-key-overwrite", "spec_version": "1.1", - "spec_sha256": "653f795b5dd9a627e79a865316e22d8d7ca35f86cbdf6e72dea25c631687cadf", + "spec_sha256": "88795858ea78e4c8a0f6fca3a6131c36883a2378246384b83b9d31b636a7b5a4", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.mmd b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.mmd index cfb03da..4104350 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.mmd +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.mmd @@ -5,6 +5,6 @@ flowchart TB n1["브라우저 B 세션"] n2[("토큰 행")] n3[("로그아웃 후 남는 것")] - n0 -->|"principal 이름으로 쓴다"| n2 - n1 -->|"같은 키로 덮어쓴다"| n2 - n2 -->|"로그아웃이 정리하지 않는다"| n3 + n0 -->|"principal 이름"| n2 + n1 -->|"같은 키 · 덮어쓰기"| n2 + n2 -->|"로그아웃 미정리"| n3 diff --git a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.svg b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.svg index 8819824..859ff80 100644 --- a/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.svg +++ b/docs/keycloak-session-store/final/assets/b2-primary-key-overwrite/b2-primary-key-overwrite.svg @@ -51,14 +51,14 @@ - -principal 이름으로 쓴다 + +principal 이름 - -같은 키로 덮어쓴다 + +같은 키 · 덮어쓰기 - -로그아웃이 정리하지 않는다 + +로그아웃 미정리 브라우저 A 세션 diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.alt.md b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.alt.md index 7987acb..0ea32b5 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.alt.md +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.alt.md @@ -18,5 +18,5 @@ revokeRefreshToken 을 켜고 refreshTokenMaxReuse 를 0 으로 둔 상태에서 ## Relationships - **동시 refresh 5건 → 회전 검사:** 동시 도착. Evidence: L369–L377. -- **client session → 이긴 요청의 새 토큰:** 세션이 없으니 못 쓴다. Evidence: L378–L384. +- **client session → 이긴 요청의 새 토큰:** 사용 불가. Evidence: L378–L384. - **회전 검사 → client session:** 경쟁 감지 시 삭제. Evidence: L378–L384. diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.d2 b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.d2 index f149616..18d1c37 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.d2 +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.d2 @@ -15,4 +15,4 @@ n3: "이긴 요청의 새 토큰" { } n0 -> n1: "동시 도착" n1 -> n2: "경쟁 감지 시 삭제" -n2 -> n3: "세션이 없으니 못 쓴다" +n2 -> n3: "사용 불가" diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.dot b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.dot index 7a66d82..13dff69 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.dot +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.dot @@ -8,5 +8,5 @@ digraph techviz { n3 [label="이긴 요청의 새 토큰", shape=box, style="rounded,filled"]; n0 -> n1 [label="동시 도착", style=solid]; n1 -> n2 [label="경쟁 감지 시 삭제", style=solid]; - n2 -> n3 [label="세션이 없으니 못 쓴다", style=solid]; + n2 -> n3 [label="사용 불가", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.drawio b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.drawio index 914790b..1c99e2f 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.drawio +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.drawio @@ -5,8 +5,8 @@ - - + + @@ -22,7 +22,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.excalidraw b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.excalidraw index ae8ac7c..3707667 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.excalidraw +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.excalidraw @@ -165,9 +165,9 @@ { "id": "edge-label-cs-nt", "type": "text", - "x": 196.0, + "x": 199.0, "y": 507.0, - "width": 96, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "세션이 없으니 못 쓴다", + "text": "사용 불가", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션이 없으니 못 쓴다", + "originalText": "사용 불가", "autoResize": true, "lineHeight": 1.25 }, @@ -303,9 +303,9 @@ { "id": "node-concurrent", "type": "rectangle", - "x": 135.0, + "x": 145.0, "y": 60.0, - "width": 170.0, + "width": 150.0, "height": 84.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -333,9 +333,9 @@ { "id": "node-label-concurrent", "type": "text", - "x": 145.0, + "x": 155.0, "y": 70.0, - "width": 150.0, + "width": 130.0, "height": 64.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -361,11 +361,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "동시 refresh 5건\n& 와 wait 이 없으면 재현되지 않는다", + "text": "동시 refresh 5건\n& + wait 필요", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "동시 refresh 5건\n& 와 wait 이 없으면 재현되지 않는다", + "originalText": "동시 refresh 5건\n& + wait 필요", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.manifest.json b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.manifest.json index 7657f7d..20a2539 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.manifest.json +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "b3-rotation-contention", "spec_version": "1.1", - "spec_sha256": "3fbbe8b3528bbcc2ad23e48a820e9ddc6fe6072857bfbe2fa3df0e566fe99162", + "spec_sha256": "31779474e5400d5e719faf81a62da35a657994d952e4e0324a1c76c5d18183e4", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.mmd b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.mmd index 3b8cb08..28352b4 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.mmd +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.mmd @@ -7,6 +7,6 @@ flowchart TB n3["이긴 요청의 새 토큰"] n0 -->|"동시 도착"| n1 n1 -->|"경쟁 감지 시 삭제"| n2 - n2 -->|"세션이 없으니 못 쓴다"| n3 + n2 -->|"사용 불가"| n3 classDef external stroke-dasharray: 6 4 class n0 external diff --git a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.svg b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.svg index 1da6c70..373627e 100644 --- a/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.svg +++ b/docs/keycloak-session-store/final/assets/b3-rotation-contention/b3-rotation-contention.svg @@ -54,8 +54,8 @@ 동시 도착 - -세션이 없으니 못 쓴다 + +사용 불가 경쟁 감지 시 삭제 diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.alt.md b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.alt.md index 04e1a3c..68b8c0c 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.alt.md +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.alt.md @@ -18,5 +18,5 @@ nginx 는 자기가 proxy_set_header 로 설정한 헤더만 덮어쓴다. 설 ## Relationships - **밖에서 보낸 위조 헤더 → nginx:** 위조 헤더. Evidence: L393–L400. -- **nginx → oauth2-proxy:** 지우지 않으면 그대로 지난다. Evidence: L393–L400. +- **nginx → oauth2-proxy:** 미삭제 시 통과. Evidence: L393–L400. - **oauth2-proxy → 앱:** 인가 헤더. Evidence: L393–L408. diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.d2 b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.d2 index 226bc05..4802b4f 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.d2 +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.d2 @@ -14,5 +14,5 @@ n3: "앱" { shape: rectangle } n0 -> n1: "위조 헤더" -n1 -> n2: "지우지 않으면 그대로 지난다" +n1 -> n2: "미삭제 시 통과" n2 -> n3: "인가 헤더" diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.dot b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.dot index c3f3b86..98caebb 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.dot +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.dot @@ -7,6 +7,6 @@ digraph techviz { n2 [label="oauth2-proxy", shape=diamond, style="rounded,filled"]; n3 [label="앱", shape=box, style="rounded,filled"]; n0 -> n1 [label="위조 헤더", style=solid]; - n1 -> n2 [label="지우지 않으면 그대로 지난다", style=solid]; + n1 -> n2 [label="미삭제 시 통과", style=solid]; n2 -> n3 [label="인가 헤더", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.drawio b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.drawio index e6d18c6..57191fa 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.drawio +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.drawio @@ -6,30 +6,30 @@ - + - - + + - + - - + + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.excalidraw b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.excalidraw index 5ed7840..05f6e11 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.excalidraw +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.excalidraw @@ -6,7 +6,7 @@ { "id": "edge-a-n", "type": "arrow", - "x": 209.5, + "x": 167.5, "y": 144.0, "width": 0.0, "height": 96.0, @@ -66,7 +66,7 @@ { "id": "edge-label-a-n", "type": "text", - "x": 188.5, + "x": 146.5, "y": 180.0, "width": 90, "height": 24, @@ -105,7 +105,7 @@ { "id": "edge-n-p", "type": "arrow", - "x": 209.5, + "x": 167.5, "y": 311.0, "width": 0.0, "height": 96.0, @@ -165,9 +165,9 @@ { "id": "edge-label-n-p", "type": "text", - "x": 173.5, + "x": 146.5, "y": 347.0, - "width": 120, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,18 +193,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "지우지 않으면 그대로 지난다", + "text": "미삭제 시 통과", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "지우지 않으면 그대로 지난다", + "originalText": "미삭제 시 통과", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-p-a", "type": "arrow", - "x": 209.5, + "x": 167.5, "y": 478.0, "width": 0.0, "height": 96.0, @@ -264,7 +264,7 @@ { "id": "edge-label-p-a", "type": "text", - "x": 188.5, + "x": 146.5, "y": 514.0, "width": 90, "height": 24, @@ -303,7 +303,7 @@ { "id": "node-attacker", "type": "rectangle", - "x": 124.5, + "x": 82.5, "y": 60.0, "width": 170.0, "height": 84.0, @@ -333,7 +333,7 @@ { "id": "node-label-attacker", "type": "text", - "x": 134.5, + "x": 92.5, "y": 70.0, "width": 150.0, "height": 64.0, @@ -374,7 +374,7 @@ "type": "rectangle", "x": 70.0, "y": 240.0, - "width": 279.0, + "width": 195.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -404,7 +404,7 @@ "type": "text", "x": 80.0, "y": 250.0, - "width": 259.0, + "width": 175.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,18 +430,18 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "nginx\nproxy_set_header ... \"\" 로 먼저 지워야 한다", + "text": "nginx\nproxy_set_header ... \"\"", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "nginx\nproxy_set_header ... \"\" 로 먼저 지워야 한다", + "originalText": "nginx\nproxy_set_header ... \"\"", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-proxy", "type": "rectangle", - "x": 129.5, + "x": 87.5, "y": 407.0, "width": 160.0, "height": 71.0, @@ -471,7 +471,7 @@ { "id": "node-label-proxy", "type": "text", - "x": 139.5, + "x": 97.5, "y": 417.0, "width": 140.0, "height": 51.0, @@ -510,7 +510,7 @@ { "id": "node-app", "type": "rectangle", - "x": 134.5, + "x": 92.5, "y": 574.0, "width": 150.0, "height": 71.0, @@ -540,7 +540,7 @@ { "id": "node-label-app", "type": "text", - "x": 144.5, + "x": 102.5, "y": 584.0, "width": 130.0, "height": 51.0, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "앱\n세션은 로그인 시점의 스냅샷", + "text": "앱\n로그인 시점 스냅샷", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "앱\n세션은 로그인 시점의 스냅샷", + "originalText": "앱\n로그인 시점 스냅샷", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.manifest.json b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.manifest.json index 70d4162..4386b1c 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.manifest.json +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "b4-header-trust-boundary", "spec_version": "1.1", - "spec_sha256": "9ae5cf39dfc20e31d81b892ae7483d2b9ccf94fa2c91a03837200b463bfc1103", + "spec_sha256": "56747d5f7826ad63f202d8dc4d6a4f1323f12eeaedb4bf989b67d0bfab5f09cd", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.mmd b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.mmd index 5a87f87..818572c 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.mmd +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.mmd @@ -6,7 +6,7 @@ flowchart TB n2{"oauth2-proxy"} n3["앱"] n0 -->|"위조 헤더"| n1 - n1 -->|"지우지 않으면 그대로 지난다"| n2 + n1 -->|"미삭제 시 통과"| n2 n2 -->|"인가 헤더"| n3 classDef external stroke-dasharray: 6 4 class n0 external diff --git a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.svg b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.svg index 75aba82..86eb0b5 100644 --- a/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.svg +++ b/docs/keycloak-session-store/final/assets/b4-header-trust-boundary/b4-header-trust-boundary.svg @@ -50,35 +50,35 @@ - - -위조 헤더 - - -지우지 않으면 그대로 지난다 - - -인가 헤더 + + +위조 헤더 + + +미삭제 시 통과 + + +인가 헤더 - -밖에서 보낸 위조 헤더 + +밖에서 보낸 위조 헤더 - -nginx - -proxy_set_header ... "" 로 먼저 지워야 한다 + +nginx + +proxy_set_header ... "" - -oauth2-proxy - ---set-xauthrequest + +oauth2-proxy + +--set-xauthrequest - - - -세션은 로그인 시점의 스냅샷 + + + +로그인 시점 스냅샷 diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.alt.md b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.alt.md index cafc78c..404e4d0 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.alt.md +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.alt.md @@ -17,6 +17,6 @@ redis-cli config set appendonly yes 를 켜도 아무것도 달라지지 않았 ## Relationships -- **appendonly yes → /data:** AOF 파일을 쓴다. Evidence: L406–L412. -- **/data → 컨테이너:** 컨테이너와 함께 죽는다. Evidence: L406–L412. -- **/data → PersistentVolume:** 볼륨을 붙여야 남는다. Evidence: L406–L412. +- **appendonly yes → /data:** AOF 기록. Evidence: L406–L412. +- **/data → 컨테이너:** 컨테이너와 함께 소멸. Evidence: L406–L412. +- **/data → PersistentVolume:** 볼륨 마운트. Evidence: L406–L412. diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.d2 b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.d2 index 0c75e06..3b40383 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.d2 +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.d2 @@ -13,6 +13,6 @@ n2: "컨테이너" { n3: "PersistentVolume" { shape: cylinder } -n0 -> n1: "AOF 파일을 쓴다" -n1 -> n2: "컨테이너와 함께 죽는다" -n1 -> n3: "볼륨을 붙여야 남는다" +n0 -> n1: "AOF 기록" +n1 -> n2: "컨테이너와 함께 소멸" +n1 -> n3: "볼륨 마운트" diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.dot b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.dot index 6722dff..178aa12 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.dot +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="/data", shape=cylinder, style="rounded,filled"]; n2 [label="컨테이너", shape=box, style="rounded,filled"]; n3 [label="PersistentVolume", shape=cylinder, style="rounded,filled"]; - n0 -> n1 [label="AOF 파일을 쓴다", style=solid]; - n1 -> n2 [label="컨테이너와 함께 죽는다", style=solid]; - n1 -> n3 [label="볼륨을 붙여야 남는다", style=solid]; + n0 -> n1 [label="AOF 기록", style=solid]; + n1 -> n2 [label="컨테이너와 함께 소멸", style=solid]; + n1 -> n3 [label="볼륨 마운트", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.drawio b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.drawio index 232a347..f535cae 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.drawio +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.drawio @@ -8,26 +8,26 @@ - - + + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.excalidraw b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.excalidraw index 1473476..cda1d92 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.excalidraw +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "AOF 파일을 쓴다", + "text": "AOF 기록", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "AOF 파일을 쓴다", + "originalText": "AOF 기록", "autoResize": true, "lineHeight": 1.25 }, @@ -165,9 +165,9 @@ { "id": "edge-label-d-c", "type": "text", - "x": 145.0, + "x": 148.0, "y": 336.75, - "width": 96, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "컨테이너와 함께 죽는다", + "text": "컨테이너와 함께 소멸", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "컨테이너와 함께 죽는다", + "originalText": "컨테이너와 함께 소멸", "autoResize": true, "lineHeight": 1.25 }, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "볼륨을 붙여야 남는다", + "text": "볼륨 마운트", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "볼륨을 붙여야 남는다", + "originalText": "볼륨 마운트", "autoResize": true, "lineHeight": 1.25 }, @@ -372,9 +372,9 @@ { "id": "node-datadir", "type": "rectangle", - "x": 142.0, + "x": 175.0, "y": 227.0, - "width": 216.0, + "width": 150.0, "height": 97.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -402,9 +402,9 @@ { "id": "node-label-datadir", "type": "text", - "x": 152.0, + "x": 185.0, "y": 237.0, - "width": 196.0, + "width": 130.0, "height": 77.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "/data\nappendonlydir 이 만들어졌다 버려진다", + "text": "/data\nappendonlydir", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "/data\nappendonlydir 이 만들어졌다 버려진다", + "originalText": "/data\nappendonlydir", "autoResize": true, "lineHeight": 1.25 }, @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "컨테이너\n볼륨이 없으면 여기까지다", + "text": "컨테이너\n볼륨 없음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "컨테이너\n볼륨이 없으면 여기까지다", + "originalText": "컨테이너\n볼륨 없음", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.manifest.json b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.manifest.json index 3d560f2..d81ddae 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.manifest.json +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "b5-b6-storage-and-keys", "spec_version": "1.1", - "spec_sha256": "51b618881bf3ef23a734b2beb319e756c12a9a7ff1ae578b7b5ef78a1461b0e9", + "spec_sha256": "6be204030cc95c5d9aec2ec4f07eae62bd88e7f344d00c2e014a20e18d6f8dba", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.mmd b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.mmd index 21e9e19..81678e8 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.mmd +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.mmd @@ -5,6 +5,6 @@ flowchart TB n1[("/data")] n2["컨테이너"] n3[("PersistentVolume")] - n0 -->|"AOF 파일을 쓴다"| n1 - n1 -->|"컨테이너와 함께 죽는다"| n2 - n1 -->|"볼륨을 붙여야 남는다"| n3 + n0 -->|"AOF 기록"| n1 + n1 -->|"컨테이너와 함께 소멸"| n2 + n1 -->|"볼륨 마운트"| n3 diff --git a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.svg b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.svg index edda6dd..78efc76 100644 --- a/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.svg +++ b/docs/keycloak-session-store/final/assets/b5-b6-storage-and-keys/b5-b6-storage-and-keys.svg @@ -51,14 +51,14 @@ - -AOF 파일을 쓴다 + +AOF 기록 - -컨테이너와 함께 죽는다 + +컨테이너와 함께 소멸 - -볼륨을 붙여야 남는다 + +볼륨 마운트 appendonly yes @@ -66,16 +66,16 @@ redis-cli config set - + /data - -appendonlydir 이 만들어졌다 버려진다 + +appendonlydir 컨테이너 -볼륨이 없으면 여기까지다 +볼륨 없음 diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.alt.md b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.alt.md index 26de907..bd13d8e 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.alt.md +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.alt.md @@ -17,6 +17,6 @@ oauth2-proxy 는 세션 전체를 쿠키에 담고 replica 는 같은 k8s Secret ## Relationships -- **Redis 의 세션 → TTL:** 생성 시각이 여기 남는다. Evidence: L441–L452. -- **k8s Secret → 쿠키의 티켓:** 티켓을 암호화한다. Evidence: L419–L432. -- **쿠키의 티켓 → Redis 의 세션:** 키 이름을 만든다. Evidence: L429–L438. +- **Redis 의 세션 → TTL:** 생성 시각. Evidence: L441–L452. +- **k8s Secret → 쿠키의 티켓:** 티켓 암호화. Evidence: L419–L432. +- **쿠키의 티켓 → Redis 의 세션:** 키 이름 생성. Evidence: L429–L438. diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.d2 b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.d2 index 164818b..e2e5501 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.d2 +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.d2 @@ -13,6 +13,6 @@ n2: "Redis 의 세션" { n3: "TTL" { shape: rectangle } -n0 -> n1: "티켓을 암호화한다" -n1 -> n2: "키 이름을 만든다" -n2 -> n3: "생성 시각이 여기 남는다" +n0 -> n1: "티켓 암호화" +n1 -> n2: "키 이름 생성" +n2 -> n3: "생성 시각" diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.dot b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.dot index 107e1ce..ed5a6f6 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.dot +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="쿠키의 티켓", shape=box, style="rounded,filled"]; n2 [label="Redis 의 세션", shape=cylinder, style="rounded,filled"]; n3 [label="TTL", shape=box, style="rounded,filled"]; - n0 -> n1 [label="티켓을 암호화한다", style=solid]; - n1 -> n2 [label="키 이름을 만든다", style=solid]; - n2 -> n3 [label="생성 시각이 여기 남는다", style=solid]; + n0 -> n1 [label="티켓 암호화", style=solid]; + n1 -> n2 [label="키 이름 생성", style=solid]; + n2 -> n3 [label="생성 시각", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.drawio b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.drawio index 356e9db..982e99c 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.drawio +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.drawio @@ -8,26 +8,26 @@ - - + + - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.excalidraw b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.excalidraw index ed89f2c..43a1d74 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.excalidraw +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.excalidraw @@ -66,9 +66,9 @@ { "id": "edge-label-r-ttl", "type": "text", - "x": 129.0, + "x": 136.0, "y": 553.0, - "width": 104, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "생성 시각이 여기 남는다", + "text": "생성 시각", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "생성 시각이 여기 남는다", + "originalText": "생성 시각", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "티켓을 암호화한다", + "text": "티켓 암호화", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "티켓을 암호화한다", + "originalText": "티켓 암호화", "autoResize": true, "lineHeight": 1.25 }, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "키 이름을 만든다", + "text": "키 이름 생성", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "키 이름을 만든다", + "originalText": "키 이름 생성", "autoResize": true, "lineHeight": 1.25 }, @@ -372,9 +372,9 @@ { "id": "node-ticket", "type": "rectangle", - "x": 80.5, + "x": 77.0, "y": 253.0, - "width": 153.0, + "width": 160.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -402,9 +402,9 @@ { "id": "node-label-ticket", "type": "text", - "x": 90.5, + "x": 87.0, "y": 263.0, - "width": 133.0, + "width": 140.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "쿠키의 티켓\nsecret 을 바꾸면 못 푼다", + "text": "쿠키의 티켓\nsecret 교체 시 복호화 불가", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "쿠키의 티켓\nsecret 을 바꾸면 못 푼다", + "originalText": "쿠키의 티켓\nsecret 교체 시 복호화 불가", "autoResize": true, "lineHeight": 1.25 }, @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "Redis 의 세션\n고아로 남는다", + "text": "Redis 의 세션\n고아 세션", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "Redis 의 세션\n고아로 남는다", + "originalText": "Redis 의 세션\n고아 세션", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "TTL\n역산으로 고아를 고른다", + "text": "TTL\n생성 시각 역산", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "TTL\n역산으로 고아를 고른다", + "originalText": "TTL\n생성 시각 역산", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.manifest.json b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.manifest.json index c7154f0..75d5f58 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.manifest.json +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "b7-cookie-session-tradeoff", "spec_version": "1.1", - "spec_sha256": "ae4774e0d8dfda387902c00a5d3c933672d4adf799cd6774760a74b8a1ad376a", + "spec_sha256": "9a594212157672a9188e296e73a0ab9af3d53992c94afdbfe2e1aeedaf8998bc", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.mmd b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.mmd index 95eb34c..54cd3ed 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.mmd +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.mmd @@ -5,6 +5,6 @@ flowchart TB n1["쿠키의 티켓"] n2[("Redis 의 세션")] n3["TTL"] - n0 -->|"티켓을 암호화한다"| n1 - n1 -->|"키 이름을 만든다"| n2 - n2 -->|"생성 시각이 여기 남는다"| n3 + n0 -->|"티켓 암호화"| n1 + n1 -->|"키 이름 생성"| n2 + n2 -->|"생성 시각"| n3 diff --git a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.svg b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.svg index 4f31f51..e4c5f10 100644 --- a/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.svg +++ b/docs/keycloak-session-store/final/assets/b7-cookie-session-tradeoff/b7-cookie-session-tradeoff.svg @@ -51,14 +51,14 @@ - -생성 시각이 여기 남는다 + +생성 시각 - -티켓을 암호화한다 + +티켓 암호화 - -키 이름을 만든다 + +키 이름 생성 k8s Secret @@ -66,21 +66,21 @@ --cookie-secret 은 단수 - + 쿠키의 티켓 - -secret 을 바꾸면 못 푼다 + +secret 교체 시 복호화 불가 Redis 의 세션 -고아로 남는다 +고아 세션 TTL -역산으로 고아를 고른다 +생성 시각 역산 diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.alt.md b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.alt.md index b8164a6..cb0bc5e 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.alt.md +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.alt.md @@ -17,6 +17,6 @@ C-1 에서 로그아웃이 다른 앱으로 퍼지지 않는 것을 관측했고 ## Relationships -- **backchannelLogoutUrl → 앱의 수신 엔드포인트:** 주소가 있어야 부른다. Evidence: L458–L466. -- **앱의 수신 엔드포인트 → 다른 앱의 세션:** 받을 곳이 있어야 지운다. Evidence: L458–L466. -- **한 앱에서 로그아웃 → backchannelLogoutUrl:** 통지할 주소를 찾는다. Evidence: L458–L466. +- **backchannelLogoutUrl → 앱의 수신 엔드포인트:** 호출 (주소 필요). Evidence: L458–L466. +- **앱의 수신 엔드포인트 → 다른 앱의 세션:** 세션 삭제 (엔드포인트 필요). Evidence: L458–L466. +- **한 앱에서 로그아웃 → backchannelLogoutUrl:** 통지 주소 조회. Evidence: L458–L466. diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.d2 b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.d2 index 270e336..72d22f7 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.d2 +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.d2 @@ -13,6 +13,6 @@ n2: "앱의 수신 엔드포인트" { n3: "다른 앱의 세션" { shape: rectangle } -n0 -> n1: "통지할 주소를 찾는다" -n1 -> n2: "주소가 있어야 부른다" -n2 -> n3: "받을 곳이 있어야 지운다" +n0 -> n1: "통지 주소 조회" +n1 -> n2: "호출 (주소 필요)" +n2 -> n3: "세션 삭제 (엔드포인트 필요)" diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.dot b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.dot index 816422d..2faaa0e 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.dot +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="backchannelLogoutUrl", shape=box, style="rounded,filled"]; n2 [label="앱의 수신 엔드포인트", shape=box, style="rounded,filled"]; n3 [label="다른 앱의 세션", shape=box, style="rounded,filled"]; - n0 -> n1 [label="통지할 주소를 찾는다", style=solid]; - n1 -> n2 [label="주소가 있어야 부른다", style=solid]; - n2 -> n3 [label="받을 곳이 있어야 지운다", style=solid]; + n0 -> n1 [label="통지 주소 조회", style=solid]; + n1 -> n2 [label="호출 (주소 필요)", style=solid]; + n2 -> n3 [label="세션 삭제 (엔드포인트 필요)", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.drawio b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.drawio index 84bd66b..817b7e2 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.drawio +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.drawio @@ -6,30 +6,30 @@ - + - - + + - + - - + + - + - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.excalidraw b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.excalidraw index 5c38cca..c14f8e7 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.excalidraw +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.excalidraw @@ -6,7 +6,7 @@ { "id": "edge-c-e", "type": "arrow", - "x": 160.5, + "x": 157.0, "y": 311.0, "width": 0.0, "height": 96.0, @@ -66,7 +66,7 @@ { "id": "edge-label-c-e", "type": "text", - "x": 139.5, + "x": 136.0, "y": 347.0, "width": 90, "height": 24, @@ -94,18 +94,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "주소가 있어야 부른다", + "text": "호출 (주소 필요)", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "주소가 있어야 부른다", + "originalText": "호출 (주소 필요)", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-e-s", "type": "arrow", - "x": 160.5, + "x": 157.0, "y": 478.0, "width": 0.0, "height": 96.0, @@ -165,9 +165,9 @@ { "id": "edge-label-e-s", "type": "text", - "x": 132.5, + "x": 117.0, "y": 514.0, - "width": 104, + "width": 128, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,18 +193,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "받을 곳이 있어야 지운다", + "text": "세션 삭제 (엔드포인트 필요)", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "받을 곳이 있어야 지운다", + "originalText": "세션 삭제 (엔드포인트 필요)", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-l-c", "type": "arrow", - "x": 160.5, + "x": 157.0, "y": 144.0, "width": 0.0, "height": 96.0, @@ -264,7 +264,7 @@ { "id": "edge-label-l-c", "type": "text", - "x": 139.5, + "x": 136.0, "y": 180.0, "width": 90, "height": 24, @@ -292,18 +292,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "통지할 주소를 찾는다", + "text": "통지 주소 조회", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "통지할 주소를 찾는다", + "originalText": "통지 주소 조회", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-logout", "type": "rectangle", - "x": 85.5, + "x": 82.0, "y": 60.0, "width": 150.0, "height": 84.0, @@ -333,7 +333,7 @@ { "id": "node-label-logout", "type": "text", - "x": 95.5, + "x": 92.0, "y": 70.0, "width": 130.0, "height": 64.0, @@ -374,7 +374,7 @@ "type": "rectangle", "x": 70.0, "y": 240.0, - "width": 181.0, + "width": 174.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -404,7 +404,7 @@ "type": "text", "x": 80.0, "y": 250.0, - "width": 161.0, + "width": 154.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,18 +430,18 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "backchannelLogoutUrl\nKeycloak 은 부를 주소를 모른다", + "text": "backchannelLogoutUrl\n주소 없음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "backchannelLogoutUrl\nKeycloak 은 부를 주소를 모른다", + "originalText": "backchannelLogoutUrl\n주소 없음", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-app-endpoint", "type": "rectangle", - "x": 85.5, + "x": 82.0, "y": 407.0, "width": 150.0, "height": 71.0, @@ -471,7 +471,7 @@ { "id": "node-label-app-endpoint", "type": "text", - "x": 95.5, + "x": 92.0, "y": 417.0, "width": 130.0, "height": 51.0, @@ -510,7 +510,7 @@ { "id": "node-app-session", "type": "rectangle", - "x": 85.5, + "x": 82.0, "y": 574.0, "width": 150.0, "height": 71.0, @@ -540,7 +540,7 @@ { "id": "node-label-app-session", "type": "text", - "x": 95.5, + "x": 92.0, "y": 584.0, "width": 130.0, "height": 51.0, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "다른 앱의 세션\n네트워크는 200 으로 닿는다", + "text": "다른 앱의 세션\n네트워크 도달 200", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "다른 앱의 세션\n네트워크는 200 으로 닿는다", + "originalText": "다른 앱의 세션\n네트워크 도달 200", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.manifest.json b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.manifest.json index ee1af25..418a101 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.manifest.json +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "c2-backchannel-both-sides", "spec_version": "1.1", - "spec_sha256": "43396622cbf01d243efac1f48396163cc64738ef902bddda0ded0d9fb6467eb1", + "spec_sha256": "dd700a72a2ec7d5427681b95610e9715385241a81c78e2e9dce2aafdee32b35c", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.mmd b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.mmd index 30a6aa4..42984fd 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.mmd +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.mmd @@ -5,8 +5,8 @@ flowchart TB n1["backchannelLogoutUrl"] n2["앱의 수신 엔드포인트"] n3["다른 앱의 세션"] - n0 -->|"통지할 주소를 찾는다"| n1 - n1 -->|"주소가 있어야 부른다"| n2 - n2 -->|"받을 곳이 있어야 지운다"| n3 + n0 -->|"통지 주소 조회"| n1 + n1 -->|"호출 (주소 필요)"| n2 + n2 -->|"세션 삭제 (엔드포인트 필요)"| n3 classDef external stroke-dasharray: 6 4 class n0 external diff --git a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.svg b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.svg index 2395b35..4492142 100644 --- a/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.svg +++ b/docs/keycloak-session-store/final/assets/c2-backchannel-both-sides/c2-backchannel-both-sides.svg @@ -50,35 +50,35 @@ - - -주소가 있어야 부른다 - - -받을 곳이 있어야 지운다 - - -통지할 주소를 찾는다 + + +호출 (주소 필요) + + +세션 삭제 (엔드포인트 필요) + + +통지 주소 조회 - -한 앱에서 로그아웃 + +한 앱에서 로그아웃 - -backchannelLogoutUrl - -Keycloak 은 부를 주소를 모른다 + +backchannelLogoutUrl + +주소 없음 - -앱의 수신 엔드포인트 - -oidcLogout 설정 없음 + +앱의 수신 엔드포인트 + +oidcLogout 설정 없음 - -다른 앱의 세션 - -네트워크는 200 으로 닿는다 + +다른 앱의 세션 + +네트워크 도달 200 diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.alt.md b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.alt.md index 95debb6..285f0f1 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.alt.md +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.alt.md @@ -17,6 +17,6 @@ volatile 모드에서 로그인은 SQL 을 0개 쏜다. refresh 는 딱 한 문 ## Relationships -- **CLIENT 조회 → CLIENT_SCOPE_CLIENT 조회:** refresh 는 스코프도 다시 계산한다. Evidence: L284–L292. +- **CLIENT 조회 → CLIENT_SCOPE_CLIENT 조회:** 스코프 재계산. Evidence: L284–L292. - **로그인 · refresh 요청 → CLIENT 조회:** 클라이언트 확인. Evidence: L306–L312. -- **CLIENT_SCOPE_CLIENT 조회 → PostgreSQL:** 캐시에 없으면 여기까지 간다. Evidence: L296–L302. +- **CLIENT_SCOPE_CLIENT 조회 → PostgreSQL:** 캐시 미스. Evidence: L296–L302. diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.d2 b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.d2 index 4acd88a..1adc86d 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.d2 +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.d2 @@ -14,5 +14,5 @@ n3: "PostgreSQL" { shape: cylinder } n0 -> n1: "클라이언트 확인" -n1 -> n2: "refresh 는 스코프도 다시 계산한다" -n2 -> n3: "캐시에 없으면 여기까지 간다" +n1 -> n2: "스코프 재계산" +n2 -> n3: "캐시 미스" diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.dot b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.dot index 89df6bb..ba436c5 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.dot +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.dot @@ -7,6 +7,6 @@ digraph techviz { n2 [label="CLIENT_SCOPE_CLIENT 조회", shape=box, style="rounded,filled"]; n3 [label="PostgreSQL", shape=cylinder, style="rounded,filled"]; n0 -> n1 [label="클라이언트 확인", style=solid]; - n1 -> n2 [label="refresh 는 스코프도 다시 계산한다", style=solid]; - n2 -> n3 [label="캐시에 없으면 여기까지 간다", style=solid]; + n1 -> n2 [label="스코프 재계산", style=solid]; + n2 -> n3 [label="캐시 미스", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.drawio b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.drawio index 7b4a48f..d7c492d 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.drawio +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.drawio @@ -11,13 +11,13 @@ - - + + - + - + @@ -27,7 +27,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.excalidraw b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.excalidraw index abea2c1..b7efa80 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.excalidraw +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.excalidraw @@ -66,9 +66,9 @@ { "id": "edge-label-c-s", "type": "text", - "x": 117.5, + "x": 160.5, "y": 347.0, - "width": 176, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "refresh 는 스코프도 다시 계산한다", + "text": "스코프 재계산", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "refresh 는 스코프도 다시 계산한다", + "originalText": "스코프 재계산", "autoResize": true, "lineHeight": 1.25 }, @@ -264,9 +264,9 @@ { "id": "edge-label-s-db", "type": "text", - "x": 145.5, + "x": 160.5, "y": 514.0, - "width": 120, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "캐시에 없으면 여기까지 간다", + "text": "캐시 미스", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "캐시에 없으면 여기까지 간다", + "originalText": "캐시 미스", "autoResize": true, "lineHeight": 1.25 }, @@ -441,9 +441,9 @@ { "id": "node-scope-lookup", "type": "rectangle", - "x": 70.0, + "x": 87.5, "y": 407.0, - "width": 223.0, + "width": 188.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -471,9 +471,9 @@ { "id": "node-label-scope-lookup", "type": "text", - "x": 80.0, + "x": 97.5, "y": 417.0, - "width": 203.0, + "width": 168.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "CLIENT_SCOPE_CLIENT 조회\nDEFAULT_SCOPE='f' — 선택적 스코프", + "text": "CLIENT_SCOPE_CLIENT 조회\nDEFAULT_SCOPE='f'", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "CLIENT_SCOPE_CLIENT 조회\nDEFAULT_SCOPE='f' — 선택적 스코프", + "originalText": "CLIENT_SCOPE_CLIENT 조회\nDEFAULT_SCOPE='f'", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "PostgreSQL\n캐시에 있으면 닿지 않는다", + "text": "PostgreSQL\n캐시 미스 시에만 도달", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "PostgreSQL\n캐시에 있으면 닿지 않는다", + "originalText": "PostgreSQL\n캐시 미스 시에만 도달", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.manifest.json b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.manifest.json index 909466a..33ec5ec 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.manifest.json +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "cache-temperature-outcomes", "spec_version": "1.1", - "spec_sha256": "d29d1507f8c0801290e71152181fc3427617ae85cd3f1d72493352841cb60224", + "spec_sha256": "ef12517d7e1783c23b34a19ae285946eaf73ec600e5487c5d9bca1c086e0c22d", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.mmd b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.mmd index eca7b33..b1ce306 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.mmd +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.mmd @@ -6,7 +6,7 @@ flowchart TB n2["CLIENT_SCOPE_CLIENT 조회"] n3[("PostgreSQL")] n0 -->|"클라이언트 확인"| n1 - n1 -->|"refresh 는 스코프도 다시 계산한다"| n2 - n2 -->|"캐시에 없으면 여기까지 간다"| n3 + n1 -->|"스코프 재계산"| n2 + n2 -->|"캐시 미스"| n3 classDef external stroke-dasharray: 6 4 class n0 external diff --git a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.svg b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.svg index e05f725..ca49b8d 100644 --- a/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.svg +++ b/docs/keycloak-session-store/final/assets/cache-temperature-outcomes/cache-temperature-outcomes.svg @@ -51,14 +51,14 @@ - -refresh 는 스코프도 다시 계산한다 + +스코프 재계산 클라이언트 확인 - -캐시에 없으면 여기까지 간다 + +캐시 미스 로그인 · refresh 요청 @@ -70,15 +70,15 @@ select ce1_0.ID from CLIENT - + CLIENT_SCOPE_CLIENT 조회 - -DEFAULT_SCOPE='f' — 선택적 스코프 + +DEFAULT_SCOPE='f' PostgreSQL -캐시에 있으면 닿지 않는다 +캐시 미스 시에만 도달 diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.alt.md b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.alt.md index 1d758c7..bcba7e3 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.alt.md +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.alt.md @@ -18,7 +18,7 @@ ## Relationships -- **Liquibase 검증 → databasechangelog 행 수:** 무엇을 보고 판단하나. Evidence: L499–L505. -- **Liquibase 검증 → StatefulSet 롤링 업데이트:** 실패가 여기서 멈춘다. Evidence: L492–L497. +- **Liquibase 검증 → databasechangelog 행 수:** 판단 기준. Evidence: L499–L505. +- **Liquibase 검증 → StatefulSet 롤링 업데이트:** 중단 지점. Evidence: L492–L497. - **옛 버전으로 되돌리기 → Liquibase 검증:** 기동 시 검증. Evidence: L483–L491. -- **StatefulSet 롤링 업데이트 → 외부 서비스:** 남은 파드가 응답한다. Evidence: L492–L498. +- **StatefulSet 롤링 업데이트 → 외부 서비스:** 잔여 파드 응답. Evidence: L492–L498. diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.d2 b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.d2 index 242c0e7..92f64cc 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.d2 +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.d2 @@ -17,6 +17,6 @@ n4: "databasechangelog 행 수" { shape: cylinder } n0 -> n1: "기동 시 검증" -n1 -> n2: "실패가 여기서 멈춘다" -n2 -> n3: "남은 파드가 응답한다" -n1 -> n4: "무엇을 보고 판단하나" +n1 -> n2: "중단 지점" +n2 -> n3: "잔여 파드 응답" +n1 -> n4: "판단 기준" diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.dot b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.dot index 3d8332a..2433b59 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.dot +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.dot @@ -8,7 +8,7 @@ digraph techviz { n3 [label="외부 서비스", shape=box, style="rounded,filled"]; n4 [label="databasechangelog 행 수", shape=cylinder, style="rounded,filled"]; n0 -> n1 [label="기동 시 검증", style=solid]; - n1 -> n2 [label="실패가 여기서 멈춘다", style=solid]; - n2 -> n3 [label="남은 파드가 응답한다", style=solid]; - n1 -> n4 [label="무엇을 보고 판단하나", style=solid]; + n1 -> n2 [label="중단 지점", style=solid]; + n2 -> n3 [label="잔여 파드 응답", style=solid]; + n1 -> n4 [label="판단 기준", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.drawio b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.drawio index 1107a6a..a00cbe1 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.drawio +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.drawio @@ -11,21 +11,21 @@ - + - + - + - + @@ -35,7 +35,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.excalidraw b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.excalidraw index a076928..7fab663 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.excalidraw +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "무엇을 보고 판단하나", + "text": "판단 기준", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "무엇을 보고 판단하나", + "originalText": "판단 기준", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "실패가 여기서 멈춘다", + "text": "중단 지점", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "실패가 여기서 멈춘다", + "originalText": "중단 지점", "autoResize": true, "lineHeight": 1.25 }, @@ -391,11 +391,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "남은 파드가 응답한다", + "text": "잔여 파드 응답", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "남은 파드가 응답한다", + "originalText": "잔여 파드 응답", "autoResize": true, "lineHeight": 1.25 }, @@ -598,11 +598,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "databasechangelog 행 수\n늘었으면 스키마가 움직였다", + "text": "databasechangelog 행 수\n전후 행 수 비교", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "databasechangelog 행 수\n늘었으면 스키마가 움직였다", + "originalText": "databasechangelog 행 수\n전후 행 수 비교", "autoResize": true, "lineHeight": 1.25 }, @@ -667,11 +667,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "StatefulSet 롤링 업데이트\n나머지 파드는 건드리지 않는다", + "text": "StatefulSet 롤링 업데이트\n나머지 파드 유지", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "StatefulSet 롤링 업데이트\n나머지 파드는 건드리지 않는다", + "originalText": "StatefulSet 롤링 업데이트\n나머지 파드 유지", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.manifest.json b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.manifest.json index 9a1c8d1..5d96584 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.manifest.json +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "d2-upgrade-direction", "spec_version": "1.1", - "spec_sha256": "30ae7b783f6b33d4364a113637e61b09cbf87be39bac08a41b49f134f2a845be", + "spec_sha256": "7f7090d0f9f237909f548d3f67104bb98dba10e94b63ca7e6e0c684d92afe199", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.mmd b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.mmd index 007f85b..0bef4e5 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.mmd +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.mmd @@ -7,6 +7,6 @@ flowchart TB n3["외부 서비스"] n4[("databasechangelog 행 수")] n0 -->|"기동 시 검증"| n1 - n1 -->|"실패가 여기서 멈춘다"| n2 - n2 -->|"남은 파드가 응답한다"| n3 - n1 -->|"무엇을 보고 판단하나"| n4 + n1 -->|"중단 지점"| n2 + n2 -->|"잔여 파드 응답"| n3 + n1 -->|"판단 기준"| n4 diff --git a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.svg b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.svg index 1946ff7..9db5e64 100644 --- a/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.svg +++ b/docs/keycloak-session-store/final/assets/d2-upgrade-direction/d2-upgrade-direction.svg @@ -51,17 +51,17 @@ - -무엇을 보고 판단하나 + +판단 기준 - -실패가 여기서 멈춘다 + +중단 지점 기동 시 검증 - -남은 파드가 응답한다 + +잔여 파드 응답 옛 버전으로 되돌리기 @@ -76,13 +76,13 @@ databasechangelog 행 수 -늘었으면 스키마가 움직였다 +전후 행 수 비교 StatefulSet 롤링 업데이트 -나머지 파드는 건드리지 않는다 +나머지 파드 유지 diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.alt.md b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.alt.md index 1c41f44..9453f55 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.alt.md +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.alt.md @@ -16,5 +16,5 @@ kubectl get secret -o yaml 이 보여주는 base64 는 인코딩이지 암호화 ## Relationships -- **k8s Secret → etcd:** 여기 저장된다. Evidence: L495–L501. -- **k8s Secret → 파드 환경 변수:** 주입된다. Evidence: L495–L501. +- **k8s Secret → etcd:** 저장. Evidence: L495–L501. +- **k8s Secret → 파드 환경 변수:** 주입. Evidence: L495–L501. diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.d2 b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.d2 index 6864b3f..faaf45d 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.d2 +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.d2 @@ -10,5 +10,5 @@ n1: "etcd" { n2: "파드 환경 변수" { shape: rectangle } -n0 -> n1: "여기 저장된다" -n0 -> n2: "주입된다" +n0 -> n1: "저장" +n0 -> n2: "주입" diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.dot b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.dot index 14418dd..e3262a1 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.dot +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.dot @@ -5,6 +5,6 @@ digraph techviz { n0 [label="k8s Secret", shape=cylinder, style="rounded,filled"]; n1 [label="etcd", shape=cylinder, style="rounded,filled"]; n2 [label="파드 환경 변수", shape=box, style="rounded,filled"]; - n0 -> n1 [label="여기 저장된다", style=solid]; - n0 -> n2 [label="주입된다", style=solid]; + n0 -> n1 [label="저장", style=solid]; + n0 -> n2 [label="주입", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.drawio b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.drawio index a088b6a..994fad3 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.drawio +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.drawio @@ -5,7 +5,7 @@ - + @@ -14,12 +14,12 @@ - + - + diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.excalidraw b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.excalidraw index 1012446..78fc866 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.excalidraw +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "여기 저장된다", + "text": "저장", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "여기 저장된다", + "originalText": "저장", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "주입된다", + "text": "주입", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "주입된다", + "originalText": "주입", "autoResize": true, "lineHeight": 1.25 }, @@ -262,11 +262,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "k8s Secret\n인코딩이지 암호화가 아니다", + "text": "k8s Secret\nbase64 인코딩", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "k8s Secret\n인코딩이지 암호화가 아니다", + "originalText": "k8s Secret\nbase64 인코딩", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.manifest.json b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.manifest.json index 5acbff5..d5c1b2e 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.manifest.json +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "d3-secret-exposure", "spec_version": "1.1", - "spec_sha256": "ed7488f2d1f9b5d6e17cf9e6ed697252b007d0504df014aeb9afab065da20cff", + "spec_sha256": "b6167a15c39563b3cfa5ee200ba34a5cb23220b1c93428ad2bb399c48e3df240", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.mmd b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.mmd index 24ed628..af58092 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.mmd +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.mmd @@ -4,5 +4,5 @@ flowchart TB n0[("k8s Secret")] n1[("etcd")] n2["파드 환경 변수"] - n0 -->|"여기 저장된다"| n1 - n0 -->|"주입된다"| n2 + n0 -->|"저장"| n1 + n0 -->|"주입"| n2 diff --git a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.svg b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.svg index 4fda9a9..96cd96f 100644 --- a/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.svg +++ b/docs/keycloak-session-store/final/assets/d3-secret-exposure/d3-secret-exposure.svg @@ -51,16 +51,16 @@ - -여기 저장된다 + +저장 - -주입된다 + +주입 k8s Secret -인코딩이지 암호화가 아니다 +base64 인코딩 diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.alt.md b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.alt.md index 3b705cb..66c1610 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.alt.md +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.alt.md @@ -19,4 +19,4 @@ certbot 이 갱신에 성공한 뒤 deploy 훅이 nginx 를 reload 하는 경로 - **deploy 훅 → nginx 워커 교체:** reload 신호. Evidence: L560–L580. - **certbot 갱신 성공 → deploy 훅:** 갱신 성공 시 호출. Evidence: L560–L575. -- **nginx 워커 교체 → 새 인증서 서빙:** 새 워커가 새 인증서를 읽는다. Evidence: L571–L580. +- **nginx 워커 교체 → 새 인증서 서빙:** 새 인증서 적재. Evidence: L571–L580. diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.d2 b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.d2 index 2322a4b..e3f564c 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.d2 +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.d2 @@ -15,4 +15,4 @@ n3: "새 인증서 서빙" { } n0 -> n1: "갱신 성공 시 호출" n1 -> n2: "reload 신호" -n2 -> n3: "새 워커가 새 인증서를 읽는다" +n2 -> n3: "새 인증서 적재" diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.dot b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.dot index c72f097..5575502 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.dot +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.dot @@ -8,5 +8,5 @@ digraph techviz { n3 [label="새 인증서 서빙", shape=box, style="rounded,filled"]; n0 -> n1 [label="갱신 성공 시 호출", style=solid]; n1 -> n2 [label="reload 신호", style=solid]; - n2 -> n3 [label="새 워커가 새 인증서를 읽는다", style=solid]; + n2 -> n3 [label="새 인증서 적재", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.drawio b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.drawio index bde9bc1..6864853 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.drawio +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.drawio @@ -27,7 +27,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.excalidraw b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.excalidraw index 8482eff..6c7f4d6 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.excalidraw +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.excalidraw @@ -264,9 +264,9 @@ { "id": "edge-label-w-s", "type": "text", - "x": 141.5, + "x": 160.5, "y": 494.0, - "width": 128, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "새 워커가 새 인증서를 읽는다", + "text": "새 인증서 적재", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "새 워커가 새 인증서를 읽는다", + "originalText": "새 인증서 적재", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.manifest.json b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.manifest.json index a56f5e3..c950b41 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.manifest.json +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "d4a-hook-effect", "spec_version": "1.1", - "spec_sha256": "59efe2ccd992f17d10ab3dfb326165c08f77c325c5d080f339ea556a07daefe3", + "spec_sha256": "94bfbe9e771b5ce00e14823ff32b308db3853d5c388631c9e2e8f58fc1532697", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.mmd b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.mmd index 287b995..eb9024f 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.mmd +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.mmd @@ -7,4 +7,4 @@ flowchart TB n3["새 인증서 서빙"] n0 -->|"갱신 성공 시 호출"| n1 n1 -->|"reload 신호"| n2 - n2 -->|"새 워커가 새 인증서를 읽는다"| n3 + n2 -->|"새 인증서 적재"| n3 diff --git a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.svg b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.svg index 6c77a64..6a1f9fd 100644 --- a/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.svg +++ b/docs/keycloak-session-store/final/assets/d4a-hook-effect/d4a-hook-effect.svg @@ -57,8 +57,8 @@ 갱신 성공 시 호출 - -새 워커가 새 인증서를 읽는다 + +새 인증서 적재 certbot 갱신 성공 diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.alt.md b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.alt.md index 7e3b170..7872691 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.alt.md +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.alt.md @@ -16,5 +16,5 @@ ## Relationships -- **주입 명령 → 대상 상태 확인:** 걸렸는가를 먼저 본다. Evidence: L128–L133. -- **대상 상태 확인 → 결과 관측:** 걸린 뒤에만 결과를 읽는다. Evidence: L128–L133. +- **주입 명령 → 대상 상태 확인:** 상태 확인. Evidence: L128–L133. +- **대상 상태 확인 → 결과 관측:** 결과 판독. Evidence: L128–L133. diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.d2 b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.d2 index eb41b5e..175a970 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.d2 +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.d2 @@ -10,5 +10,5 @@ n1: "대상 상태 확인" { n2: "결과 관측" { shape: rectangle } -n0 -> n1: "걸렸는가를 먼저 본다" -n1 -> n2: "걸린 뒤에만 결과를 읽는다" +n0 -> n1: "상태 확인" +n1 -> n2: "결과 판독" diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.dot b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.dot index 8112eb2..bb98010 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.dot +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.dot @@ -5,6 +5,6 @@ digraph techviz { n0 [label="주입 명령", shape=box, style="rounded,filled"]; n1 [label="대상 상태 확인", shape=box, style="rounded,filled"]; n2 [label="결과 관측", shape=box, style="rounded,filled"]; - n0 -> n1 [label="걸렸는가를 먼저 본다", style=solid]; - n1 -> n2 [label="걸린 뒤에만 결과를 읽는다", style=solid]; + n0 -> n1 [label="상태 확인", style=solid]; + n1 -> n2 [label="결과 판독", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.drawio b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.drawio index 9418ff2..5dcefb4 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.drawio +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.drawio @@ -1,25 +1,25 @@ - + - + - - + + - + - + diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.excalidraw b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.excalidraw index af95485..89df539 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.excalidraw +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "걸렸는가를 먼저 본다", + "text": "상태 확인", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "걸렸는가를 먼저 본다", + "originalText": "상태 확인", "autoResize": true, "lineHeight": 1.25 }, @@ -165,9 +165,9 @@ { "id": "edge-label-v-o", "type": "text", - "x": 704.0, + "x": 715.0, "y": 55.5, - "width": 112, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "걸린 뒤에만 결과를 읽는다", + "text": "결과 판독", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "걸린 뒤에만 결과를 읽는다", + "originalText": "결과 판독", "autoResize": true, "lineHeight": 1.25 }, @@ -262,11 +262,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "주입 명령\n아홉 번 조용히 실패했다", + "text": "주입 명령\n조용한 실패 9건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "주입 명령\n아홉 번 조용히 실패했다", + "originalText": "주입 명령\n조용한 실패 9건", "autoResize": true, "lineHeight": 1.25 }, @@ -344,7 +344,7 @@ "type": "rectangle", "x": 840.0, "y": 60.0, - "width": 174.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -374,7 +374,7 @@ "type": "text", "x": 850.0, "y": 70.0, - "width": 154.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -400,11 +400,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "결과 관측\n주입 실패 = 영향 없음 으로 읽힌다", + "text": "결과 관측\n실패 · 무영향 구별 불가", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "결과 관측\n주입 실패 = 영향 없음 으로 읽힌다", + "originalText": "결과 관측\n실패 · 무영향 구별 불가", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.manifest.json b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.manifest.json index 9093849..770f550 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.manifest.json +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "injection-verification", "spec_version": "1.1", - "spec_sha256": "611f473e287966f16e1be6d7cd47ea750e670f3c89e904fa7ec945363433293e", + "spec_sha256": "0826a08af0195d042f44cb3a9193ff9d9fe84316a739000e989b23b320a9363b", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.mmd b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.mmd index 4437a02..1cd771d 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.mmd +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.mmd @@ -4,5 +4,5 @@ flowchart LR n0["주입 명령"] n1["대상 상태 확인"] n2["결과 관측"] - n0 -->|"걸렸는가를 먼저 본다"| n1 - n1 -->|"걸린 뒤에만 결과를 읽는다"| n2 + n0 -->|"상태 확인"| n1 + n1 -->|"결과 판독"| n2 diff --git a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.svg b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.svg index 62e4b9f..f8375cb 100644 --- a/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.svg +++ b/docs/keycloak-session-store/final/assets/injection-verification/injection-verification.svg @@ -1,5 +1,5 @@ - + 주입이 걸렸는지 따로 확인한다 이 실험대에서 아홉 번의 주입이 조용히 실패했다. conntrack 이 ESTABLISHED 연결을 통과시키고, kubectl delete --force 가 크래시가 아니며, PID 1 이 SIGKILL 을 무시하고, kube-router 가 iptables 체인을 다시 끼워 넣는다. 모두 아무 일도 없었다로 보였다. 그래서 주입 뒤에는 결과를 보기 전에 대상이 실제로 그 상태인지를 cluster_size, 워커 PID, conntrack 표, 패킷 카운터로 확인한다. {"techviz":{"spec_version":"1.1","id":"injection-verification","profile":"component-flow"},"source_context":{"document":"docs/keycloak-session-store/final/document.md","document_sha256":"1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe","anchor":{"kind":"heading","value":"주입이 먹지 않는다 — 아홉 번, 전부 조용히","line":113}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true} @@ -49,18 +49,18 @@ .timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; } - + - -걸렸는가를 먼저 본다 + +상태 확인 - -걸린 뒤에만 결과를 읽는다 + +결과 판독 주입 명령 -아홉 번 조용히 실패했다 +조용한 실패 9건 @@ -69,9 +69,9 @@ cluster_size · 워커 PID · conntrack · 패킷 카운터 - -결과 관측 - -주입 실패 = 영향 없음 으로 읽힌다 + +결과 관측 + +실패 · 무영향 구별 불가 diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.alt.md b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.alt.md index 5d3e00d..ee45452 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.alt.md +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.alt.md @@ -17,6 +17,6 @@ D-4 에서 주입 전에 900건을 재서 오류 0을 확인했다. 그래서 ## Relationships -- **주입 전 대조군 → 주입 중 관측:** 비교 기준을 준다. Evidence: L596–L610. -- **주입 중 관측 → 귀속:** 대조가 있으면. Evidence: L596–L618. -- **주입 중 관측 → 오보:** 대조가 없으면. Evidence: L607–L618. +- **주입 전 대조군 → 주입 중 관측:** 비교 기준. Evidence: L596–L610. +- **주입 중 관측 → 귀속:** 대조군 있음. Evidence: L596–L618. +- **주입 중 관측 → 오보:** 대조군 없음. Evidence: L607–L618. diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.d2 b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.d2 index 91057a4..06015d5 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.d2 +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.d2 @@ -13,6 +13,6 @@ n2: "귀속" { n3: "오보" { shape: rectangle } -n0 -> n1: "비교 기준을 준다" -n1 -> n2: "대조가 있으면" -n1 -> n3: "대조가 없으면" +n0 -> n1: "비교 기준" +n1 -> n2: "대조군 있음" +n1 -> n3: "대조군 없음" diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.dot b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.dot index 9fd6620..7e18bd6 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.dot +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="주입 중 관측", shape=box, style="rounded,filled"]; n2 [label="귀속", shape=box, style="rounded,filled"]; n3 [label="오보", shape=box, style="rounded,filled"]; - n0 -> n1 [label="비교 기준을 준다", style=solid]; - n1 -> n2 [label="대조가 있으면", style=solid]; - n1 -> n3 [label="대조가 없으면", style=solid]; + n0 -> n1 [label="비교 기준", style=solid]; + n1 -> n2 [label="대조군 있음", style=solid]; + n1 -> n3 [label="대조군 없음", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.drawio b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.drawio index 82596a4..5d51ffb 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.drawio +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.drawio @@ -6,30 +6,30 @@ - + - + - - + + - - + + - + - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.excalidraw b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.excalidraw index f400f18..4aac88f 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.excalidraw +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.excalidraw @@ -6,7 +6,7 @@ { "id": "edge-b-o", "type": "arrow", - "x": 263.5, + "x": 250.0, "y": 131.0, "width": 0.0, "height": 96.0, @@ -66,7 +66,7 @@ { "id": "edge-label-b-o", "type": "text", - "x": 242.5, + "x": 229.0, "y": 167.0, "width": 90, "height": 24, @@ -94,20 +94,20 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "비교 기준을 준다", + "text": "비교 기준", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "비교 기준을 준다", + "originalText": "비교 기준", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-o-a", "type": "arrow", - "x": 157.0, + "x": 145.0, "y": 291.0, - "width": 97.5, + "width": 96.0, "height": 96.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -131,11 +131,11 @@ "locked": false, "points": [ [ - 97.5, + 96.0, 0.0 ], [ - 97.5, + 96.0, 48.0 ], [ @@ -165,7 +165,7 @@ { "id": "edge-label-o-a", "type": "text", - "x": 160.75, + "x": 148.0, "y": 299.0, "width": 90, "height": 24, @@ -193,20 +193,20 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "대조가 있으면", + "text": "대조군 있음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "대조가 있으면", + "originalText": "대조군 있음", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-o-m", "type": "arrow", - "x": 272.5, + "x": 259.0, "y": 291.0, - "width": 108.0, + "width": 96.0, "height": 96.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -238,11 +238,11 @@ 48.0 ], [ - 108.0, + 96.0, 48.0 ], [ - 108.0, + 96.0, 96.0 ] ], @@ -264,7 +264,7 @@ { "id": "edge-label-o-m", "type": "text", - "x": 281.5, + "x": 262.0, "y": 299.0, "width": 90, "height": 24, @@ -292,18 +292,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "대조가 없으면", + "text": "대조군 없음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "대조가 없으면", + "originalText": "대조군 없음", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-baseline", "type": "rectangle", - "x": 188.5, + "x": 175.0, "y": 60.0, "width": 150.0, "height": 71.0, @@ -333,7 +333,7 @@ { "id": "node-label-baseline", "type": "text", - "x": 198.5, + "x": 185.0, "y": 70.0, "width": 130.0, "height": 51.0, @@ -372,7 +372,7 @@ { "id": "node-observation", "type": "rectangle", - "x": 188.5, + "x": 175.0, "y": 227.0, "width": 150.0, "height": 64.0, @@ -402,7 +402,7 @@ { "id": "node-label-observation", "type": "text", - "x": 198.5, + "x": 185.0, "y": 237.0, "width": 130.0, "height": 44.0, @@ -443,7 +443,7 @@ "type": "rectangle", "x": 70.0, "y": 387.0, - "width": 174.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -473,7 +473,7 @@ "type": "text", "x": 80.0, "y": 397.0, - "width": 154.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -499,20 +499,20 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "귀속\n대조군이 0 이므로 한 번도 갱신 탓", + "text": "귀속\n대조군 0 → 귀속 성립", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "귀속\n대조군이 0 이므로 한 번도 갱신 탓", + "originalText": "귀속\n대조군 0 → 귀속 성립", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-misreport", "type": "rectangle", - "x": 304.0, + "x": 280.0, "y": 387.0, - "width": 153.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -540,9 +540,9 @@ { "id": "node-label-misreport", "type": "text", - "x": 314.0, + "x": 290.0, "y": 397.0, - "width": 133.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "오보\n76건 실패는 로컬 아티팩트였다", + "text": "오보\n로컬 아티팩트 76건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "오보\n76건 실패는 로컬 아티팩트였다", + "originalText": "오보\n로컬 아티팩트 76건", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.manifest.json b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.manifest.json index b9fdedb..06d4256 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.manifest.json +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "measurement-control", "spec_version": "1.1", - "spec_sha256": "3d2920d4ba708e8e505ef14e82b01bed9c293bbfe4b0d8379a0cef7265d38414", + "spec_sha256": "169ffe513a56bc94943815168f5dd8c311041aabaa20bb8ed1328c25936e7334", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.mmd b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.mmd index 03ca43d..82f44cc 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.mmd +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.mmd @@ -5,6 +5,6 @@ flowchart TB n1["주입 중 관측"] n2["귀속"] n3["오보"] - n0 -->|"비교 기준을 준다"| n1 - n1 -->|"대조가 있으면"| n2 - n1 -->|"대조가 없으면"| n3 + n0 -->|"비교 기준"| n1 + n1 -->|"대조군 있음"| n2 + n1 -->|"대조군 없음"| n3 diff --git a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.svg b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.svg index 2cea662..2f01887 100644 --- a/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.svg +++ b/docs/keycloak-session-store/final/assets/measurement-control/measurement-control.svg @@ -50,35 +50,35 @@ - - -비교 기준을 준다 - - -대조가 있으면 - - -대조가 없으면 + + +비교 기준 + + +대조군 있음 + + +대조군 없음 - -주입 전 대조군 - -900건 중 오류 0 + +주입 전 대조군 + +900건 중 오류 0 - -주입 중 관측 + +주입 중 관측 - -귀속 - -대조군이 0 이므로 한 번도 갱신 탓 + +귀속 + +대조군 0 → 귀속 성립 - -오보 - -76건 실패는 로컬 아티팩트였다 + +오보 + +로컬 아티팩트 76건 diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.alt.md b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.alt.md index a1ad97f..c0e951d 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.alt.md +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.alt.md @@ -17,6 +17,6 @@ Keycloak 26 미만이면 persistent-user-sessions 가 기본이 아니라 A층 ## Relationships -- **캐시 온도 → 인스턴스 수:** 그 다음. Evidence: L684–L694. -- **인스턴스 수 → 시계 동기:** 수치를 읽을 때. Evidence: L684–L696. -- **Keycloak 버전 → 캐시 온도:** 버전이 먼저다. Evidence: L684–L690. +- **캐시 온도 → 인스턴스 수:** 다음 조건. Evidence: L684–L694. +- **인스턴스 수 → 시계 동기:** 수치 해석. Evidence: L684–L696. +- **Keycloak 버전 → 캐시 온도:** 선행 조건. Evidence: L684–L690. diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.d2 b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.d2 index c6ae053..5106abe 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.d2 +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.d2 @@ -13,6 +13,6 @@ n2: "인스턴스 수" { n3: "시계 동기" { shape: rectangle } -n0 -> n1: "버전이 먼저다" -n1 -> n2: "그 다음" -n2 -> n3: "수치를 읽을 때" +n0 -> n1: "선행 조건" +n1 -> n2: "다음 조건" +n2 -> n3: "수치 해석" diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.dot b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.dot index 9b98ee4..e0830b1 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.dot +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.dot @@ -6,7 +6,7 @@ digraph techviz { n1 [label="캐시 온도", shape=box, style="rounded,filled"]; n2 [label="인스턴스 수", shape=box, style="rounded,filled"]; n3 [label="시계 동기", shape=box, style="rounded,filled"]; - n0 -> n1 [label="버전이 먼저다", style=solid]; - n1 -> n2 [label="그 다음", style=solid]; - n2 -> n3 [label="수치를 읽을 때", style=solid]; + n0 -> n1 [label="선행 조건", style=solid]; + n1 -> n2 [label="다음 조건", style=solid]; + n2 -> n3 [label="수치 해석", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.drawio b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.drawio index f752ff8..c13c577 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.drawio +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.drawio @@ -5,7 +5,7 @@ - + @@ -17,17 +17,17 @@ - + - + - + diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.excalidraw b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.excalidraw index b79a309..444adf3 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.excalidraw +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "그 다음", + "text": "다음 조건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "그 다음", + "originalText": "다음 조건", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "수치를 읽을 때", + "text": "수치 해석", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "수치를 읽을 때", + "originalText": "수치 해석", "autoResize": true, "lineHeight": 1.25 }, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "버전이 먼저다", + "text": "선행 조건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "버전이 먼저다", + "originalText": "선행 조건", "autoResize": true, "lineHeight": 1.25 }, @@ -361,11 +361,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "Keycloak 버전\nA층 결론 중 셋이 뒤집힌다", + "text": "Keycloak 버전\nA층 결론 3건 반전", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "Keycloak 버전\nA층 결론 중 셋이 뒤집힌다", + "originalText": "Keycloak 버전\nA층 결론 3건 반전", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.manifest.json b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.manifest.json index 949645e..a232648 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.manifest.json +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "not-applicable-conditions", "spec_version": "1.1", - "spec_sha256": "781e50387d9e0accfe0ae33366bc7c2352438b31646900d1b1bfa81f4a8dd9e6", + "spec_sha256": "5f448f0fb937c134f7e4980085db426a78f33ef1efff5bff13d824f62a093ef3", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.mmd b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.mmd index 2cdd813..49af0a7 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.mmd +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.mmd @@ -5,6 +5,6 @@ flowchart TB n1["캐시 온도"] n2["인스턴스 수"] n3["시계 동기"] - n0 -->|"버전이 먼저다"| n1 - n1 -->|"그 다음"| n2 - n2 -->|"수치를 읽을 때"| n3 + n0 -->|"선행 조건"| n1 + n1 -->|"다음 조건"| n2 + n2 -->|"수치 해석"| n3 diff --git a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.svg b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.svg index 9d2b881..b37bf04 100644 --- a/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.svg +++ b/docs/keycloak-session-store/final/assets/not-applicable-conditions/not-applicable-conditions.svg @@ -51,19 +51,19 @@ - -그 다음 + +다음 조건 - -수치를 읽을 때 + +수치 해석 - -버전이 먼저다 + +선행 조건 Keycloak 버전 -A층 결론 중 셋이 뒤집힌다 +A층 결론 3건 반전 diff --git a/docs/keycloak-session-store/final/assets/observation-points/observation-points.drawio b/docs/keycloak-session-store/final/assets/observation-points/observation-points.drawio index b1e9f48..2356c89 100644 --- a/docs/keycloak-session-store/final/assets/observation-points/observation-points.drawio +++ b/docs/keycloak-session-store/final/assets/observation-points/observation-points.drawio @@ -8,8 +8,8 @@ - - + + @@ -19,7 +19,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/observation-points/observation-points.excalidraw b/docs/keycloak-session-store/final/assets/observation-points/observation-points.excalidraw index b47c0ef..6f1f07b 100644 --- a/docs/keycloak-session-store/final/assets/observation-points/observation-points.excalidraw +++ b/docs/keycloak-session-store/final/assets/observation-points/observation-points.excalidraw @@ -8,7 +8,7 @@ "type": "arrow", "x": 220.0, "y": 95.5, - "width": 202.0, + "width": 207.0, "height": 125.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -36,15 +36,15 @@ 125.0 ], [ - 101.0, + 103.5, 125.0 ], [ - 101.0, + 103.5, 0.0 ], [ - 202.0, + 207.0, 0.0 ] ], @@ -66,7 +66,7 @@ { "id": "edge-label-s-c", "type": "text", - "x": 300.0, + "x": 302.5, "y": 146.0, "width": 90, "height": 24, @@ -372,9 +372,9 @@ { "id": "node-curl", "type": "rectangle", - "x": 422.0, + "x": 427.0, "y": 60.0, - "width": 160.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -402,9 +402,9 @@ { "id": "node-label-curl", "type": "text", - "x": 432.0, + "x": 437.0, "y": 70.0, - "width": 140.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "외부 curl\n분단돼도 200 이 나올 수 있다", + "text": "외부 curl\n분단 시에도 200", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "외부 curl\n분단돼도 200 이 나올 수 있다", + "originalText": "외부 curl\n분단 시에도 200", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/observation-points/observation-points.manifest.json b/docs/keycloak-session-store/final/assets/observation-points/observation-points.manifest.json index 0289128..196ef77 100644 --- a/docs/keycloak-session-store/final/assets/observation-points/observation-points.manifest.json +++ b/docs/keycloak-session-store/final/assets/observation-points/observation-points.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "observation-points", "spec_version": "1.1", - "spec_sha256": "b5dfbe6448d4d010d8860e8aad1b93e5f867a628edc03d06798b4a676f2a8156", + "spec_sha256": "17709b275fbf9b82484b8ca7c509a805f74d7e90019b5e6b42e5fb0e17578325", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/observation-points/observation-points.svg b/docs/keycloak-session-store/final/assets/observation-points/observation-points.svg index aa9bc53..0cb004a 100644 --- a/docs/keycloak-session-store/final/assets/observation-points/observation-points.svg +++ b/docs/keycloak-session-store/final/assets/observation-points/observation-points.svg @@ -50,9 +50,9 @@ - - -외부 응답 + + +외부 응답 저장 결과 @@ -66,10 +66,10 @@ 두 노드 - + 외부 curl - -분단돼도 200 이 나올 수 있다 + +분단 시에도 200 diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.alt.md b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.alt.md index a6ea829..8332f55 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.alt.md +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.alt.md @@ -13,10 +13,10 @@ Q1 은 저장소를 밖으로 빼면 다중 인스턴스와 재시작은 풀리 - **열린 질문 네 개** (component): 설계로는 답할 수 없었다. Evidence: L682–L690. - **저장소 선택** (process): 다중 인스턴스와 재시작은 여기서 풀린다. Evidence: L682–L692. - **스키마와 조회 키** (process): 덮어쓰기와 정리 누락은 여기가 원인이다. Evidence: L682–L694. -- **세션은 스냅샷이다** (process): 클레임 변경이 반영되지 않는 이유. Evidence: L682–L696. +- **세션 스냅샷** (process): 클레임 변경이 반영되지 않는 이유. Evidence: L682–L696. ## Relationships -- **열린 질문 네 개 → 저장소 선택:** 먼저 여기를 본다. Evidence: L682–L692. -- **저장소 선택 → 스키마와 조회 키:** 여기서 풀리지 않는 것. Evidence: L682–L694. -- **스키마와 조회 키 → 세션은 스냅샷이다:** 남는 것. Evidence: L682–L696. +- **열린 질문 네 개 → 저장소 선택:** 1차 검토. Evidence: L682–L692. +- **저장소 선택 → 스키마와 조회 키:** 미해결 잔여. Evidence: L682–L694. +- **스키마와 조회 키 → 세션 스냅샷:** 최종 잔여. Evidence: L682–L696. diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.d2 b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.d2 index 9a77301..ae52918 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.d2 +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.d2 @@ -10,9 +10,9 @@ n1: "저장소 선택" { n2: "스키마와 조회 키" { shape: rectangle } -n3: "세션은 스냅샷이다" { +n3: "세션 스냅샷" { shape: rectangle } -n0 -> n1: "먼저 여기를 본다" -n1 -> n2: "여기서 풀리지 않는 것" -n2 -> n3: "남는 것" +n0 -> n1: "1차 검토" +n1 -> n2: "미해결 잔여" +n2 -> n3: "최종 잔여" diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.dot b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.dot index 417468f..d7bb494 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.dot +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.dot @@ -5,8 +5,8 @@ digraph techviz { n0 [label="열린 질문 네 개", shape=box, style="rounded,filled"]; n1 [label="저장소 선택", shape=box, style="rounded,filled"]; n2 [label="스키마와 조회 키", shape=box, style="rounded,filled"]; - n3 [label="세션은 스냅샷이다", shape=box, style="rounded,filled"]; - n0 -> n1 [label="먼저 여기를 본다", style=solid]; - n1 -> n2 [label="여기서 풀리지 않는 것", style=solid]; - n2 -> n3 [label="남는 것", style=solid]; + n3 [label="세션 스냅샷", shape=box, style="rounded,filled"]; + n0 -> n1 [label="1차 검토", style=solid]; + n1 -> n2 [label="미해결 잔여", style=solid]; + n2 -> n3 [label="최종 잔여", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.drawio b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.drawio index 8be6179..f414f81 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.drawio +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.drawio @@ -11,23 +11,23 @@ - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.excalidraw b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.excalidraw index 3faa139..57a7c14 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.excalidraw +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "먼저 여기를 본다", + "text": "1차 검토", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "먼저 여기를 본다", + "originalText": "1차 검토", "autoResize": true, "lineHeight": 1.25 }, @@ -165,9 +165,9 @@ { "id": "edge-label-s-sc", "type": "text", - "x": 126.0, + "x": 129.0, "y": 334.0, - "width": 96, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "여기서 풀리지 않는 것", + "text": "미해결 잔여", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "여기서 풀리지 않는 것", + "originalText": "미해결 잔여", "autoResize": true, "lineHeight": 1.25 }, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "남는 것", + "text": "최종 잔여", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "남는 것", + "originalText": "최종 잔여", "autoResize": true, "lineHeight": 1.25 }, @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "스키마와 조회 키\n세션 id 가 키에 없다", + "text": "스키마와 조회 키\n키에 세션 id 없음", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "스키마와 조회 키\n세션 id 가 키에 없다", + "originalText": "스키마와 조회 키\n키에 세션 id 없음", "autoResize": true, "lineHeight": 1.25 }, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "세션은 스냅샷이다\n재인증까지 옛 값", + "text": "세션 스냅샷\n재인증까지 옛 값", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션은 스냅샷이다\n재인증까지 옛 값", + "originalText": "세션 스냅샷\n재인증까지 옛 값", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.manifest.json b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.manifest.json index 1f710d5..a240837 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.manifest.json +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "open-questions-answered", "spec_version": "1.1", - "spec_sha256": "393e86220223912183fd40cfdd76266b6180959ba3ba863884a18e491631d6e2", + "spec_sha256": "176dac77a298b7d32cd7e1958a7468f496a070983e0ca7cbfc1af1a636e7579c", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.mmd b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.mmd index 249a548..277cd66 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.mmd +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.mmd @@ -4,7 +4,7 @@ flowchart TB n0["열린 질문 네 개"] n1["저장소 선택"] n2["스키마와 조회 키"] - n3["세션은 스냅샷이다"] - n0 -->|"먼저 여기를 본다"| n1 - n1 -->|"여기서 풀리지 않는 것"| n2 - n2 -->|"남는 것"| n3 + n3["세션 스냅샷"] + n0 -->|"1차 검토"| n1 + n1 -->|"미해결 잔여"| n2 + n2 -->|"최종 잔여"| n3 diff --git a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.svg b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.svg index dd0d90d..311e358 100644 --- a/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.svg +++ b/docs/keycloak-session-store/final/assets/open-questions-answered/open-questions-answered.svg @@ -51,14 +51,14 @@ - -먼저 여기를 본다 + +1차 검토 - -여기서 풀리지 않는 것 + +미해결 잔여 - -남는 것 + +최종 잔여 열린 질문 네 개 @@ -75,11 +75,11 @@ 스키마와 조회 키 -세션 id 가 키에 없다 +키에 세션 id 없음 -세션은 스냅샷이다 +세션 스냅샷 재인증까지 옛 값 diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.alt.md b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.alt.md index 4d5565e..2df7271 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.alt.md +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.alt.md @@ -17,7 +17,7 @@ certbot renew 는 archive 디렉터리에 새 인증서를 쓰고 live 심볼릭 ## Relationships -- **live/fullchain.pem → nginx 워커:** reload 없이는 닿지 않는다. Evidence: L536–L540. +- **live/fullchain.pem → nginx 워커:** reload 필요. Evidence: L536–L540. - **renewal-hooks/deploy → nginx 워커:** reload 신호. Evidence: L556–L562. - **certbot renew → renewal-hooks/deploy:** 갱신 성공 시 호출. Evidence: L527–L533. - **certbot renew → live/fullchain.pem:** 새 인증서 기록. Evidence: L504–L510. diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.d2 b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.d2 index f87c91b..80ccd90 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.d2 +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.d2 @@ -14,6 +14,6 @@ n3: "nginx 워커" { shape: rectangle } n0 -> n1: "새 인증서 기록" -n1 -> n3: "reload 없이는 닿지 않는다" +n1 -> n3: "reload 필요" n0 -> n2: "갱신 성공 시 호출" n2 -> n3: "reload 신호" diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.dot b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.dot index 5663be4..496b681 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.dot +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.dot @@ -7,7 +7,7 @@ digraph techviz { n2 [label="renewal-hooks/deploy", shape=box, style="rounded,filled"]; n3 [label="nginx 워커", shape=box, style="rounded,filled"]; n0 -> n1 [label="새 인증서 기록", style=solid]; - n1 -> n3 [label="reload 없이는 닿지 않는다", style=solid]; + n1 -> n3 [label="reload 필요", style=solid]; n0 -> n2 [label="갱신 성공 시 호출", style=solid]; n2 -> n3 [label="reload 신호", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.drawio b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.drawio index a3b9893..3f86bc9 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.drawio +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.drawio @@ -11,15 +11,15 @@ - - + + - + - + @@ -34,7 +34,7 @@ - + diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.excalidraw b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.excalidraw index 3bfe070..fb14292 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.excalidraw +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.excalidraw @@ -6,9 +6,9 @@ { "id": "edge-needs-reload", "type": "arrow", - "x": 592.5, + "x": 575.0, "y": 189.0, - "width": 170.5, + "width": 188.0, "height": 62.5, "angle": 0, "strokeColor": "#1e1e1e", @@ -36,15 +36,15 @@ 62.5 ], [ - 85.25, + 94.0, 62.5 ], [ - 85.25, + 94.0, 0.0 ], [ - 170.5, + 188.0, 0.0 ] ], @@ -66,9 +66,9 @@ { "id": "edge-label-needs-reload", "type": "text", - "x": 633.75, + "x": 648.0, "y": 208.25, - "width": 136, + "width": 90, "height": 24, "angle": 0, "strokeColor": "#1e1e1e", @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "reload 없이는 닿지 않는다", + "text": "reload 필요", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "reload 없이는 닿지 않는다", + "originalText": "reload 필요", "autoResize": true, "lineHeight": 1.25 }, @@ -305,7 +305,7 @@ "type": "arrow", "x": 220.0, "y": 189.0, - "width": 170.5, + "width": 188.0, "height": 62.5, "angle": 0, "strokeColor": "#1e1e1e", @@ -333,15 +333,15 @@ 0.0 ], [ - 85.25, + 94.0, 0.0 ], [ - 85.25, + 94.0, 62.5 ], [ - 170.5, + 188.0, 62.5 ] ], @@ -363,7 +363,7 @@ { "id": "edge-label-write", "type": "text", - "x": 284.25, + "x": 293.0, "y": 208.25, "width": 90, "height": 24, @@ -540,9 +540,9 @@ { "id": "node-live-link", "type": "rectangle", - "x": 390.5, + "x": 408.0, "y": 203.0, - "width": 202.0, + "width": 167.0, "height": 97.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -570,9 +570,9 @@ { "id": "node-label-live-link", "type": "text", - "x": 400.5, + "x": 418.0, "y": 213.0, - "width": 182.0, + "width": 147.0, "height": 77.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -598,11 +598,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "live/fullchain.pem\narchive/cert2.pem 을 가리킨다", + "text": "live/fullchain.pem\n→ archive/cert2.pem", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "live/fullchain.pem\narchive/cert2.pem 을 가리킨다", + "originalText": "live/fullchain.pem\n→ archive/cert2.pem", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.manifest.json b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.manifest.json index bdb22ab..563e703 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.manifest.json +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "renewal-to-serving-gap", "spec_version": "1.1", - "spec_sha256": "3e3db52f9abd54ed3f8d6d45e2bff22ba1c2fa312dfb8185d7d5c5c3b5ea24be", + "spec_sha256": "27876093d869fde6f95f5f296995ef24011354039da6da56a049d114068545d4", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "609353e10bfd37a9bbb6a79ecf2a32f3d3c02d5d161879a14ad4713e49e7e5e8", diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.mmd b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.mmd index 3169794..b514537 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.mmd +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.mmd @@ -6,6 +6,6 @@ flowchart LR n2["renewal-hooks/deploy"] n3["nginx 워커"] n0 -->|"새 인증서 기록"| n1 - n1 -->|"reload 없이는 닿지 않는다"| n3 + n1 -->|"reload 필요"| n3 n0 -->|"갱신 성공 시 호출"| n2 n2 -->|"reload 신호"| n3 diff --git a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.svg b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.svg index fecf19e..6652b46 100644 --- a/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.svg +++ b/docs/keycloak-session-store/final/assets/renewal-to-serving-gap/renewal-to-serving-gap.svg @@ -50,18 +50,18 @@ - - -reload 없이는 닿지 않는다 + + +reload 필요 reload 신호 갱신 성공 시 호출 - - -새 인증서 기록 + + +새 인증서 기록 certbot renew @@ -75,10 +75,10 @@ nginx -t && nginx -s reload - + live/fullchain.pem - -archive/cert2.pem 을 가리킨다 + +→ archive/cert2.pem diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.alt.md b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.alt.md index 0a629ed..f242c61 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.alt.md +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.alt.md @@ -10,13 +10,13 @@ ## Elements and evidence -- **산문으로 적힌 측정 장치** (component): 괄호와 설명으로 남아 있었다. Evidence: L598–L610. +- **산문 상태의 측정 장치** (component): 괄호와 설명으로 남아 있었다. Evidence: L598–L610. - **셸 표현식** (component): 붙여넣으면 도는 형태. Evidence: L598–L614. - **실제 실행 확인** (process): 여기서 한 건이 깨졌다. Evidence: L615–L622. - **재현 가능** (component): 실행까지 확인된 것만. Evidence: L615–L622. ## Relationships -- **셸 표현식 → 실제 실행 확인:** 돌려본다. Evidence: L615–L622. -- **실제 실행 확인 → 재현 가능:** 통과한 것만 남긴다. Evidence: L615–L622. -- **산문으로 적힌 측정 장치 → 셸 표현식:** 바꿔 적는다. Evidence: L598–L614. +- **셸 표현식 → 실제 실행 확인:** 실행. Evidence: L615–L622. +- **실제 실행 확인 → 재현 가능:** 통과분 채택. Evidence: L615–L622. +- **산문 상태의 측정 장치 → 셸 표현식:** 명령화. Evidence: L598–L614. diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.d2 b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.d2 index a5ab41f..23fa3f3 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.d2 +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.d2 @@ -1,7 +1,7 @@ # 명령으로 적는 것과 도는 것 # Question: 절차를 명령으로 적으면 재현이 보장되는가 direction: down -n0: "산문으로 적힌 측정 장치" { +n0: "산문 상태의 측정 장치" { shape: rectangle } n1: "셸 표현식" { @@ -13,6 +13,6 @@ n2: "실제 실행 확인" { n3: "재현 가능" { shape: rectangle } -n0 -> n1: "바꿔 적는다" -n1 -> n2: "돌려본다" -n2 -> n3: "통과한 것만 남긴다" +n0 -> n1: "명령화" +n1 -> n2: "실행" +n2 -> n3: "통과분 채택" diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.dot b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.dot index 337c1e0..4d53bc3 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.dot +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.dot @@ -2,11 +2,11 @@ digraph techviz { graph [rankdir=TB, splines=ortho, nodesep=0.55, ranksep=0.85]; node [fontname=Helvetica, fontsize=11, margin="0.18,0.12", style="rounded,filled", fillcolor=white, color="#2d4357", penwidth=1.5]; edge [fontname=Helvetica, fontsize=10, color="#364b5f", penwidth=1.4, arrowsize=0.75]; - n0 [label="산문으로 적힌 측정 장치", shape=box, style="rounded,filled"]; + n0 [label="산문 상태의 측정 장치", shape=box, style="rounded,filled"]; n1 [label="셸 표현식", shape=box, style="rounded,filled"]; n2 [label="실제 실행 확인", shape=box, style="rounded,filled"]; n3 [label="재현 가능", shape=box, style="rounded,filled"]; - n0 -> n1 [label="바꿔 적는다", style=solid]; - n1 -> n2 [label="돌려본다", style=solid]; - n2 -> n3 [label="통과한 것만 남긴다", style=solid]; + n0 -> n1 [label="명령화", style=solid]; + n1 -> n2 [label="실행", style=solid]; + n2 -> n3 [label="통과분 채택", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.drawio b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.drawio index 026fcc7..a195bab 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.drawio +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.drawio @@ -5,31 +5,31 @@ - - + + - + - + - - + + - + - + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.excalidraw b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.excalidraw index 2e6ea4a..2d6ffb8 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.excalidraw +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.excalidraw @@ -6,7 +6,7 @@ { "id": "edge-c-e", "type": "arrow", - "x": 188.5, + "x": 145.0, "y": 291.0, "width": 0.0, "height": 96.0, @@ -66,7 +66,7 @@ { "id": "edge-label-c-e", "type": "text", - "x": 167.5, + "x": 124.0, "y": 327.0, "width": 90, "height": 24, @@ -94,18 +94,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "돌려본다", + "text": "실행", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "돌려본다", + "originalText": "실행", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-e-v", "type": "arrow", - "x": 188.5, + "x": 145.0, "y": 458.0, "width": 0.0, "height": 96.0, @@ -165,7 +165,7 @@ { "id": "edge-label-e-v", "type": "text", - "x": 167.5, + "x": 124.0, "y": 494.0, "width": 90, "height": 24, @@ -193,18 +193,18 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "통과한 것만 남긴다", + "text": "통과분 채택", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "통과한 것만 남긴다", + "originalText": "통과분 채택", "autoResize": true, "lineHeight": 1.25 }, { "id": "edge-p-c", "type": "arrow", - "x": 188.5, + "x": 145.0, "y": 131.0, "width": 0.0, "height": 96.0, @@ -264,7 +264,7 @@ { "id": "edge-label-p-c", "type": "text", - "x": 167.5, + "x": 124.0, "y": 167.0, "width": 90, "height": 24, @@ -292,11 +292,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "바꿔 적는다", + "text": "명령화", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "바꿔 적는다", + "originalText": "명령화", "autoResize": true, "lineHeight": 1.25 }, @@ -305,7 +305,7 @@ "type": "rectangle", "x": 70.0, "y": 60.0, - "width": 237.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -335,7 +335,7 @@ "type": "text", "x": 80.0, "y": 70.0, - "width": 217.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -361,18 +361,18 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "산문으로 적힌 측정 장치\n( curl ... ) & 를 20개 띄우고 wait", + "text": "산문 상태의 측정 장치\n부하 생성기 20건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "산문으로 적힌 측정 장치\n( curl ... ) & 를 20개 띄우고 wait", + "originalText": "산문 상태의 측정 장치\n부하 생성기 20건", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-command", "type": "rectangle", - "x": 113.5, + "x": 70.0, "y": 227.0, "width": 150.0, "height": 64.0, @@ -402,7 +402,7 @@ { "id": "node-label-command", "type": "text", - "x": 123.5, + "x": 80.0, "y": 237.0, "width": 130.0, "height": 44.0, @@ -441,7 +441,7 @@ { "id": "node-execute", "type": "rectangle", - "x": 113.5, + "x": 70.0, "y": 387.0, "width": 150.0, "height": 71.0, @@ -471,7 +471,7 @@ { "id": "node-label-execute", "type": "text", - "x": 123.5, + "x": 80.0, "y": 397.0, "width": 130.0, "height": 51.0, @@ -510,7 +510,7 @@ { "id": "node-verified", "type": "rectangle", - "x": 113.5, + "x": 70.0, "y": 554.0, "width": 150.0, "height": 71.0, @@ -540,7 +540,7 @@ { "id": "node-label-verified", "type": "text", - "x": 123.5, + "x": 80.0, "y": 564.0, "width": 130.0, "height": 51.0, @@ -568,11 +568,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "재현 가능\n상주 탐침으로 20/20", + "text": "재현 가능\n상주 탐침 20/20", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "재현 가능\n상주 탐침으로 20/20", + "originalText": "재현 가능\n상주 탐침 20/20", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.manifest.json b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.manifest.json index 170cb74..5e12f15 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.manifest.json +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "reproducibility-gap", "spec_version": "1.1", - "spec_sha256": "f869b1dec58438616a980ae048ea5c43e8f56634949eaddb25d06057728c008f", + "spec_sha256": "9abe66c731b4e2a6740d245cd6c9018517553efc0a17d4bedef56adde13ad97c", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.mmd b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.mmd index d07623e..b604fa7 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.mmd +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.mmd @@ -1,10 +1,10 @@ %% 명령으로 적는 것과 도는 것 %% question: 절차를 명령으로 적으면 재현이 보장되는가 flowchart TB - n0["산문으로 적힌 측정 장치"] + n0["산문 상태의 측정 장치"] n1["셸 표현식"] n2["실제 실행 확인"] n3["재현 가능"] - n0 -->|"바꿔 적는다"| n1 - n1 -->|"돌려본다"| n2 - n2 -->|"통과한 것만 남긴다"| n3 + n0 -->|"명령화"| n1 + n1 -->|"실행"| n2 + n2 -->|"통과분 채택"| n3 diff --git a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.svg b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.svg index 19d588f..90ca2f1 100644 --- a/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.svg +++ b/docs/keycloak-session-store/final/assets/reproducibility-gap/reproducibility-gap.svg @@ -50,35 +50,35 @@ - - -돌려본다 - - -통과한 것만 남긴다 - - -바꿔 적는다 + + +실행 + + +통과분 채택 + + +명령화 - -산문으로 적힌 측정 장치 - -( curl ... ) & 를 20개 띄우고 wait + +산문 상태의 측정 장치 + +부하 생성기 20건 - -셸 표현식 + +셸 표현식 - -실제 실행 확인 - -일회성 파드의 출력 유실 + +실제 실행 확인 + +일회성 파드의 출력 유실 - -재현 가능 - -상주 탐침으로 20/20 + +재현 가능 + +상주 탐침 20/20 diff --git a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.drawio b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.drawio index 89f3c79..00ca401 100644 --- a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.drawio +++ b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.drawio @@ -5,36 +5,36 @@ - - + + - - + + - + - - + + - + - + - + - + diff --git a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.excalidraw b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.excalidraw index 001b42f..0cbd5c3 100644 --- a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.excalidraw +++ b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.excalidraw @@ -6,9 +6,9 @@ { "id": "edge-k0-discovery", "type": "arrow", - "x": 242.5, + "x": 220.0, "y": 96.0, - "width": 212.0, + "width": 160.0, "height": 13.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -36,15 +36,15 @@ 13.0 ], [ - 106.0, + 80.0, 13.0 ], [ - 106.0, + 80.0, 0.0 ], [ - 212.0, + 160.0, 0.0 ] ], @@ -66,7 +66,7 @@ { "id": "edge-label-k0-discovery", "type": "text", - "x": 327.5, + "x": 279.0, "y": 90.5, "width": 90, "height": 24, @@ -105,9 +105,9 @@ { "id": "edge-k0-writes", "type": "arrow", - "x": 242.5, + "x": 220.0, "y": 127.0, - "width": 182.5, + "width": 160.0, "height": 134.5, "angle": 0, "strokeColor": "#1e1e1e", @@ -135,15 +135,15 @@ 0.0 ], [ - 91.25, + 80.0, 0.0 ], [ - 91.25, + 80.0, 134.5 ], [ - 182.5, + 160.0, 134.5 ] ], @@ -165,7 +165,7 @@ { "id": "edge-label-k0-writes", "type": "text", - "x": 312.75, + "x": 279.0, "y": 182.25, "width": 90, "height": 24, @@ -204,9 +204,9 @@ { "id": "edge-k1-discovery", "type": "arrow", - "x": 265.0, + "x": 220.0, "y": 114.0, - "width": 189.5, + "width": 160.0, "height": 138.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -234,15 +234,15 @@ 138.0 ], [ - 94.75, + 80.0, 138.0 ], [ - 94.75, + 80.0, 0.0 ], [ - 189.5, + 160.0, 0.0 ] ], @@ -264,7 +264,7 @@ { "id": "edge-label-k1-discovery", "type": "text", - "x": 338.75, + "x": 279.0, "y": 171.0, "width": 90, "height": 24, @@ -303,7 +303,7 @@ { "id": "edge-k1-reads", "type": "arrow", - "x": 265.0, + "x": 220.0, "y": 270.0, "width": 160.0, "height": 9.5, @@ -363,7 +363,7 @@ { "id": "edge-label-k1-reads", "type": "text", - "x": 324.0, + "x": 279.0, "y": 262.75, "width": 90, "height": 24, @@ -402,7 +402,7 @@ { "id": "node-keycloak-0", "type": "rectangle", - "x": 92.5, + "x": 70.0, "y": 82.5, "width": 150.0, "height": 71.0, @@ -432,7 +432,7 @@ { "id": "node-label-keycloak-0", "type": "text", - "x": 102.5, + "x": 80.0, "y": 92.5, "width": 130.0, "height": 51.0, @@ -460,11 +460,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "keycloak-0\n자기가 처리한 로그인만 캐시", + "text": "keycloak-0\n자기 처리분만 캐시", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "keycloak-0\n자기가 처리한 로그인만 캐시", + "originalText": "keycloak-0\n자기 처리분만 캐시", "autoResize": true, "lineHeight": 1.25 }, @@ -473,7 +473,7 @@ "type": "rectangle", "x": 70.0, "y": 225.5, - "width": 195.0, + "width": 150.0, "height": 71.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -503,7 +503,7 @@ "type": "text", "x": 80.0, "y": 235.5, - "width": 175.0, + "width": 130.0, "height": 51.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -529,18 +529,18 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "keycloak-1\nrefresh 요청을 받으면 DB 를 조회", + "text": "keycloak-1\nrefresh 시 DB 조회", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "keycloak-1\nrefresh 요청을 받으면 DB 를 조회", + "originalText": "keycloak-1\nrefresh 시 DB 조회", "autoResize": true, "lineHeight": 1.25 }, { "id": "node-jgroups-ping", "type": "rectangle", - "x": 454.5, + "x": 380.0, "y": 60.0, "width": 150.0, "height": 90.0, @@ -570,7 +570,7 @@ { "id": "node-label-jgroups-ping", "type": "text", - "x": 464.5, + "x": 390.0, "y": 70.0, "width": 130.0, "height": 70.0, @@ -609,9 +609,9 @@ { "id": "node-postgres", "type": "rectangle", - "x": 425.0, + "x": 380.0, "y": 222.0, - "width": 209.0, + "width": 150.0, "height": 97.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -639,9 +639,9 @@ { "id": "node-label-postgres", "type": "text", - "x": 435.0, + "x": 390.0, "y": 232.0, - "width": 189.0, + "width": 130.0, "height": 77.0, "angle": 0, "strokeColor": "#1e1e1e", @@ -667,11 +667,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "PostgreSQL\noffline_flag='0' 이 온라인 세션", + "text": "PostgreSQL\noffline_flag='0'", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "PostgreSQL\noffline_flag='0' 이 온라인 세션", + "originalText": "PostgreSQL\noffline_flag='0'", "autoResize": true, "lineHeight": 1.25 } diff --git a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.manifest.json b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.manifest.json index 8d99d0e..4d258b8 100644 --- a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.manifest.json +++ b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "session-sharing-path", "spec_version": "1.1", - "spec_sha256": "622b6917edfc97cfbbbeea476bac0bceab339d4734549895d8acd721284f0a42", + "spec_sha256": "347c9930c1720050bf968e27eb87993d3eaaa3139ac231d1b6f8f93d770dd148", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "609353e10bfd37a9bbb6a79ecf2a32f3d3c02d5d161879a14ad4713e49e7e5e8", diff --git a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.svg b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.svg index fb13c05..eb0972a 100644 --- a/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.svg +++ b/docs/keycloak-session-store/final/assets/session-sharing-path/session-sharing-path.svg @@ -50,38 +50,38 @@ - - -멤버 등록 - - -세션 INSERT - - -멤버 등록 - - -세션 SELECT + + +멤버 등록 + + +세션 INSERT + + +멤버 등록 + + +세션 SELECT - -keycloak-0 - -자기가 처리한 로그인만 캐시 + +keycloak-0 + +자기 처리분만 캐시 - -keycloak-1 - -refresh 요청을 받으면 DB 를 조회 + +keycloak-1 + +refresh 시 DB 조회 - -JGROUPS_PING + +JGROUPS_PING - -PostgreSQL - -offline_flag='0' 이 온라인 세션 + +PostgreSQL + +offline_flag='0' diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.alt.md b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.alt.md index 00c1407..a48fb2d 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.alt.md +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.alt.md @@ -17,5 +17,5 @@ Keycloak 26 은 persistent-user-sessions 가 기본값이라 세션을 PostgreSQ ## Relationships -- **persistent-user-sessions 켜짐 → PostgreSQL 의 세션 행:** 세션을 여기 쓴다. Evidence: L62–L68. -- **persistent-user-sessions 꺼짐 → 노드 메모리의 세션:** 세션이 여기 있다. Evidence: L62–L68. +- **persistent-user-sessions 켜짐 → PostgreSQL 의 세션 행:** 세션 기록. Evidence: L62–L68. +- **persistent-user-sessions 꺼짐 → 노드 메모리의 세션:** 세션 보관. Evidence: L62–L68. diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.d2 b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.d2 index b86d661..814f266 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.d2 +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.d2 @@ -13,5 +13,5 @@ n2: "PostgreSQL 의 세션 행" { n3: "노드 메모리의 세션" { shape: rectangle } -n0 -> n2: "세션을 여기 쓴다" -n1 -> n3: "세션이 여기 있다" +n0 -> n2: "세션 기록" +n1 -> n3: "세션 보관" diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.dot b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.dot index cadfaec..d58ffb8 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.dot +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.dot @@ -6,6 +6,6 @@ digraph techviz { n1 [label="persistent-user-sessions 꺼짐", shape=box, style="rounded,filled"]; n2 [label="PostgreSQL 의 세션 행", shape=cylinder, style="rounded,filled"]; n3 [label="노드 메모리의 세션", shape=box, style="rounded,filled"]; - n0 -> n2 [label="세션을 여기 쓴다", style=solid]; - n1 -> n3 [label="세션이 여기 있다", style=solid]; + n0 -> n2 [label="세션 기록", style=solid]; + n1 -> n3 [label="세션 보관", style=solid]; } diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.drawio b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.drawio index e3142a6..cf73f76 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.drawio +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.drawio @@ -5,10 +5,10 @@ - + - + @@ -17,12 +17,12 @@ - + - + diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.excalidraw b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.excalidraw index 1445d2c..0c49577 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.excalidraw +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.excalidraw @@ -94,11 +94,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "세션을 여기 쓴다", + "text": "세션 기록", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션을 여기 쓴다", + "originalText": "세션 기록", "autoResize": true, "lineHeight": 1.25 }, @@ -193,11 +193,11 @@ "locked": false, "fontSize": 13, "fontFamily": 5, - "text": "세션이 여기 있다", + "text": "세션 보관", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "세션이 여기 있다", + "originalText": "세션 보관", "autoResize": true, "lineHeight": 1.25 }, @@ -262,11 +262,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "persistent-user-sessions 켜짐\n세션을 DB 에 쓴다", + "text": "persistent-user-sessions 켜짐\n세션 → DB", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "persistent-user-sessions 켜짐\n세션을 DB 에 쓴다", + "originalText": "persistent-user-sessions 켜짐\n세션 → DB", "autoResize": true, "lineHeight": 1.25 }, @@ -331,11 +331,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "persistent-user-sessions 꺼짐\n세션이 메모리에만 있다", + "text": "persistent-user-sessions 꺼짐\n세션 → 메모리", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "persistent-user-sessions 꺼짐\n세션이 메모리에만 있다", + "originalText": "persistent-user-sessions 꺼짐\n세션 → 메모리", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.manifest.json b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.manifest.json index ebe5a36..215d7b4 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.manifest.json +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "version-conditional-results", "spec_version": "1.1", - "spec_sha256": "67137c09f1217d0e2141e8f560c3c6970821cd2a4f5a91591f3729281ab55c04", + "spec_sha256": "24fe5d934211da9916c42d3db966c04559e51956a550964296655cbced280750", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.mmd b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.mmd index fd8c4bf..4561ab5 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.mmd +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.mmd @@ -5,5 +5,5 @@ flowchart LR n1["persistent-user-sessions 꺼짐"] n2[("PostgreSQL 의 세션 행")] n3["노드 메모리의 세션"] - n0 -->|"세션을 여기 쓴다"| n2 - n1 -->|"세션이 여기 있다"| n3 + n0 -->|"세션 기록"| n2 + n1 -->|"세션 보관"| n3 diff --git a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.svg b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.svg index ee89152..da10df4 100644 --- a/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.svg +++ b/docs/keycloak-session-store/final/assets/version-conditional-results/version-conditional-results.svg @@ -51,24 +51,24 @@ - -세션을 여기 쓴다 + +세션 기록 - -세션이 여기 있다 + +세션 보관 persistent-user-sessions 켜짐 -세션을 DB 에 쓴다 +세션 → DB persistent-user-sessions 꺼짐 -세션이 메모리에만 있다 +세션 → 메모리 diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.alt.md b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.alt.md index 79c7a31..def014b 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.alt.md +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.alt.md @@ -10,13 +10,13 @@ ## Elements and evidence -- **예측을 먼저 적는다** (process): 결과를 보고 나면 정직하게 쓸 수 없다. Evidence: L744–L752. -- **주입이 걸렸는지 확인** (process): 아무 일도 없었다와 영향이 없다를 가른다. Evidence: L744–L752. -- **대조군을 잡는다** (process): 가장 자주 어겨졌고 가장 비쌌다. Evidence: L744–L753. +- **예측 선기록** (process): 결과를 보고 나면 정직하게 쓸 수 없다. Evidence: L744–L752. +- **주입 검증** (process): 아무 일도 없었다와 영향이 없다를 가른다. Evidence: L744–L752. +- **대조군 확보** (process): 가장 자주 어겨졌고 가장 비쌌다. Evidence: L744–L753. - **결론** (component): 세 단계를 거친 것만 남긴다. Evidence: L744–L753. ## Relationships -- **대조군을 잡는다 → 결론:** 귀속. Evidence: L744–L753. -- **예측을 먼저 적는다 → 주입이 걸렸는지 확인:** 주입 뒤. Evidence: L744–L752. -- **주입이 걸렸는지 확인 → 대조군을 잡는다:** 관측 전. Evidence: L744–L752. +- **대조군 확보 → 결론:** 귀속. Evidence: L744–L753. +- **예측 선기록 → 주입 검증:** 주입 뒤. Evidence: L744–L752. +- **주입 검증 → 대조군 확보:** 관측 전. Evidence: L744–L752. diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.d2 b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.d2 index 23236e2..8011cf0 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.d2 +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.d2 @@ -1,13 +1,13 @@ # 틀린 예측이 남긴 것 # Question: 예측을 지우지 않고 남기면 무엇이 달라지는가 direction: down -n0: "예측을 먼저 적는다" { +n0: "예측 선기록" { shape: rectangle } -n1: "주입이 걸렸는지 확인" { +n1: "주입 검증" { shape: rectangle } -n2: "대조군을 잡는다" { +n2: "대조군 확보" { shape: rectangle } n3: "결론" { diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.dot b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.dot index 79b5bf4..909493d 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.dot +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.dot @@ -2,9 +2,9 @@ digraph techviz { graph [rankdir=TB, splines=ortho, nodesep=0.55, ranksep=0.85]; node [fontname=Helvetica, fontsize=11, margin="0.18,0.12", style="rounded,filled", fillcolor=white, color="#2d4357", penwidth=1.5]; edge [fontname=Helvetica, fontsize=10, color="#364b5f", penwidth=1.4, arrowsize=0.75]; - n0 [label="예측을 먼저 적는다", shape=box, style="rounded,filled"]; - n1 [label="주입이 걸렸는지 확인", shape=box, style="rounded,filled"]; - n2 [label="대조군을 잡는다", shape=box, style="rounded,filled"]; + n0 [label="예측 선기록", shape=box, style="rounded,filled"]; + n1 [label="주입 검증", shape=box, style="rounded,filled"]; + n2 [label="대조군 확보", shape=box, style="rounded,filled"]; n3 [label="결론", shape=box, style="rounded,filled"]; n0 -> n1 [label="주입 뒤", style=solid]; n1 -> n2 [label="관측 전", style=solid]; diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.drawio b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.drawio index f46db55..342de1f 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.drawio +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.drawio @@ -5,13 +5,13 @@ - + - + - + diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.excalidraw b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.excalidraw index ffa2884..1f2f4f3 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.excalidraw +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.excalidraw @@ -361,11 +361,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "예측을 먼저 적는다\n예측 다섯 개가 틀렸다", + "text": "예측 선기록\n틀린 예측 5건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "예측을 먼저 적는다\n예측 다섯 개가 틀렸다", + "originalText": "예측 선기록\n틀린 예측 5건", "autoResize": true, "lineHeight": 1.25 }, @@ -430,11 +430,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "주입이 걸렸는지 확인\n아홉 번 조용히 실패했다", + "text": "주입 검증\n조용한 실패 9건", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "주입이 걸렸는지 확인\n아홉 번 조용히 실패했다", + "originalText": "주입 검증\n조용한 실패 9건", "autoResize": true, "lineHeight": 1.25 }, @@ -499,11 +499,11 @@ "locked": false, "fontSize": 15, "fontFamily": 5, - "text": "대조군을 잡는다", + "text": "대조군 확보", "textAlign": "center", "verticalAlign": "middle", "containerId": null, - "originalText": "대조군을 잡는다", + "originalText": "대조군 확보", "autoResize": true, "lineHeight": 1.25 }, diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.manifest.json b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.manifest.json index ba77199..40cc9c0 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.manifest.json +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.manifest.json @@ -2,7 +2,7 @@ "harness_version": "0.2.0", "spec_id": "wrong-predictions", "spec_version": "1.1", - "spec_sha256": "1e7e2e947e2590ba086c056c82cf6d3fe4455c4c4137eb380c05c2495396ae8e", + "spec_sha256": "9afb114a63c78ec63e9c3dbafe7c902ccca77be9b9745ddebaf832f1ea2842cd", "source_context": { "document": "docs/keycloak-session-store/final/document.md", "document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe", diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.mmd b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.mmd index 436c10f..084fe2d 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.mmd +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.mmd @@ -1,9 +1,9 @@ %% 틀린 예측이 남긴 것 %% question: 예측을 지우지 않고 남기면 무엇이 달라지는가 flowchart TB - n0["예측을 먼저 적는다"] - n1["주입이 걸렸는지 확인"] - n2["대조군을 잡는다"] + n0["예측 선기록"] + n1["주입 검증"] + n2["대조군 확보"] n3["결론"] n0 -->|"주입 뒤"| n1 n1 -->|"관측 전"| n2 diff --git a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.svg b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.svg index 0dea351..14cf8e3 100644 --- a/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.svg +++ b/docs/keycloak-session-store/final/assets/wrong-predictions/wrong-predictions.svg @@ -61,19 +61,19 @@ 관측 전 -예측을 먼저 적는다 +예측 선기록 -예측 다섯 개가 틀렸다 +틀린 예측 5건 -주입이 걸렸는지 확인 +주입 검증 -아홉 번 조용히 실패했다 +조용한 실패 9건 -대조군을 잡는다 +대조군 확보 diff --git a/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap3-bff-session-csrf.md b/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap3-bff-session-csrf.md index 9a206e2..d35cb06 100644 --- a/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap3-bff-session-csrf.md +++ b/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap3-bff-session-csrf.md @@ -20,62 +20,66 @@ assets: # BFF에서 Browser Token을 제거하고 Session과 CSRF를 처리한 방식 -BFF 구조에서는 브라우저가 access token이나 refresh token을 받지 않는다. 로그인 이후 브라우저는 `AP3_SESSION`으로 BFF를 호출하고, access token과 refresh token은 BFF의 authorized client에 저장된다. +BFF 구조에서는 브라우저가 access token도 refresh token도 받지 않는다. confidential client인 BFF 서버가 code를 교환해 두 토큰을 server-side authorized client에 넣어 두고, 로그인이 끝난 브라우저는 HttpOnly가 붙은 AP3_SESSION 쿠키 하나로 BFF를 부른다. -상태를 변경하는 요청도 session cookie를 사용하게 되면서 CSRF 검증이 추가됐다. 이때 브라우저에는 `XSRF-TOKEN`도 함께 사용된다. 현재 구현에서는 여기까지 확인했고, 재시작이나 여러 replica에서 session을 공유하는 부분은 아직 구현하지 않았다. +토큰이 빠진 자리를 세션 쿠키가 채우면서 브라우저는 상태를 바꾸는 요청에도 쿠키를 자동으로 붙이게 됐고, 그래서 그 요청이 사용자가 보던 화면에서 시작한 것인지 가려낼 CSRF 검증이 새로 필요해졌다. 이때 쓰는 XSRF-TOKEN 값은 스크립트가 읽어 헤더에 다시 넣어야 해서 이 쿠키에는 HttpOnly를 붙이지 않았다. 지금 구현에서 확인한 것은 여기까지이고, 재시작한 뒤 로그인을 유지하는 것과 여러 replica가 세션을 함께 쓰는 것은 아직 구현하지 않았다. ## 관계 - **BFF 인증 구조 설계 기준** - BFF 구조에서 필요한 항목 중 현재 구현된 부분과 아직 구현하지 않은 부분을 확인한다. + 그 기준이 함께 설계하라고 적은 항목 가운데 지금 구현에 들어가 있는 것은 CSRF 검증 하나이고, 나머지는 아직 없다. - **OAuth Token과 Application Session을 구분하는 기준** - `AP3_SESSION`, `XSRF-TOKEN`, server-side access token과 refresh token이 각각 다른 위치에서 사용된다. + AP3_SESSION은 브라우저와 BFF 사이에서, access token은 BFF와 Resource Server 사이에서 쓰이고, XSRF-TOKEN은 상태를 바꾸는 요청에서만 대조된다. - **OAuth/OIDC 인증 패턴 선택 기준** - 브라우저에 OAuth token을 전달하지 않는 대신 BFF가 session과 token을 관리하고, 상태 변경 요청에는 CSRF 검증이 필요하다. + 이 구조를 고르면 브라우저에서 OAuth token이 사라지는 대신 BFF가 세션과 토큰을 든 보안 구성요소가 되고, 상태 변경 요청마다 CSRF 검증이 붙는다. - **BFF가 OAuth Token을 관리하는 조건** - access token과 refresh token을 BFF가 보관하고 Resource Server 호출도 BFF가 수행하는 구조를 실제로 확인한다. + 그 결정이 적은 대로 BFF가 code를 교환해 두 토큰을 보관하고 Resource Server도 BFF가 부르는지 이 구성에서 확인했다. - **서버 세션 기반 인증 구조는 다중 인스턴스에서 어떻게 운영할 것인가** - 현재 session과 authorized client가 모두 process-local memory에 있다는 점에서 시작한다. + 지금 세션과 authorized client는 한 프로세스의 메모리에 있어서, 인스턴스를 늘리면 그 상태를 어디에 둘지부터 정해야 한다. - **BFF의 Session과 OAuth2AuthorizedClient를 어디에 저장할 것인가** - HttpSession과 authorized client가 서로 다른 방식으로 조회되고 저장된다. + HttpSession은 session ID로 찾고 authorized client는 client registration 이름과 principal name으로 찾아서, 두 상태를 꼭 같은 저장소에 둬야 하는 것은 아니다. ## 문제 -BFF에서는 confidential client인 BFF 서버가 code를 교환하고 access token과 refresh token을 server-side authorized client에 저장한다. 브라우저에는 HttpOnly AP3_SESSION이 전달된다. +브라우저에 OAuth token을 두지 않으려면 code 교환과 token 보관을 서버가 맡아야 한다. BFF 구조에서는 confidential client인 BFF 서버가 code를 교환하고, access token과 refresh token을 server-side authorized client에 넣는다. 브라우저가 받는 것은 HttpOnly가 붙은 AP3_SESSION 쿠키다. -브라우저는 이후 요청마다 이 session cookie를 BFF로 보낸다. 상태를 변경하는 요청에서도 cookie는 자동으로 전송되기 때문에 session cookie만 확인해서는 해당 요청이 원래 페이지에서 보낸 요청인지 구분할 수 없다. 그래서 상태 변경 요청에는 CSRF 검증이 추가된다. +토큰이 사라진 자리를 이 세션 쿠키가 대신하면서 브라우저는 이후 요청마다 쿠키를 자동으로 붙인다. 상태를 바꾸는 요청에서도 마찬가지라, 세션 쿠키만 봐서는 그 요청이 사용자가 보던 화면에서 시작한 것인지 알 수 없다. 그래서 상태 변경 요청에는 CSRF 검증이 새로 붙는다. -현재 session과 authorized client는 memory에 저장되어 있다. BFF를 재시작하거나 요청이 다른 replica로 이동하는 경우까지 처리하려면 이 상태를 어디에 저장할지도 따로 정해야 한다. +서버가 들고 있게 된 상태에도 둘 곳이 필요하다. 지금 session과 authorized client는 모두 memory에 있어서, BFF를 재시작하거나 요청이 다른 replica로 가는 경우까지 처리하려면 이 상태를 어디에 저장할지 따로 정해야 한다. -브라우저에서 OAuth token을 제거한 뒤 실제로 브라우저에 무엇이 남고 BFF에서 추가로 처리해야 하는 부분이 무엇인지 확인했다. +그래서 브라우저에서 OAuth token을 없앤 뒤 브라우저에 무엇이 남는지, BFF가 무엇을 더 맡게 되는지 확인했다. ## 결론 -브라우저에서는 두 개의 cookie를 사용한다. +브라우저에 남는 자격 증명은 cookie 2개다. -AP3_SESSION : HttpOnly, JavaScript 읽기 x +AP3_SESSION : HttpOnly, JavaScript 읽기 x XSRF-TOKEN : JavaScript 읽기 o -AP3_SESSION은 브라우저가 요청을 보낼 때 자동으로 포함된다. 상태 변경 요청에서는 XSRF-TOKEN의 값을 X-XSRF-TOKEN 헤더에도 넣고 BFF가 이를 확인한다. JavaScript에서 값을 읽어 헤더에 넣어야 하기 때문에 XSRF-TOKEN은 HttpOnly가 아니다. +AP3_SESSION은 브라우저가 BFF로 요청을 보낼 때마다 자동으로 실린다. 상태를 바꾸는 요청에서는 XSRF-TOKEN의 값을 X-XSRF-TOKEN 헤더에도 넣어야 하고 BFF가 그 둘을 대조한다. 스크립트가 쿠키 값을 읽어 헤더에 넣어야 하기 때문에 XSRF-TOKEN에는 HttpOnly를 붙이지 않았다. -XSS가 없어지는 것은 아니다. same-origin의 악성 script는 AP3_SESSION을 직접 읽을 수는 없지만, 브라우저가 session cookie를 붙인 상태로 BFF를 호출하게 할 수 있다. XSRF-TOKEN은 JavaScript에서 읽을 수도 있다. +토큰이 브라우저에서 사라졌다고 XSS까지 없어지지는 않는다. 같은 출처에서 실행되는 악성 script는 AP3_SESSION을 직접 읽지 못하지만 브라우저가 session cookie를 붙인 채 BFF를 부르게 만들 수 있고, XSRF-TOKEN은 아예 읽을 수 있다. 이 구조가 줄이는 것은 브라우저로 새어 나간 access token과 refresh token 원문을 다른 client에서 쓰거나 Resource Server로 바로 보내는 재사용이다. -이 구조에서 브라우저에 전달되지 않는 것은 access token과 refresh token 원문이다. 그래서 브라우저에서 유출된 OAuth token을 다른 client에서 사용하거나 Resource Server에 직접 보내는 형태의 재사용은 줄어든다. +브라우저에서 덜어낸 일 가운데 지금 BFF에 들어가 있는 것은 CSRF 검증 하나다. 나머지 일곱은 아직 없다. -현재 추가로 구현된 부분은 CSRF 검증이다. - -재시작 뒤 로그인 유지, replica 공유 session, 저장 token 암호화, logout, downstream 오류 변환, timeout, 경로별 인가 : x +재시작 뒤 로그인 유지 : x +replica 공유 session : x +저장 token 암호화 : x +logout : x +downstream 오류 변환 : x +timeout : x +경로별 인가 : x ## 검증 환경 Keycloak 26.7.0 realms -confidential, client_secret_basic +client : confidential, client_secret_basic PKCE S256 : o provider : authorization-code, refresh-token -store : memory o +store : memory CSRF : o HTTP : o @@ -110,7 +114,7 @@ HTTP : o ## 본문 -이 기록은 브라우저에서 OAuth 토큰을 없앤 구조에서 브라우저에 무엇이 남고 서버가 무엇을 더 맡게 되는지 확인한 것이다. BFF(Backend For Frontend)는 화면에 필요한 API를 브라우저 대신 호출하고 결과만 돌려주는 서버이고, 여기서는 로그인과 토큰 보관까지 이 서버가 맡는다. 먼저 브라우저에 남는 값부터 보고, 그 값으로 시작한 요청이 보호 자원 서버(Resource Server)로 가는 Bearer 요청이 되기까지를 따라간 다음, 상태를 바꾸는 요청에서 새로 필요해진 검사와 아직 구현하지 않은 항목을 적는다. +BFF(Backend For Frontend)는 화면에 필요한 API를 브라우저 대신 호출하고 결과만 돌려주는 서버이고, 여기서는 로그인과 토큰 보관까지 이 서버가 맡는다. 브라우저에서 OAuth 토큰을 걷어내면 브라우저에는 무엇이 남고 서버는 무엇을 더 맡게 되는지 확인했다. 먼저 브라우저에 남는 값부터 보고, 그 값으로 시작한 요청이 보호 자원 서버(Resource Server)로 가는 Bearer 요청이 되기까지를 따라간 다음, 상태를 바꾸는 요청에서 새로 필요해진 검사와 아직 구현하지 않은 항목을 적는다. ## 브라우저에는 쿠키 2개만 남는다 diff --git a/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap4-identity-header-trust.md b/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap4-identity-header-trust.md index cb5a3e1..353f748 100644 --- a/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap4-identity-header-trust.md +++ b/docs/keycloak/tech-log-studio/oauth-oidc-auth-boundary/case/case-ap4-identity-header-trust.md @@ -18,44 +18,38 @@ assets: # Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유 -X-Auth-Request-User는 인증을 마친 edge가 만들 수도 있고 공격자가 직접 적어 보낼 수도 있다. -upstream이 받는 요청에서는 두 경우의 모양이 같다. -그래서 header overwrite, backend direct path 차단, internal credential 검증을 서로 독립된 세 곳에 둔다. +앞단에 세운 프록시가 로그인을 대신 받으면 upstream은 OAuth를 몰라도 되고, 대신 요청에 붙어 온 X-Auth-Request-User 하나로 사용자를 판단한다. 이 헤더는 인증을 마친 프록시가 붙일 수도 있고 브라우저가 직접 적어 보낼 수도 있는데, 두 값은 upstream이 받은 요청에서 이름도 형식도 같아 서로 구분되지 않는다. + +그래서 이 구성에서는 헤더를 믿을 조건을 세 곳에 나눠 두었다. 밖에서 들어오는 길을 Nginx 8088 하나로 줄이고, Nginx가 클라이언트의 동명 헤더를 자기 값으로 덮어쓰고, upstream이 사용자 헤더와 함께 내부 토큰까지 대조한다. 세 곳은 각각 다른 구간을 맡아서 하나가 나머지 둘을 대신하지 못한다. ## 관계 - **Forward-Auth에서 Identity Header를 신뢰하기 위한 조건** - 이 기준의 다섯 조건이 실제로 어떻게 구성되는지 코드와 설정으로 확인한 자리다. + 그 기준이 세운 다섯 조건을 Nginx 설정과 upstream 코드에서 하나씩 찾아 어디에 들어가 있는지 확인했다. - **OAuth Token과 Application Session을 구분하는 기준** - proxy session cookie와 identity 헤더를 JWT와 구분해야 하는 실례다. + 프록시 세션 쿠키 AP4_SESSION과 identity 헤더가 각각 다른 구간에서 쓰이고, upstream은 JWT를 입력으로 받지 않는다. - **OAuth/OIDC 인증 패턴 선택 기준** - OAuth를 모르는 upstream 앞의 공통 관문을 얻고 network·헤더 신뢰 계약을 내주는 경우다. + 이 구조를 고르면 OAuth를 모르는 upstream 앞에 공통 관문이 생기는 대신, 네트워크 경로와 헤더를 어디까지 믿을지를 따로 정해 두어야 한다. - **Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가** - edge가 user와 email만 전달한다는 사실이 이 질문의 출발점이다. + 지금 edge는 사용자와 이메일만 넘기고 role은 넘기지 않는데, 그러면 인가를 어디서 판단할지가 남는다. ## 문제 -앞단 proxy가 로그인을 맡으면 upstream은 OAuth를 몰라도 된다. +앞단 프록시가 로그인을 맡으면 upstream은 OAuth를 몰라도 되고, 대신 요청에 붙어 온 X-Auth-Request-User 하나로 사용자를 판단하게 된다. 그러려면 upstream은 이 헤더를 인증을 마친 edge가 붙였는지 브라우저가 직접 적어 넣었는지 가릴 수 있어야 한다. -대신 upstream은 X-Auth-Request-User 하나로 사용자를 판단하게 된다. -이 헤더는 인증을 마친 edge가 만들 수도 있고 공격자가 요청에 직접 적어 보낼 수도 있다. -upstream이 받는 요청에서는 둘이 구분되지 않는다는 점이 문제가 된다. +가릴 방법이 없다. 두 값은 upstream이 받은 요청에서 이름도 형식도 같고, 어느 쪽이 붙였는지 적힌 자리가 없기 때문이다. -backend port가 외부에 열려 있거나 Nginx가 브라우저의 헤더를 그대로 넘기면 -공격자가 인증된 사용자처럼 보낼 수 있다. - -그래서 이 구조의 문제는 upstream이 X-Auth-Request-User의 출처를 구분할 수 없다는 점이다. +그래서 backend port가 외부에 열려 있거나 Nginx가 브라우저의 동명 헤더를 그대로 넘기면, 공격자가 원하는 이름을 적어 인증된 사용자처럼 요청을 보낼 수 있다. ## 결론 -헤더를 믿으려면 서로 독립된 세 곳에서 막아야 한다. +헤더를 인증 근거로 쓰려면 서로 독립된 세 곳에서 막아야 한다. -host port 닫힘 : 외부에서 upstream·proxy로 바로 가는 경로를 막는다 +host port 닫힘 : 외부에서 upstream과 프록시로 바로 가는 경로를 막는다 Nginx header 덮어쓰기 : client가 보낸 동명 헤더를 merge하지 않고 덮어쓴다 upstream internal token : edge를 거치지 않은 내부 요청을 막는다 -network isolation만으로는 내부 workload나 잘못된 proxy 헤더가 신뢰되는 문제를 막지 못한다. -controller의 공유 token만으로는 외부 직접 접근이 어려워지는 network 속성을 대신할 수 없다. +세 곳은 각각 다른 구간을 맡는다. 네트워크를 나눠 두는 것만으로는 내부 workload가 보낸 요청이나 Nginx가 잘못 넘긴 헤더가 신뢰되는 것까지 막지는 못한다. 컨트롤러가 들고 있는 공유 토큰만으로는 외부에서 upstream으로 바로 가는 경로가 막혀 있다는 네트워크 쪽 성질을 대신할 수 없다. ## 검증 환경 @@ -71,7 +65,7 @@ app 8081, oauth2-proxy 4180 : Compose network에 expose만, host publish x Nginx auth_request /oauth2/auth location = /oauth2/auth : internal -auth_request_set으로 user, email, Set-Cookie 복사 +auth_request_set : user, email, Set-Cookie 복사 client 제공 동명 헤더 : 덮어쓰기 trusted proxy : 단일 IP @@ -83,46 +77,46 @@ SecurityConfig의 /edge/** : permitAll AP4_SESSION HttpOnly : true SameSite : Lax -Secure : false in local HTTP fixture -expire : 1 hour in proxy configuration +Secure : false, local HTTP fixture 기준 +expire : 1 hour, 프록시 설정값 session-cookie-minimal : true server-side session store : x automatic discovery : x -login, token, JWKS, userinfo URL을 각각 관리. +login, token, JWKS, userinfo URL : 각각 따로 관리 HTTP : o ## 재현 조건 -1. cookie 없이 GET /를 부르면 /oauth2/start로 302가 되는지 확인. +1. cookie 없이 GET /를 부르면 /oauth2/start로 302가 되는지 확인한다. -2. cookie 없이 GET /api/edge를 부르면 Location 없는 401이 되는지 확인. +2. cookie 없이 GET /api/edge를 부르면 Location 없는 401이 되는지 확인한다. -3. authorization request에 client_id=edge-proxy와 code_challenge_method=S256이 있는지 확인. +3. authorization request에 client_id=edge-proxy와 code_challenge_method=S256이 있는지 확인한다. -4. 로그인 뒤 cookie가 AP4_SESSION이며 HttpOnly와 SameSite=Lax인지 확인. -브라우저 요청 목록에 Keycloak token endpoint가 없어야 함. -Web Storage가 비어 있고 document.cookie로 session cookie를 읽을 수 없어야 함. +4. 로그인 뒤 cookie가 AP4_SESSION이며 HttpOnly와 SameSite=Lax인지 확인한다. +브라우저 요청 목록에 Keycloak token endpoint가 없어야 한다. +Web Storage가 비어 있어야 하고 document.cookie로 session cookie를 읽을 수 없어야 한다. -5. 정상 session에 다음 헤더를 얹어 GET /api/edge를 보냄. +5. 정상 session에 다음 헤더를 얹어 GET /api/edge를 보낸다. X-Auth-Request-User : spoofed-admin X-Auth-Request-Email : spoofed-admin@example.test X-Internal-Auth-Token : attacker-controlled-token -응답은 200이고 user는 spoofed-admin이 아니라 실제 authenticated user여야 함. +응답은 200이고, 응답의 user는 spoofed-admin이 아니라 실제로 인증된 사용자여야 한다. -6. 외부에서 GET /oauth2/auth를 부르면 404인지 확인. +6. 외부에서 GET /oauth2/auth를 부르면 404인지 확인한다. -7. host의 4180과 8081에 접근할 수 없는지 확인. +7. host의 4180과 8081에 접근할 수 없는지 확인한다. 8. 내부에서 /edge/me를 부를 때 user 헤더만 있거나 internal token이 없거나 틀리면 401이고, -둘 다 맞으면 200인지 확인. +둘 다 맞으면 200인지 확인한다. ## 본문 -이 기록은 앞단 프록시가 로그인을 맡는 구성에서 upstream이 받은 사용자 헤더를 어디까지 믿을 수 있는지 확인한 것이다. forward-auth는 실제 요청을 upstream으로 넘기기 전에 별도의 인증 엔드포인트에 허용 여부를 묻는 방식이고, Nginx에서는 `auth_request` 디렉티브가 그 질문을 subrequest로 만든다. 이 두 낱말만 알면 따라올 수 있고, 나머지 용어는 쓰는 자리에서 푼다. 먼저 위조 요청의 모양부터 보고, 그것을 막는 세 곳을 하나씩 따라간 뒤, 지금 확인한 범위와 확인하지 않은 범위를 나눠 적는다. +forward-auth는 실제 요청을 upstream으로 넘기기 전에 별도의 인증 엔드포인트에 허용 여부를 묻는 방식이고, Nginx에서는 `auth_request` 디렉티브가 그 질문을 subrequest로 만든다. 이 두 낱말만 알면 따라올 수 있고, 나머지 용어는 쓰는 자리에서 푼다. 먼저 위조 요청의 모양부터 보고, 그것을 막는 세 곳을 하나씩 따라간 뒤, 지금 확인한 범위와 확인하지 않은 범위를 나눠 적는다. ## 같은 이름의 헤더가 두 곳에서 만들어진다 @@ -131,7 +125,7 @@ X-Internal-Auth-Token : attacker-controlled-token 앞단 프록시가 로그인을 맡으면 upstream은 OAuth를 몰라도 된다. 로그인과 세션 검증은 앞단에 세운 oauth2-proxy가 맡는데, 이렇게 로그인을 대신 받는 관문을 edge라고 부른다. upstream은 요청에 붙어 온 `X-Auth-Request-User` 하나로 사용자를 판단한다. 이 헤더는 oauth2-proxy가 확인한 로그인 사용자의 이름을 담아 edge가 upstream 요청에 붙이는 값이다. -문제는 같은 이름의 헤더를 브라우저도 직접 적어 보낼 수 있다는 점이다. upstream이 받는 요청에서 두 값은 이름도 형식도 같고, 어느 쪽이 붙였는지 적힌 자리가 없다. 그래서 이 구조의 문제는 upstream이 `X-Auth-Request-User`의 출처를 구분할 수 없다는 점이다. 백엔드 포트가 외부에 열려 있거나 Nginx가 브라우저의 헤더를 그대로 넘기면 공격자가 인증된 사용자처럼 보낼 수 있다. +같은 이름의 헤더는 브라우저도 직접 적어 보낼 수 있다. upstream이 받는 요청에서 두 값은 이름도 형식도 같고, 어느 쪽이 붙였는지 적힌 자리가 없다. 그래서 upstream은 `X-Auth-Request-User`가 edge에서 온 값인지 브라우저가 적어 넣은 값인지 가리지 못한다. 백엔드 포트가 외부에 열려 있거나 Nginx가 브라우저의 헤더를 그대로 넘기면 공격자가 인증된 사용자처럼 보낼 수 있다. ### 상태 코드가 아니라 응답의 user로 판정한다