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.2 KiB
JSON
15 lines
4.2 KiB
JSON
{
|
|
"assetKey": "a19-f008-acl",
|
|
"kind": "terminal",
|
|
"command": "set -e\nset -o pipefail\nS=src/messaging/messaging-security/src/main/java/dev/caskeleton/messaging/security/BrokerAclManifest.java\nstrip() { sed -E 's#^src/[^:]*/src/(main|test)/[^:]*/([^:/]+):([0-9]+):# \\1 · \\2:\\3 #'; }\ncut_range() { awk -v f=\"$2\" -v a=\"$3\" -v b=\"$4\" 'NR>=a && NR<=b {printf \" %s:%d %s\\n\", f, NR, $0}' \"$1\"; }\n\nprintf \" %s : %s 줄\\n\" \"BrokerAclManifest.java\" \"$(wc -l < $S)\"\necho \"# 자바독이 적어 둔 두 검사\"\ncut_range $S BrokerAclManifest.java 12 20\n\necho\necho \"# 그 두 성질에 대응하는 코드가 이 타입 안에 있다\"\ncut_range $S BrokerAclManifest.java 94 95\ncut_range $S BrokerAclManifest.java 98 111\ncut_range $S BrokerAclManifest.java 113 128\ncut_range $S BrokerAclManifest.java 130 140\n\necho\necho \"# 간결 생성자는 그 검사를 하지 않는다\"\ncut_range $S BrokerAclManifest.java 81 87\n\necho\necho \"# 그 세 메서드를 부르는 자리 전부\"\ngit grep -n 'requireApplicationRuntime\\|destructiveGrants()\\|\\.undeclared(\\|\\.missing(' -- 'src/messaging/**/*.java' | strip\necho \" 그중 BrokerAclManifest.java 밖의 main 코드 :\"\no=$(git grep -n 'requireApplicationRuntime\\|destructiveGrants()\\|\\.undeclared(\\|\\.missing(' -- 'src/messaging/**/*.java' | grep -v '/BrokerAclManifest.java:' | grep '/main/' || true)\nif [ -z \"$o\" ]; then echo \" 0 건\"; else echo \"$o\" | strip; fi\n\necho \"# 이 타입을 만들거나 받는 프로덕션 코드\"\nh=$(git grep -n 'BrokerAclManifest' -- 'src/**/*.java' | grep -v '/BrokerAclManifest.java:' | grep '/main/' || true)\nif [ -z \"$h\" ]; then echo \" main 에서 0 건\"; else echo \"$h\" | strip; fi\necho -n \" 자기 파일 밖에서 이 이름이 나오는 파일 수 : \"\ngit grep -l 'BrokerAclManifest' -- 'src/**/*.java' | grep -vc '/BrokerAclManifest.java' || true\ngit grep -l 'BrokerAclManifest' -- 'src/**/*.java' | grep -v '/BrokerAclManifest.java' | sed 's#^src/# #'\necho \" 그 시험이 단언하는 것 :\"\nawk 'NR>=167 && NR<=201 && (/void |assertThat/) {printf \" CredentialRuntimeRegistryTest.java:%d %s\\n\", NR, $0}' \\\n src/messaging/messaging-security/src/test/java/dev/caskeleton/messaging/security/CredentialRuntimeRegistryTest.java\n\necho\necho \"# 파괴적 권한이 값으로 표시되는 방식\"\nawk 'NR>=49 && NR<=66 && (/enum Operation/ || /\\(true\\)/ || /\\(false\\)/) {printf \" BrokerAclManifest.java:%d %s\\n\", NR, $0}' $S\n\necho\necho \"# 기동 시점 검증으로 감싸인 프로파일은 셋이다\"\nfor f in $(git grep -l 'new StartupProfileValidation' -- 'src/**/*.java'); do\n awk -v n=\"$(basename $f)\" '/new StartupProfileValidation/{c=4} c&&c--{printf \" %s:%d %s\\n\", n, NR, $0}' \"$f\"\ndone\n\necho\necho \"# 파괴 연산 자체를 막는 다른 장치\"\ngit grep -n 'DestructiveMessagingAdmin' -- 'src/**/*.java' | strip\nn=$(git grep -l 'implements DestructiveMessagingAdmin' -- 'src/**/*.java' 2>/dev/null | grep -c '/main/' || true)\necho \" 그 인터페이스를 구현하는 main 클래스 : ${n:-0} 건\" \n\necho\necho \"# 브로커에 권한을 질의하는 코드\"\nfor pat in describeAcls DescribeAclsResult AclBinding createAcls AclOperation Authorizer listPermissions checkPermissions; do\n n=$(git grep -l \"$pat\" -- 'src/**/*.java' 2>/dev/null | wc -l || true)\n printf \" %-22s %s 파일\\n\" \"$pat\" \"$n\"\ndone\necho \" 그 0 들의 의미를 정하는 사실 — Kafka AdminClient 자체의 소스 세트별 분포 :\"\ngit grep -l 'org.apache.kafka.clients.admin\\|AdminClient' -- 'src/**/*.java' 2>/dev/null \\\n | sed -E 's#^src/[^/]*/[^/]*/src/([a-zA-Z]+)/.*# \\1#' | sort | uniq -c | sed -E 's#^ *([0-9]+) +(.*)# \\2 : \\1 파일#' || echo \" 0 파일\"\n",
|
|
"cwd": "/shared/codebase/clean-architecture-backend-template",
|
|
"exitCode": 0,
|
|
"executedAt": "2026-09-04T01:21:20+00:00",
|
|
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
|
|
"raw": "evidence/raw/a19-f008-acl.txt",
|
|
"svg": "evidence/rendered/a19-f008-acl.svg",
|
|
"rawSha256": "da6f5d8c0df331580192be6c1240a7842b334d7182b7e3a2dd4a85738252d85c",
|
|
"lines": 125,
|
|
"redaction": "코드베이스 측정으로 교체"
|
|
}
|