The originating repository's SVGs were drawn by hand and every one of them
put a title, a subtitle and an explanation band inside the canvas. This
repository forbids both, so they could not be carried over — the whole set
was rebuilt through the skill's pipeline instead.
Each diagram went through prepare, references, prompt, a VizSpec 1.1 citing
document line ranges, lint, and render. All 28 pass lint and produce the
same eight formats the existing keycloak project has. Sentences moved out of
the canvas into <desc> and the paragraph beside each figure; the drawings
carry names only.
Two lint rules did real work rather than formatting work:
edge-through-node caught arrows crossing an unrelated
node and implying an adjacency that
does not exist — four diagrams had to
be restructured, not just relaid out
evidence-outside-prepared-context caught a diagram citing another
section; its anchor moved from B-0 to
B-1 so all three sections it draws on
are inside the prepared context
lab-topology also had to change profile: its context offers a different
candidate set, and query-fanout with shard roles is what the section
actually shows — one entry point spreading to two Keycloak nodes.
The document now carries all 28 inline, one per claim that needed one, and
the section recording what was still missing is updated: the diagram gap is
closed, Studio records remain.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
186 lines
5.0 KiB
JSON
186 lines
5.0 KiB
JSON
{
|
|
"version": "1.1",
|
|
"id": "lab-topology",
|
|
"title": "실험대의 구성",
|
|
"question": "이 실험들은 어떤 기계 위에서 돌았는가",
|
|
"type": "architecture",
|
|
"direction": "TB",
|
|
"audience": [
|
|
"같은 실험을 재현하려는 백엔드 엔지니어"
|
|
],
|
|
"summary": "베어메탈 한 대 위의 VM 두 대에 k3s 를 올리고, 호스트 nginx 가 TLS 를 끝낸 뒤 traefik 으로 넘긴다.",
|
|
"alt": "test-server 호스트의 nginx 가 kc-lab-1 의 traefik 으로 프록시하고, 그 아래 두 VM 에 Keycloak 과 데이터 저장소가 나뉘어 있는 구성.",
|
|
"long_description": "베어메탈 test-server 위에 VM 두 대를 올렸다. kc-lab-1 이 k3s server 이자 컨트롤 플레인이고 keycloak-1 이 여기 있다. kc-lab-2 는 agent 이며 keycloak-0 과 PostgreSQL, Redis 가 함께 있다. 저장소가 한 노드에 몰려 있어 그 노드를 잃으면 DB 도 같이 잃는다. 호스트 nginx 가 Let's Encrypt 인증서로 TLS 를 끝내고 traefik 으로 넘기며, 인증서 하나에 auth·app1·app2 세 이름이 SAN 으로 들어 있다.",
|
|
"source_context": {
|
|
"document": "docs/keycloak-session-store/final/document.md",
|
|
"document_sha256": "1d44cba1905544d92f1d26ae36a8deb64a3db3914d6b488fd30d6ae7f8cfbabe",
|
|
"anchor": {
|
|
"kind": "heading",
|
|
"value": "실험대",
|
|
"line": 85
|
|
}
|
|
},
|
|
"composition": {
|
|
"profile": "query-fanout",
|
|
"diagram_only": true,
|
|
"reference_ids": [
|
|
"metrics-query-fanout"
|
|
],
|
|
"rationale": "호스트 nginx 에서 들어온 요청이 traefik 을 거쳐 두 Keycloak 노드로 갈라지는 것이 이 절의 지배적 구조다. 하나의 진입점에서 여러 백엔드로 퍼지는 모양이므로 query-fanout 을 골랐다."
|
|
},
|
|
"groups": [],
|
|
"nodes": [
|
|
{
|
|
"id": "nginx",
|
|
"label": "호스트 nginx",
|
|
"kind": "gateway",
|
|
"role": "source",
|
|
"emphasis": "primary",
|
|
"description": "Let's Encrypt 인증서로 TLS 를 끝내고 traefik 으로 넘긴다.",
|
|
"details": [
|
|
"SAN: auth · app1 · app2"
|
|
],
|
|
"evidence": [
|
|
{
|
|
"start_line": 88,
|
|
"end_line": 92
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "traefik",
|
|
"label": "traefik (kc-lab-1)",
|
|
"kind": "gateway",
|
|
"role": "control",
|
|
"emphasis": "normal",
|
|
"description": "k3s 의 인그레스. 호스트 이름으로 서비스를 고른다.",
|
|
"details": [
|
|
"k3s server 노드"
|
|
],
|
|
"evidence": [
|
|
{
|
|
"start_line": 85,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "keycloak-1",
|
|
"label": "keycloak-1",
|
|
"kind": "service",
|
|
"role": "shard",
|
|
"emphasis": "primary",
|
|
"description": "컨트롤 플레인 노드에 있다.",
|
|
"details": [
|
|
"kc-lab-1"
|
|
],
|
|
"evidence": [
|
|
{
|
|
"start_line": 85,
|
|
"end_line": 86
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "keycloak-0",
|
|
"label": "keycloak-0",
|
|
"kind": "service",
|
|
"role": "shard",
|
|
"emphasis": "primary",
|
|
"description": "저장소와 같은 노드에 있다.",
|
|
"details": [
|
|
"kc-lab-2"
|
|
],
|
|
"evidence": [
|
|
{
|
|
"start_line": 86,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "stores",
|
|
"label": "PostgreSQL · Redis",
|
|
"kind": "datastore",
|
|
"role": "store",
|
|
"emphasis": "warning",
|
|
"description": "둘 다 kc-lab-2 에 있다. 이 노드를 잃으면 저장소도 같이 잃는다.",
|
|
"details": [
|
|
"kc-lab-2"
|
|
],
|
|
"evidence": [
|
|
{
|
|
"start_line": 86,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"edges": [
|
|
{
|
|
"id": "tls",
|
|
"from": "nginx",
|
|
"to": "traefik",
|
|
"label": "TLS 종단",
|
|
"kind": "request",
|
|
"evidence": [
|
|
{
|
|
"start_line": 88,
|
|
"end_line": 92
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "to-k1",
|
|
"from": "traefik",
|
|
"to": "keycloak-1",
|
|
"label": "라우팅",
|
|
"kind": "request",
|
|
"evidence": [
|
|
{
|
|
"start_line": 85,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "to-k0",
|
|
"from": "traefik",
|
|
"to": "keycloak-0",
|
|
"label": "라우팅",
|
|
"kind": "request",
|
|
"evidence": [
|
|
{
|
|
"start_line": 85,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "k0-store",
|
|
"from": "keycloak-0",
|
|
"to": "stores",
|
|
"label": "같은 노드",
|
|
"kind": "read",
|
|
"evidence": [
|
|
{
|
|
"start_line": 86,
|
|
"end_line": 87
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"legend": [],
|
|
"metadata": {
|
|
"rationale": "저장소가 kc-lab-2 한 곳에 몰린 것을 그림에서 읽히게 배치했다. A-4 의 두 결과가 이 배치에서 갈린다."
|
|
}
|
|
} |