The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.2 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, body, assets, evidence, source
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | evidenceCapturedOn | body | assets | evidence | source | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CASE | analysis-finding-a19-f001 | capability 12개 중 main 코드가 읽는 것은 3개, 거부하는 것은 1개 | messaging-and-outbox | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | case:analysis-finding-a19-f001 | 2026-09-01 | case-analysis-finding-a19-f001.body.md |
|
|
|
capability 12개 중 main 코드가 읽는 것은 3개, 거부하는 것은 1개
능력 레코드의 자바독이 없는 능력을 요구하면 플랫폼이 크게 실패한다고 선언한다. 열두 깃발 중 아홉을 주 코드가 읽지 않고, 읽는 셋 중 둘은 거부가 아니라 분기다. 거부하는 것은 하나뿐이다.
관계
- 선언된 Advanced 능력 11개 중 9개는 켜는 방법이 없다 같은 형태의 능력 선언과 실제 어긋남이다.
- 조용히 약해진 보증은 사고 전까지 동작하는 것과 구분되지 않는다 자바독이 적은 근거다.
- 분기와 거부는 다른 답이다 이 사례가 그 규칙의 형태다.
문제
능력 레코드의 클래스 자바독이 계약을 선언한다.
프로파일이 여기 없는 것을 요구하면 플랫폼이 크게 실패한다는 것이다. 가능하면 시작 시점에, 아니면 능력 예외로 실패하지 조용히 저하되지 않는다는 것이다.
그 근거도 적는다. 조용히 약해진 보증은 사고가 나기 전까지 동작하는 보증과 구분되지 않기 때문이라는 것이다.
열두 깃발 전체에 대해 주 코드와 테스트 참조를 셌다.
결론
읽는 것은 셋이다.
순서 있는 흐름은 재시도 결정 엔진에서 읽고, 있으면 순서 보존 재시도를 고른다.
지연 배달도 같은 엔진에서 읽고, 있으면 브로커 지연 방식을 쓴다.
중복 제거 발행은 발행자에서 읽고, 없으면 예외를 던진다.
나머지 아홉은 모든 브로커 어댑터가 선언하지만 주 코드 어디서도 읽지 않는다.
브로커 확인과 복제 또는 지속 증거와 메시지 단위 정산과 배치 정산, 키 기반 순서와 재생과 브로커 트랜잭션과 기본 죽은 편지와 위상 관리다.
읽는 셋 중 둘은 거부가 아니라 분기다.
없으면 재시도 엔진이 조용히 다른 방식을 고른다. 자바독이 조용한 저하라고 부른 그 동작이다.
거부하는 것은 중복 제거 발행 하나뿐이다.
계수에는 주의할 점이 하나 있다. 순서 있는 흐름의 주 참조 다섯 건 중 넷은 프레임워크의 동명 메서드로 잡힌 오탐이다. 실제 깃발 참조는 한 건이다.
판정은 P2 다.
검증 환경
확인 방식 : 깃발별 참조 계수와 동명 오탐 제거 소스 수정 : x
재현 조건
원문은 final/evidence/raw/252 계열에 있다.
- 능력 레코드의 클래스 자바독을 읽는다.
- 열두 깃발 이름을 나열한다.
- 각 이름의 주 참조와 테스트 참조를 센다.
- 동명 메서드로 잡힌 오탐을 제거한다.
- 읽는 지점에서 무엇을 하는지 확인한다.
본문
MessagingCapabilities의 클래스 javadoc이 이 record의 계약을 선언한다.
"When a profile asks for something absent here the platform fails loudly — at startup where possible, otherwise with a capability exception — rather than quietly degrading, because a silently weakened guarantee is indistinguishable from a working one until the incident."
MessagingCapabilities 참조 위치
:::evidence key="analysis-finding-a19-f001" alt="코드베이스에서 MessagingCapabilities 를 검색한 출력 13줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="MessagingCapabilities 코드베이스 검색 — 13줄 · exit 0" zoom="true" :::
12개 플래그의 참조를 전수로 셌다
| 플래그 | main | test | main에서 하는 일 |
|---|---|---|---|
brokerAcknowledgement |
0 | 1 | — |
replicationOrPersistenceEvidence |
0 | 0 | — |
perMessageSettlement |
0 | 1 | — |
batchSettlement |
0 | 0 | — |
orderedStream |
1 | 1 | DefaultRetryDecisionEngine:49 — 있으면 순서보존 재시도 선택 |
keyedOrdering |
0 | 3 | — |
replay |
0 | 2 | — |
delayedDelivery |
1 | 0 | DefaultRetryDecisionEngine:64 — 있으면 BROKER_DELAYED 사용 |
brokerTransaction |
0 | 3 | — |
deduplicatedPublish |
1 | 1 | DefaultMessagePublisher:250 — 없으면 예외 |
nativeDeadLetter |
0 | 1 | — |
topologyManagement |
0 | 0 | — |
읽는 것은 셋, 거부하는 것은 하나
javadoc이 선언한 "fails loudly"가 실제로 성립하는 플래그는 deduplicatedPublish 하나다. P2.
확인하지 못한 것
능력이 없는 브로커로 프로파일을 구성해 각 깃발의 동작 차이를 재현하지 않았다. 참조 계수상 아홉은 차이가 없다.