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>
3.6 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, decisionStatus, decidedOn, source
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | decisionStatus | decidedOn | source | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PROJECT_DECISION | one-root-owns-the-master-switch | 마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다 | assembly-ownership | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | decision:one-root-owns-the-master-switch | ADOPTED | 2026-08-30 |
|
마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다
결정문
능력의 활성 여부는 자동설정 루트 하나가 판정하고, 그 루트가 임포트하는 자식 설정은 같은 조건을 갖지 않는다.
판단 이유
같은 속성을 읽는 주체가 여럿이면 각자가 다른 것이 켜졌다고 믿는 상태가 생긴다. mongo 리프에서 실제로 그랬다. 자동설정 임포트 필터와 컴포넌트 스캔되는 퍼시스턴스 설정과 플랫폼 자동설정이 각각 같은 속성을 읽었고, 셋 다 다른 둘이 꺼졌다고 믿는 무언가를 조립할 수 있었다.
자식이 조건을 반복하는 방식은 다음 달에 추가되는 빈이 그 조건을 기억해야 한다는 뜻이다. 기억하지 못한 빈 하나가 꺼진 능력을 부분적으로 켠다.
루트가 조건을 소유하면 그 문제가 구조적으로 사라진다. 자식에 빈이 추가되어도 도달 경로가 루트를 지나므로 자동으로 게이트된다.
그리고 자식을 컴포넌트 스캔에서 빼는 것이 이 구조의 나머지 절반이다. 스캔이 자식 설정을 독립적으로 발견하면 루트를 우회하기 때문이다.
임포트 필터는 권한을 잃고 도구로 남는다. 프레임워크 자신의 자동설정을 후보 집합에서 빼는 일은 어떤 프로젝트 조건보다 먼저 일어나야 하므로 그 자리가 필요하지만, 능력이 켜졌는지 판정하는 것은 그 필터의 일이 아니다.
영향
감수하는 것
스캔 제외와 자동설정 소유를 한 쌍으로 관리해야 한다. 한쪽만 하면 컴포넌트가 어디에도 없게 되고, 이 저장소에서 그 실패가 두 번 일어났다.
루트를 통하지 않는 도달 경로가 생기면 이 구조가 깨진다. 그 경로를 막는 것은 규약이 아니라 스캔 제외 정규식이다.
패키지 접두사로 제외하므로, 제외된 패키지에 새로 만든 클래스는 자동설정이 소유하지 않으면 존재하지 않는다.
얻는 것
꺼짐이 구조적 사실이 된다. 조건을 반복해서 지키는 것이 아니라 도달 경로가 하나뿐이다.
자식에 빈을 추가하는 사람이 마스터 스위치를 몰라도 된다.
근거
- 꺼짐은 조건의 반복이 아니라 구조여야 한다 이 결정을 규칙으로 옮긴 것이다.
- 프레임워크가 기여하는 자동설정까지 세지 않으면 스위치가 아니다 이 결정이 임포트 필터에 남긴 역할이다.
- 스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다 이 구조의 나머지 절반이 빠졌을 때의 결과다.