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>
7.8 KiB
Tech-Log candidate recall audit — cycle 2
대상:
/shared/document-detail/clean-architecture-backend-template의 canonical module SSOT 61편 목적: 61개 SSOT 에서 발견된 material semantic unit 이candidate-ledger.json에서 전부 설명되는지에 대한 coverage proof. 판정 기준: verifier 가 인벤토리하는 앵커(analysis/**/*.md의P1|P2|P3헤딩과 미해결 질문 절의 번호 항목)마다EMITTED | MERGED | REJECTED | BLOCKED중 하나가 존재해야 한다.unaccounted는 0 이어야 한다.
전체 수치
| 항목 | 값 |
|---|---|
| canonical module SSOT | 61 / 61 |
| verifier inventory 앵커 | 425 |
| 그중 nested leaf SSOT | 226 |
| §17 explicit finding (61 SSOT) | 392 |
| candidate ledger total | 605 |
| EMITTED | 555 |
| MERGED | 49 |
| REJECTED | 0 |
| BLOCKED | 1 |
| unaccounted | 0 |
모듈별
| module | explicit findings | CASE | OPEN QUESTION | DECISION | CONCEPT | REFERENCE | MERGED | REJECTED | BLOCKED | unaccounted |
|---|---|---|---|---|---|---|---|---|---|---|
adapter-inbound-graphql |
12 | 9 | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 |
adapter-inbound-grpc |
2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
adapter-inbound-web |
19 | 16 | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 |
adapter-inbound-websocket |
3 | 2 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
adapter-outbound-cache-redis |
11 | 7 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | 0 |
adapter-outbound-fileserver |
6 | 4 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
adapter-outbound-httpclient |
7 | 6 | 0 | 0 | 0 | 1 | 2 | 0 | 0 | 0 |
adapter-outbound-identifier |
6 | 5 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
adapter-outbound-messaging |
2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
adapter-outbound-notification |
11 | 9 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
adapter-outbound-objectstorage |
6 | 3 | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 |
adapter-outbound-persistence-jpa |
34 | 26 | 1 | 0 | 0 | 0 | 7 | 0 | 0 | 0 |
adapter-outbound-persistence-mongo |
28 | 24 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | 0 |
adapter-outbound-support |
6 | 3 | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
app-bootstrap |
2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
application-core |
4 | 1 | 2 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
domain-core |
2 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
grpc-admin |
4 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
grpc-advanced-bootstrap |
6 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-advanced-compat |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-advanced-diagnostics |
3 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-advanced-edition |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-advanced-resilience |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-advanced-streaming |
3 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-client |
4 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-codegen |
5 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-core-api |
6 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-discovery |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-observability |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-operation-ledger-jpa |
3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-policy |
8 | 10 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
grpc-proto-contract |
5 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-server |
4 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-spring-boot-starter |
4 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
grpc-testkit |
6 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
messaging-admin-api |
9 | 9 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
messaging-admin-runtime |
11 | 12 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-claim-check |
5 | 2 | 1 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-cloudevents |
5 | 1 | 1 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-core-api |
6 | 4 | 2 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
messaging-inbox-jdbc-postgresql |
6 | 4 | 1 | 0 | 1 | 4 | 0 | 0 | 0 | 0 |
messaging-kafka |
6 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
messaging-kafka-share-experimental |
6 | 1 | 1 | 0 | 0 | 4 | 0 | 0 | 0 | 0 |
messaging-nats-experimental |
4 | 6 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 0 |
messaging-observability |
7 | 5 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
messaging-outbox-jdbc-postgresql |
8 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
messaging-policy |
7 | 3 | 1 | 0 | 0 | 3 | 0 | 0 | 0 | 0 |
messaging-pulsar-experimental |
3 | 4 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-rabbit |
5 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
messaging-reliability-api |
8 | 4 | 1 | 0 | 1 | 4 | 0 | 0 | 0 | 0 |
messaging-runtime-core |
7 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | 0 |
messaging-schema-api |
3 | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-schema-avro |
5 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 0 |
messaging-schema-json |
3 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
messaging-schema-protobuf |
4 | 1 | 1 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
messaging-security |
8 | 5 | 1 | 0 | 0 | 5 | 0 | 0 | 0 | 0 |
messaging-spring-boot-starter |
6 | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
messaging-spring-cloud-stream-bridge |
6 | 0 | 1 | 0 | 0 | 5 | 0 | 0 | 0 | 0 |
messaging-testkit |
8 | 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
messaging-transport-spi |
4 | 2 | 0 | 0 | 1 | 4 | 0 | 0 | 0 | 0 |
shared-contract |
5 | 0 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 합계 | 392 | 313 | 22 | 1 | 6 | 60 | 35 | 0 | 0 | 0 |
candidate 0건 모듈
없음 — 61개 모듈 전부 최소 1건.
분류 근거
kind 는 임의로 정하지 않았다. 우선순위는 다음과 같다.
- SSOT 자신의 kind hint. 다수의 리프 SSOT 가 finding 말미에
- **다음 단계.** … CASE 후보 / REFERENCE 후보 / OPEN QUESTION 후보를 적어 둔다. 그 힌트가 있으면 그것을 따랐다(88건). verifier 도 같은 힌트를allowedKinds로 강제하므로, 힌트와 어긋난 kind 는 실패로 잡힌다. - 힌트가 없으면 finding 의 성격. 구체적 사건·재현 가능한 결함은 CASE, 재사용 가능한 판단 기준은 REFERENCE, 현재 근거로 닫을 수 없는 질문은 OPEN QUESTION.
- P1/P2/P3 는 kind 를 정하지 않는다. 우선순위는 candidate 의
priority로만 남는다.
MERGED 판정 기준
MERGED 는 causal unit · semantic unit · verification unit 이 모두 같을 때만 썼다. "주제가 비슷하다" 는
근거가 아니다. 예로 messaging-kafka 의 트랜잭션 검증기 미배선 · 일시정지 파티션 재개 누락 · 오염된 재시도 헤더의
무한 pause · 트랜잭션 레거시 API 잔존은 전부 독립 노드로 냈다. 같은 리프의 신뢰성 주제라는 것은 병합 근거가 아니다.
§17 밖 recall
문제 finding 외에 다음 절도 검토 대상이었다 — 모듈 정체와 경계, 계약·불변식, 상태 모델, 성공/실패 메커니즘, transaction/concurrency/lifecycle, negative-space 결과, "확인된 설계(문제 아님)", 소스 주석에 남은 결함 이력.
여기서 나온 CONCEPT/REFERENCE/DECISION 은 TOPIC 17~22 에 있다(CONCEPT 5 · CASE 17 · REFERENCE 11). 정상 설계에서 뽑은 CONCEPT 의 예 — 능력 선언의 세 출처, 원자 타입 위의 검사 후 실행과 비교 후 교체, bounded/unbounded 오버로드를 나란히 둔 포트, 8단계 종료 순서 계약, 승인·검증·실행의 분리.
kind 별 quota 는 만들지 않았다. 어떤 모듈에 특정 kind 가 0 인 것은 정상이며, 그 경우 위 표의 해당 칸이 0 으로 남고 그 모듈의 finding 이 전부 다른 kind 로 설명된다는 사실이 같은 행에서 확인된다.
integration/family 문서
analysis/19-messaging-platform.md 의 material finding 6건은 leaf candidate 로 환원되지 않는 cross-leaf 사실이라
별도로 disposition 했다 — EMITTED 5(TOPIC 32 cross-leaf-integration-facts), MERGED 1(문서 계약 테스트의
커버리지 경계는 기존 CASE 와 같은 사건·같은 검증 단위).