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>
2.9 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source, module
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | evidenceCapturedOn | assets | evidence | source | module | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CONCEPT | application-core-c10 | 임의 Object 대신 sealed 변수 대수를 쓴 이유 | schema-and-wire-models | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | concept:application-core-c10 | 2026-09-01 |
|
|
|
application-core |
임의 Object 대신 sealed 변수 대수를 쓴 이유
가변·임의 변수가 serialization/fingerprint drift와 toString 충돌을 만들 수 있었던 것이 변경 근거이고, 그 뒤로 비밀 경계가 계약 바깥에 따로 서 있다.
관계
- legacy storage/notification compatibility surface의 제거 조건 추적 같은 분석 리프에서 끌어낸 규칙이다.
본문
public contract는 arbitrary Object/Map<String,Object>를 허용하지 않고 sealed NotificationVariable algebra를 사용한다. 과거 mutable/arbitrary variable 때문에 serialization/fingerprint drift와 toString collision이 가능했던 것이 변경 근거다.
공개 계약과 비밀이 나뉘는 자리
:::evidence key="application-core-c10-diagram" alt="sealed 변수 대수와 고정된 템플릿 판본과 유계 수신자 수가 공개 알림 계약 안에 놓이고 임의 Object 변수와 연락처 원문이 바깥에 빗금으로 놓인다" caption="공개 계약과 비밀이 나뉘는 자리" zoom="false" :::
이 기록이 다루는 범위
:::evidence key="application-core-c10" alt="코드베이스에서 파일 목록을 만든 출력 25줄. 이 기록이 다루는 범위가 그 목록이다." caption="코드베이스 파일 목록 — 25줄 · exit 0" zoom="true" :::
vacuous pass가 남긴 regression guard
structural test는 public API에 arbitrary Object가 다시 들어오지 않는지 검사하며, 과거 잘못된 test root로 vacuous pass했던 문제도 regression guard로 남아 있다. NotificationPlan은 exact template version을 pin한다. recipient/metadata/variable count/depth가 bounded되어 있고, receipt는 "durable logical acceptance"이지 provider delivery를 의미하지 않는다.
decrypt 실패를 빈 값으로 떨어뜨리지 않는다
contact point는 encrypted value + keyed fingerprint로 분리되고 protected contact rendering은 원문을 노출하지 않는다. template variable 자체에 reset token 같은 secret이 들어갈 수 있어 payload protection이 존재한다. contact lookup/provider request/callback fingerprint는 HMAC purpose를 분리해 동일 secret-purpose reuse를 피한다.