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>
15 lines
4.1 KiB
JSON
15 lines
4.1 KiB
JSON
{
|
||
"assetKey": "a07-f002-normalize-probe",
|
||
"kind": "terminal",
|
||
"command": "set -e\nD=$(mktemp -d)\ntrap 'rm -rf \"$D\"' EXIT\n\nCP=src/adapter/outbound/identifier/build/classes/java/main\nSRC=src/adapter/outbound/identifier/src/main/java/dev/caskeleton/adapter/outbound/identifier/UuidCodec.java\necho \"# 클래스 산출물이 소스보다 새로운가 : $([ \"$CP/dev/caskeleton/adapter/outbound/identifier/UuidCodec.class\" -nt \"$SRC\" ] && echo yes || echo no)\"\n\ncat > \"$D/NormalizeProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.outbound.identifier.UuidCodec;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic final class NormalizeProbe {\n\n private static final String CANONICAL = \"0190bd6e-7c3e-7abc-8def-0123456789ab\";\n\n public static void main(String[] args) {\n System.out.println(\"java.version = \" + System.getProperty(\"java.version\"));\n System.out.println();\n\n System.out.println(\"[계약이 말하는 두 갈래]\");\n show(CANONICAL);\n show(\"0190BD6E-7C3E-7ABC-8DEF-0123456789AB\");\n show(\"not-a-uuid\");\n show(\"0190bd6e7c3e7abc8def0123456789ab\");\n System.out.println();\n\n System.out.println(\"[정규형에서 한 글자를 지운다]\");\n for (String input : List.of(\n \"0190bd6e-7c3e-7abc-8def-123456789ab\",\n \"0190bd6e-7c3e-7abc-8def-0123456789a\",\n \"0190bd6e-7c3e-7abc-8def-012345678ab\",\n \"0190bd6e7c3e-7abc-8def-0123456789ab\")) {\n show(input);\n System.out.println(\" 원본과 같은가 : \" + CANONICAL.equals(safe(input)));\n }\n System.out.println();\n\n System.out.println(\"[길이가 36이어도 대시 위치가 다르면 같은 경로로 떨어진다]\");\n show(\"0000001-00001-0001-0001-000000000001\");\n System.out.println();\n\n System.out.println(\"[그룹이 규정 자릿수를 넘으면 상위 비트를 버린다]\");\n show(\"100000001-1-1-1-1\");\n show(\"1-1-1-1-1000000000001\");\n System.out.println();\n\n System.out.println(\"[십육진이 아닌 것도 통과한다]\");\n show(\"+1-1-1-1-1\");\n show(\"١-1-1-1-1\");\n System.out.println();\n\n System.out.println(\"[서로 다른 입력이 같은 식별자가 된다]\");\n Map<String, String> byOutput = new LinkedHashMap<>();\n for (String input : List.of(\"1-1-1-1-1\", \"01-01-01-01-01\", \"+1-1-1-1-1\",\n \"00000001-0001-0001-0001-000000000001\", \"1-1-1-1-2\")) {\n byOutput.merge(safe(input), \"\\\"\" + input + \"\\\"\", (a, b) -> a + \", \" + b);\n }\n byOutput.forEach((output, inputs) -> System.out.println(\" \" + output + \" <- \" + inputs));\n System.out.println();\n\n System.out.println(\"[같은 파서를 쓰는 형제 메서드]\");\n System.out.println(\" toUuid(\\\"1-1-1-1-1\\\") = \" + UuidCodec.toUuid(\"1-1-1-1-1\"));\n }\n\n private static String safe(String input) {\n try {\n return UuidCodec.normalize(input);\n } catch (RuntimeException rejected) {\n return rejected.getClass().getSimpleName();\n }\n }\n\n private static void show(String input) {\n String pad = \" \".repeat(Math.max(1, 40 - input.length()));\n try {\n System.out.println(\" normalize(\\\"\" + input + \"\\\")\" + pad\n + \"-> \\\"\" + UuidCodec.normalize(input) + \"\\\"\");\n } catch (RuntimeException rejected) {\n System.out.println(\" normalize(\\\"\" + input + \"\\\")\" + pad\n + \"-> \" + rejected.getClass().getSimpleName() + \": \" + rejected.getMessage());\n }\n }\n}\nJAVA\n\njavac -encoding UTF-8 -cp \"$CP\" -d \"$D\" \"$D/NormalizeProbe.java\"\njava -Dstdout.encoding=UTF-8 -cp \"$D:$CP\" NormalizeProbe",
|
||
"cwd": "/shared/codebase/clean-architecture-backend-template",
|
||
"exitCode": 0,
|
||
"executedAt": "2026-09-02T09:21:32+00:00",
|
||
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
|
||
"raw": "evidence/raw/a07-f002-normalize-probe.txt",
|
||
"svg": "evidence/rendered/a07-f002-normalize-probe.svg",
|
||
"rawSha256": "1a3ef436d76fef9a0cd2465f3bd87fe0984a83d45b6216af5ce6bddaaa52d826",
|
||
"lines": 36,
|
||
"redaction": "none — 밀폐 탐침 실행 출력, 자격증명 없음"
|
||
}
|