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>
6.0 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-a16-f001 | 스키마 조립·계약 정체성·해시 사슬이 통째로 미배선이고, 그것을 발행할 액추에이터 엔드포인트도 등록되지 않는다 | graphql-surface | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | case:analysis-finding-a16-f001 | 2026-09-01 | case-analysis-finding-a16-f001.body.md |
|
|
|
스키마 조립·계약 정체성·해시 사슬이 통째로 미배선이고, 그것을 발행할 액추에이터 엔드포인트도 등록되지 않는다
조립기부터 보고서까지 사슬 전체가 끊겨 있다. 각 단계의 호출자와 생산자와 빈 선언이 모두 0 이다. 그 결과 결정적 병합 순서와 네 부분 계약 정체성과 운영 가시성이 함께 사라진다.
관계
- 시작 검증기가 시작 시 실행되지 않는다 다른 리프의 같은 형태다.
- 5계층 예산 모델에서 요청 계층만 강제되고 나머지 파생이 전부 미배선이다 같은 리프의 다른 미배선 사슬이다.
- 만들어졌으나 아무도 만들지 않는 타입은 계약이 아니다 이 사례가 그 규칙의 형태다.
문제
이 리프는 스키마 조각을 병합해 스키마를 만들고, 그 결과에서 해시를 얻고, 해시를 포함한 계약 정체성을 만들고, 그것을 운영 보고서로 발행하도록 설계되어 있다.
각 단계가 실제로 불리는지 확인했다.
결론
전 단계가 끊겨 있다.
조립 메서드의 호출자가 0 이고, 조립 결과 타입의 생산자가 0 이고, 해시 타입의 생산자가 0 이다.
보고 엔드포인트의 빈 선언이 0 이고, 그 보고서의 발행 경로가 0 이다.
네 부분 계약 정체성 타입의 생성자 호출도 0 이다.
세 가지가 함께 사라진다.
첫째는 결정적 병합 순서다.
스키마 조각의 정렬을 조립기가 강제하도록 설계되어 있는데, 실제로는 프레임워크의 탐색 순서를 그대로 쓴다.
조각이 하나뿐인 지금은 무해하다. 그러나 채택자가 자기 조각을 추가하는 순간 달라진다. 그것이 이 리프의 문서화된 확장 방식이다.
충돌 선언의 승자와 스키마 해시가 포장 방식에 따라 달라질 수 있다.
둘째는 네 부분 계약 정체성이다.
해시만으로는 호환성을 판정할 수 없다는 판단을 타입으로 만들었는데, 그 타입을 만드는 코드가 없다.
호환성 판정이 필요한 릴리스 게이트는 별도의 비교기를 직접 쓴다.
셋째는 운영 가시성이다.
보고 메서드가 배포된 스키마 해시와 실행 프로파일과 배포 모드와 활성 능력과 등록된 연산 및 페치 프로파일 수를 하나의 보고서로 낸다.
등록되지 않으므로 운영자가 이 배포가 무엇을 켜고 있는가를 물을 표면이 없다.
다른 리프의 시작 검증기 사례와 같은 형태다.
거기서는 시작 검증기가 시작 시 실행되지 않았고, 여기서는 보고 엔드포인트가 등록되지 않는다.
두 모듈 모두 파일 서버 하위 트리와 대조된다. 그쪽의 증명 메서드는 부트스트랩에서 실제로 호출된다.
권고는 이렇다.
플랫폼 자동 설정이 이미 서른아홉 빈을 만들고 해시 타입을 세 곳에서 참조하므로 자리는 있다.
스키마 원본이 확정된 뒤 그 정의로 조립기를 돌려 해시를 얻고, 그것으로 엔드포인트를 등록하면 된다.
판정은 P2 다.
검증 환경
확인 방식 : 사슬 각 단계의 호출자와 생산자 계수 소스 수정 : x
재현 조건
원문은 final/evidence/raw/182 계열에 있다.
- 조립 메서드의 호출자를 센다.
- 조립 결과와 해시 타입의 생산자를 센다.
- 보고 엔드포인트의 빈 선언을 검색한다.
- 계약 정체성 타입의 생성자 호출을 센다.
- 릴리스 게이트가 호환성을 어떻게 판정하는지 확인한다.
본문
세 가지가 통째로 미배선이다.
GraphQlSchemaContract 참조 위치
:::evidence key="analysis-finding-a16-f001" alt="코드베이스에서 GraphQlSchemaContract 를 검색한 출력 4줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="GraphQlSchemaContract 코드베이스 검색 — 4줄 · exit 0" zoom="true" :::
1. 결정적 병합 순서
SDL 조각의 정렬을 조립기가 강제하도록 설계돼 있고(§7.4), 실제로는 Spring GraphQL의 탐색 순서를 그대로 쓴다. 조각이 하나(skeleton.graphqls)뿐인 지금은 무해하지만, adopter가 자기 .graphqls를 추가하는 순간 — 그것이 이 leaf의 문서화된 확장 방식이다 — 충돌 선언의 승자와 스키마 해시가 패키징 방식에 따라 달라질 수 있다.
2. 네 부분 계약 정체성
GraphQlSchemaContract가 "해시만으로는 호환성을 판정할 수 없다"는 판단을 타입으로 만들었는데, 그 타입을 만드는 코드가 없다. 호환성 판정이 필요한 곳(릴리스 게이트)은 compat의 비교기를 직접 쓴다.
3. 운영 가시성
GraphQlPlatformActuatorEndpoint.report()가 배포된 스키마 해시 · 실행 프로파일 · 배포 모드 · 활성 능력 · 등록된 연산/페치 프로파일 수를 하나의 보고서로 낸다. 등록되지 않으므로 운영자가 "이 배포가 무엇을 켜고 있는가"를 물을 표면이 없다.
확인하지 못한 것
조각을 추가해 병합 순서가 달라지는 것을 재현하지 않았다. 조각이 하나뿐이라 현재 형상에서는 드러나지 않는다.