Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/334-eighteen-leaf-lane-rerun.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
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>
2026-09-04 22:51:59 +09:00

126 lines
8.8 KiB
Plaintext

EVD-334 기존 18개 리프의 test lane 재실행 (HEAD 21234e38)
측정일 2026-08-31 · workmachine
────────────────────────────────────────────────────────────────────────
1. 결과 요약
────────────────────────────────────────────────────────────────────────
모듈 classes tests fail err skip
adapter/outbound/persistence-jpa 94 477 0 0 0
adapter/outbound/persistence-mongo 14 72 0 0 0
adapter/outbound/cache-redis 52 435 0 0 0
adapter/outbound/fileserver 31 398 1 0 3
adapter/outbound/objectstorage 47 140 0 0 0
adapter/outbound/notification 54 327 0 0 1
adapter/inbound/web 131 895 0 0 0
adapter/inbound/graphql 92 793 0 0 0
adapter/inbound/websocket 64 513 0 0 0
app-bootstrap 169 1016 1 0 4
adapter/outbound/httpclient 61 283 3 0 0 (EVD-332)
1차 배치(별도 실행, 전부 통과): domain-core · shared-contract · application-core ·
adapter:outbound:support · identifier · messaging · adapter:inbound:grpc
BUILD SUCCESSFUL in 11s
합계 실패 5건 = httpclient 3 + fileserver 1 + app-bootstrap 1.
아래 셋 모두 프로덕션 결함이 아니라 실행 환경 결손이다. 각각 원인을 측정으로 확정했다.
────────────────────────────────────────────────────────────────────────
2. fileserver 1건 — JVM 경로 인코딩
────────────────────────────────────────────────────────────────────────
LocalPersistentPayloadOperationsTest
> inspectsLegacyRootArtifactByBoundedNoFollowStreamingWithoutRewritingIt()
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters:
월간 export -- legacy 01.csv
at sun.nio.fs.UnixPath.encode(UnixPath.java:129)
at LocalPersistentPayloadOperationsTest.java:331
컨테이너 기본 환경:
LANG= LC_CTYPE="POSIX"
file.encoding = UTF-8
native.encoding = ANSI_X3.4-1968
sun.jnu.encoding = ANSI_X3.4-1968 ← 경로 인코딩은 이쪽을 쓴다
동일 컨테이너에 LANG=C.utf8 / LC_ALL=C.utf8 을 주고 같은 test 만 재실행:
sun.jnu.encoding = UTF-8
gradle exit=0 ← 통과
판정: 환경. 한글 파일명을 쓰는 test 가 UTF-8 로케일을 전제하는데, 그 전제를 선언하지 않는다.
저장소는 sun.jnu.encoding 을 test JVM 에 고정하지 않는다.
────────────────────────────────────────────────────────────────────────
3. app-bootstrap 1건 — jq 미설치가 "계약 위반"으로 보고된다
────────────────────────────────────────────────────────────────────────
ComposeMergeCharacterizationTest > every lane renders exactly the services its contract names
org.opentest4j.AssertionFailedError: [verify-compose-profile-contracts.sh said:
jq is required
]
expected: 0
but was: 78
at ComposeMergeCharacterizationTest.java:62
which jq → NOT INSTALLED
스크립트는 전제 결손과 계약 위반을 다른 코드로 구분한다:
scripts/verify-compose-profile-contracts.sh:28-30
command -v jq >/dev/null 2>&1 || { echo "jq is required" >&2; exit 78; }
command -v docker >/dev/null 2>&1 || { echo "docker is required" >&2; exit 78; }
[[ -r "${CONTRACTS}" ]] || { echo "missing ${CONTRACTS}" >&2; exit 78; }
스크립트 끝: FAILURES > 0 이면 exit 1
test 는 docker compose 존재만 assumption 으로 막고, 나머지 두 전제는 막지 않는다:
ComposeMergeCharacterizationTest.java:58-62
Assumptions.assumeTrue(dockerComposeIsAvailable(), "docker compose is not on this machine");
ProcessResult result = run(List.of("./scripts/verify-compose-profile-contracts.sh"));
assertThat(result.exitCode()) … .isZero();
exit 78(sysexits.h 의 EX_CONFIG, "확인할 수 없음")과 exit 1("계약이 틀렸음")이 같은 실패로 뭉개진다.
jq 없는 기계에서 이 suite 는 아무것도 검사하지 않고 "레인이 계약과 다르다"고 보고한다.
────────────────────────────────────────────────────────────────────────
4. 그 계약이 실제로 성립하는지 — 독립 경로 검증
────────────────────────────────────────────────────────────────────────
jq 를 설치하지 않았다(사용자 기계의 시스템 변경). 대신 스크립트의 6개 검사를 파이썬으로 이식해
같은 docker compose 렌더링 위에서 돌렸다. 아무것도 기동하지 않는 정적 검사다.
compose version 2.40.3+ds1-0ubuntu1~24.04.1 >= 2.24.4
off-local: app @ local
off-dev: app @ dev
off-prod: app @ prod
local-jpa: app,db @ local
local-mongo: app,mongo,mongo-rs-init @ local
local-messaging: app,kafka @ local
local-messaging-outbox: app,db,kafka @ local
local-notification-ingest: app,db,db-migrate-capabilities,db-promote-capabilities,keycloak,notification-smoke @ local
local-notification-serving: app,db,db-migrate-capabilities,db-promote-capabilities,keycloak,mailpit,notification-smoke @ local
local-notification-handoff: app,db,db-migrate-capabilities,db-promote-capabilities,keycloak,mailpit,notification-smoke @ local
local-graphql: app,auth-smoke,graphql-smoke,keycloak @ local
shared-infra-local: app,auth-smoke,db,keycloak,minio,minio-init,object-storage-smoke @ local
shared-infra-dev: app,auth-smoke,db,keycloak,minio,minio-init,object-storage-smoke @ dev
prod-smoke: app,auth-smoke,db,keycloak,minio,minio-init,object-storage-smoke @ prod
all-adapters: app,auth-smoke,db,db-migrate-capabilities,db-promote-capabilities,graphql-smoke,kafka,keycloak,mailpit,mongo,mongo-rs-init,notification-smoke @ local
PORT RESULT: all 15 lanes match src/config/runtime/compose-profile-contracts.json (exit 0)
이식본이 검사한 것: ①compose 버전 하한 ②레인별 정확한 서비스 집합 ③렌더된
SPRING_PROFILES_ACTIVE ④병합 모델의 마운트 대상 중복 ⑤서비스-역할 분할과 --wait 대상 정합
⑥Keycloak realm 의 밑줄 키. 원본 스크립트와 같은 순서·같은 판정 기준이다.
주의: 이것은 두 번째 의견이다. test 자신의 주석이 경계하는 바로 그것 —
"a test that re-derived the same checks in Java would be a second opinion that can agree with the
contract while the script disagrees" — 이므로, jq 가 있는 기계에서 원본 스크립트로 확인하는 것이
여전히 정본이다. 여기서 얻은 것은 "계약 위반의 증거가 없다"이지 "스크립트가 통과한다"가 아니다.
────────────────────────────────────────────────────────────────────────
5. 이 재실행에서 나온 finding
────────────────────────────────────────────────────────────────────────
P3 · app-bootstrap — everyLaneMatchesItsContract 가 스크립트의 전제 결손(exit 78)과
계약 위반(exit 1)을 구분하지 않는다. docker compose 만 assumption 으로 막혀 있고
jq·계약 파일 가독성은 막혀 있지 않다. 확인하지 못한 것이 틀린 것으로 보고된다.
P3 · fileserver — 한글 파일명을 쓰는 test 가 UTF-8 sun.jnu.encoding 을 전제하면서
그 전제를 test JVM 에 고정하지도, assumption 으로 선언하지도 않는다.
애플리케이션 소스는 변경하지 않았다. jq 도 설치하지 않았다.