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>
14 KiB
14 KiB
Tech-Log CONCEPT recall audit — cycle 2
대상: canonical module SSOT 61편. 목적은 "이 프로젝트를 이해하려면 알아야 할, 실제로 구현된 메커니즘"을 CONCEPT 로 회수했는지에 대한 증명이다.
§17 손볼 것은 이 pass 의 입력이 아니다 — CONCEPT 는 SSOT 본문의 메커니즘 절(모듈 정체·경계, 계약·불변식, 상태 모델, 실행 흐름, 성공/실패, 트랜잭션·동시성·수명주기, 설정·활성화, 외부 시스템 상호작용, "확인된 설계(문제 아님)")에서 나온다.
방법
- 61개 SSOT 의 모든
##·###헤딩에서 메커니즘을 이름 짓는 절만 후보로 남겼다. finding 절(P1|P2|P3)과 bookkeeping 절(denominator·완료 조건·coverage ledger·테스트 레인·Source anchors 등)은 제외했다. - 상위 절이 이미 같은 메커니즘을 덮는 하위 절은 MERGED — 예:
5. idempotency, inbox, outbox아래의5.1 idempotency·5.2 inbox·5.3 outbox. - 독립 기록으로 설명할 본문이 부족한 절(정제 후 120자 미만)은 REJECTED.
- quota 는 만들지 않았다. 모듈당 0~60 까지 편차가 있고, 그 편차는 SSOT 의 메커니즘 밀도를 그대로 따른다.
전체 수치
| 항목 | 값 |
|---|---|
| canonical module SSOT | 61 / 61 |
| concept candidate reviewed (메커니즘 절) | 568 |
| EMITTED CONCEPT | 360 |
| MERGED (상위 메커니즘에 흡수) | 138 |
| REJECTED (본문 부족) | 70 |
| 이번 pass 이전 CONCEPT | 26 |
| 최종 CONCEPT | 386 |
| CONCEPT 0건 모듈 | 5 |
모듈별
| module | concept candidates reviewed | emitted CONCEPT | merged | rejected | reason / mechanism summary |
|---|---|---|---|---|---|
adapter-inbound-graphql |
16 | 13 | 0 | 3 | (8.2) 조건 형제 비교 — off 계약의 두 절반 · (8.2) 조건 형제 비교 — 스키마 해시의 생산자와 소비자 · (8.2) 조건 형제 비교 — 연산 정체성을 정하는 두 구현 … |
adapter-inbound-grpc |
1 | 1 | 0 | 0 | (8.3) 중복 메커니즘 — 인증과 예외 처리의 인터셉터 순서 |
adapter-inbound-web |
24 | 19 | 0 | 5 | (8.2) 조건 형제 비교 — 두 자동설정의 게이트 · (8.4) 문서/구현 드리프트 — 모듈 경계 선언과 실제 트리 · (8.1) 도달성 — 신원 모델의 프로덕션 참조 수 … |
adapter-inbound-websocket |
7 | 5 | 0 | 2 | 이 모듈의 형태 — 하나의 leaf, 세 개의 설정 네임스페이 · (8.1) 도달성 — 정책의 실제 적용 지점 · (8.4) 카운트 — `WebSocketFailureCateg … |
adapter-outbound-cache-redis |
13 | 13 | 0 | 0 | 조립의 순서가 클래스 하나에 고정돼 있다 · Confirmed — raw allowlist 기본값은 없는 · Confirmed — "설계상 부재" 주장 6건이 구현·정책 … |
adapter-outbound-fileserver |
8 | 8 | 0 | 0 | Confirmed — 적재 경로는 auto-configurat · Confirmed — codec이 "canonical"을 왕복 · Confirmed — 상태 전이가 인접 행렬이고 termina … |
adapter-outbound-httpclient |
10 | 9 | 1 | 0 | ClientProfileValidator — 34개 위반 · ClientRuntimeRegistry — 세대 교체가 틈 · ObjectBody의 재생 가능성 판정 — 값의 성질이지 … |
adapter-outbound-identifier |
0 | 0 | 0 | 0 | SSOT 본문이 전부 finding 절이다. 유일한 정상 설계 절(가명화기)은 독립 기록으로 낼 만큼의 메커니즘 서술이 없고 키 취급 규칙은 이미 REFERENCE 로 존재한다. |
adapter-outbound-messaging |
4 | 4 | 0 | 0 | 레지스트리가 "닫혀 있다"는 것의 의미 · 봉투 작성이 파서를 거치지 않는다 · 계약이 컴파일되어 닫힌다 … |
adapter-outbound-notification |
10 | 6 | 0 | 4 | "이름 없는 상태"를 없애는 것이 이 sub-scope의 주제 · (8.3) 중복 메커니즘 — 종료 경로 · (8.1) 도달성 — provider가 준 `Retry-Aft … |
adapter-outbound-objectstorage |
9 | 9 | 0 | 0 | Confirmed — "컴파일이 먼저, 생성은 나중"이 실제 · Confirmed — legacy가 세 겹으로 격리돼 있다 · Confirmed — 후보로 본 unguarded split은 … |
adapter-outbound-persistence-jpa |
82 | 58 | 22 | 2 | Sub-scope 02 — API contracts (`api · Capability API — 실행 기능과 지원 등급을 rep · Error API — provider exception을 st … |
adapter-outbound-persistence-mongo |
9 | 9 | 0 | 0 | opt-in은 네 겹이고, 각 겹이 서로 다른 실패를 막는다 · mapping의 나머지는 manifest를 실제로 강제한다 · 실행 scope의 고정된 순서가 이 sub-scope의 중심이 … |
adapter-outbound-support |
9 | 6 | 2 | 1 | 모듈의 정체와 경계 · FailOpenDependencyLogger: 진단을 bu · global masking도 이 보장을 복구하지 않는다 … |
app-bootstrap |
7 | 5 | 0 | 2 | (8.3) 중복 메커니즘 — 세 개의 환경 검증기 · — 다섯 어댑터 범위는 런타임 멤버십 레지스트리와 일치한다 ( · (8.4) 카운트 — .imports 여섯 줄과 다섯 능력 … |
application-core |
17 | 11 | 6 | 0 | 모듈 경계와 빌드 의존성 · authorization: permission과 object · transaction: framework vocabulary … |
domain-core |
3 | 3 | 0 | 0 | 관찰: 재사용 가능한 도메인 “내용”보다 도메인 모델링 계약을 · Runtime reachability / wiring · Success / failure mechanics |
grpc-admin |
4 | 2 | 0 | 2 | 건강 레지스트리 — 낙관에서 시작하지 않는다 · 배수 순서 |
grpc-advanced-bootstrap |
4 | 3 | 0 | 1 | 능력 15종과 등급 4종 · 게이트가 세 조건을 순서대로 본다 · 승격 게이트 |
grpc-advanced-compat |
2 | 0 | 0 | 2 | 두 절 모두 '무엇을 거절하는가'로 finding 성격이고 독립 메커니즘 서술이 아니다. |
grpc-advanced-diagnostics |
5 | 2 | 0 | 3 | 모듈의 정체 · 두 겹의 게이트 |
grpc-advanced-edition |
1 | 0 | 0 | 1 | 메커니즘 절이 '모듈의 정체' 하나이고, 두 레인의 성격은 concept:three-sources-of-a-capability-answer 와 승격 게이트 노드가 덮는다. |
grpc-advanced-resilience |
3 | 2 | 0 | 1 | 헤징 예산 · xDS 시작 가드 |
grpc-advanced-streaming |
2 | 1 | 0 | 1 | 수동 흐름 제어 |
grpc-client |
2 | 0 | 0 | 2 | '세대와 배수' 절이 있으나 본문이 짧다. 그 메커니즘은 concept:check-then-act-on-atomic-types 가 가족 수준에서 덮는다. |
grpc-codegen |
4 | 1 | 0 | 3 | 소비자 컴파일 게이트 |
grpc-core-api |
2 | 1 | 0 | 1 | Stable 모듈 목록과 불변식 |
grpc-discovery |
3 | 1 | 0 | 2 | 생성자가 거부하는 것과 검증기가 보고하는 것 |
grpc-observability |
4 | 3 | 1 | 0 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식 |
grpc-operation-ledger-jpa |
4 | 3 | 0 | 1 | 스키마가 계약이다 · 저장 키와 유니크 제약이 같은 행을 가리킨다 · 상태 전이 |
grpc-policy |
4 | 1 | 0 | 3 | 재개 토큰 — 서명하고, 구분자를 봉인한다 |
grpc-proto-contract |
1 | 0 | 0 | 1 | 메커니즘 절이 '모듈의 정체' 하나뿐이고 본문이 짧다. 이 리프의 실제 메커니즘(규칙 엔진과 게이트)은 TOPIC 3·17 의 CONCEPT 와 CASE 가 이미 덮는다. |
grpc-server |
5 | 1 | 0 | 4 | 인터셉터 순서 계약 |
grpc-spring-boot-starter |
2 | 2 | 0 | 0 | 모듈의 정체와 격리 규칙 · 검증기가 담은 규칙 |
grpc-testkit |
2 | 1 | 0 | 1 | 릴리스 게이트 — 문서가 후속이 아니라 차단 사유다 |
messaging-admin-api |
13 | 7 | 5 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-admin-runtime |
12 | 7 | 4 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-claim-check |
11 | 7 | 3 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-cloudevents |
13 | 8 | 5 | 0 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 패키지/컴포넌트 지도 … |
messaging-core-api |
23 | 8 | 15 | 0 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 패키지/컴포넌트 지도 … |
messaging-inbox-jdbc-postgresql |
15 | 7 | 7 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-kafka |
4 | 2 | 0 | 2 | 소비자 런타임 — 스레드 규율이 설계다 · 커밋은 연속 워터마크로만 전진한다 |
messaging-kafka-share-experimental |
12 | 7 | 4 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-nats-experimental |
2 | 2 | 0 | 0 | 능력 선언 · 프로파일이 스스로 거부하는 것 |
messaging-observability |
12 | 7 | 4 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-outbox-jdbc-postgresql |
13 | 6 | 5 | 2 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-policy |
16 | 9 | 6 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-pulsar-experimental |
2 | 1 | 0 | 1 | 실패 분류 — 타입 있는 신호만 본다 |
messaging-rabbit |
2 | 2 | 0 | 0 | 소비·정착·죽은 편지의 세 규율 · 자격증명은 연결 시도마다 해석된다 |
messaging-reliability-api |
16 | 7 | 8 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-runtime-core |
16 | 7 | 8 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-schema-api |
14 | 7 | 6 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-schema-avro |
12 | 7 | 4 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-schema-json |
11 | 7 | 3 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-schema-protobuf |
9 | 7 | 1 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-security |
14 | 7 | 6 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-spring-boot-starter |
3 | 3 | 0 | 0 | 선택은 닫힌 레지스트리이고, 등록과 조립은 다르다 · 설정이 프로파일이 된다 · 종료 순서가 두 수명 주기의 phase 로 표현된다 |
messaging-spring-cloud-stream-bridge |
14 | 6 | 6 | 2 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
messaging-testkit |
9 | 8 | 1 | 0 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 패키지/컴포넌트 지도 … |
messaging-transport-spi |
13 | 7 | 5 | 1 | 모듈의 정체와 경계 · 의존성과 런타임 배선 · 계약·불변식·상태 모델 … |
shared-contract |
4 | 4 | 0 | 0 | 주요 계약과 불변식 · Permission · Activation and health snapshot … |
| 합계 | 568 | 360 | 138 | 70 |
CONCEPT 0건 모듈과 사유
adapter-outbound-identifier— SSOT 본문이 전부 finding 절이다. 유일한 정상 설계 절(가명화기)은 독립 기록으로 낼 만큼의 메커니즘 서술이 없고 키 취급 규칙은 이미 REFERENCE 로 존재한다.grpc-advanced-compat— 두 절 모두 '무엇을 거절하는가'로 finding 성격이고 독립 메커니즘 서술이 아니다.grpc-advanced-edition— 메커니즘 절이 '모듈의 정체' 하나이고, 두 레인의 성격은concept:three-sources-of-a-capability-answer와 승격 게이트 노드가 덮는다.grpc-client— '세대와 배수' 절이 있으나 본문이 짧다. 그 메커니즘은concept:check-then-act-on-atomic-types가 가족 수준에서 덮는다.grpc-proto-contract— 메커니즘 절이 '모듈의 정체' 하나뿐이고 본문이 짧다. 이 리프의 실제 메커니즘(규칙 엔진과 게이트)은 TOPIC 3·17 의 CONCEPT 와 CASE 가 이미 덮는다.
CONCEPT 와 REFERENCE 를 쌍으로 둔 자리
같은 source 에서 둘 다 나올 수 있다. 이 pass 는 그 둘을 대체 관계로 쓰지 않았다.
| source 메커니즘 | CONCEPT | REFERENCE |
|---|---|---|
| Kafka 연속 워터마크 커밋 | 커밋은 연속 워터마크로만 전진한다 | 완료된 offset 사이에 gap 이 있으면 commit position 을 넘기지 않는다 |
| 자격증명 회전 | 준비 후 교체 후 배수 | 공유 런타임 교체는 준비 → 원자 교체 → 이전 세대 drain 순서로 한다 |
| 원자 타입 위의 갱신 | 검사 후 실행과 비교 후 교체 루프 | Atomic* 타입의 존재는 원자성의 증거가 아니다 |
| bounded/unbounded 오버로드 | 두 형태를 나란히 둔 포트 | 두 형태를 나란히 내놓는 포트는 이미 안전하지 않은 쪽을 고른 것이다 |
| 8단계 종료 계약 | 선언된 순서와 실제 종료 경로 | 선언 순서를 단언하는 테스트는 그 순서를 읽는 코드가 있을 때만 게이트다 |
REFERENCE semantic audit 결과
REFERENCE 105건을 전수 검토했다. 규칙 형태(rule · purpose · scope · exceptions)를 갖추지 못하고 관측 문장으로 남아 있던 41건을 다시 썼다. 그 41건의 규칙 문장은 대부분 SSOT 자신이 괄호로 적어 둔 것이고 (40/41), 나머지 1건은 cycle 1 의 규칙이라 누락된 scope·exceptions 만 채웠다.
재작성 후 105 / 105 가 rule-shaped 다. 구체 사건은 규칙 기록에 섞지 않고 source 의 finding 이 소유한다.