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>
4.4 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source, module, priority
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | evidenceCapturedOn | assets | evidence | source | module | priority | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CASE | grpc-core-api-f05 | 메타데이터 예산의 두 성분 중 하나는 강제되지 않고, 나머지 하나는 바이트가 아니라 문자를 센다 | contract-domain-and-bounds | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | case:grpc-core-api-f05 | 2026-09-01 |
|
|
|
grpc-core-api | P3 |
메타데이터 예산의 두 성분 중 하나는 강제되지 않고, 나머지 하나는 바이트가 아니라 문자를 센다
GrpcMetadataBudget 은 세 성분을 갖는다 — maxTotalBytes·maxUserDefinedBytes·maxEntries. check(...) 가 보는 것은 뒤의 둘뿐이다.
문제
GrpcMetadataBudget 은 세 성분을 갖는다 — maxTotalBytes·maxUserDefinedBytes·maxEntries.
check(...) 가 보는 것은 뒤의 둘뿐이다.
결론
저장소 전체에서 이 접근자를 부르는 곳은 compact constructor 의 순서 가드와 테스트 단언 하나뿐이다.
자바독은 그 이유를 설명한다 — 하드 총계를 넘기는 것은 프레임워크가 던지는 전송 거절이고, 여기서 함께 검사하면 "고칠 수 있는 쪽" 과 "고칠 수 없는 쪽" 이 한 자리에서 발견된다는 것.
판단은 옳다.
다만 그 결과로 이 record 는 자기가 쓰지 않는 수를 성분으로 들고 있고, 이름은 그것이 강제된다고 읽힌다.
성분 이름은 ...Bytes 인데 세는 것은 String.length(), 즉 UTF-16 코드 단위다.
키는 [a-z0-9._-] 로 제한되어 ASCII 지만 값에는 문자 집합 제약이 없다.
다중 바이트 문자를 담은 값은 실제 프레임보다 적게 계산된다.
gRPC 의 ASCII 메타데이터 값은 프로토콜 상 인쇄 가능 ASCII 여야 하므로 실무에서는 대개 일치한다.
검증 환경
OpenJDK : 21.0.12 java -version 으로 확인 Gradle : 9.0.0 src/gradle/wrapper/gradle-wrapper.properties 의 distributionUrl 로 확인 확인 방식 : GrpcMetadataBudget 참조 26건 검색과 check 가 실제로 보는 성분 확인 소스 수정 : x
재현 조건
원문은 analysis/grpc/grpc-core-api.md#L219 에 있다.
본문
GrpcMetadataBudget 은 세 성분을 갖는다 — maxTotalBytes·maxUserDefinedBytes·maxEntries. check(...) 가 보는 것은 뒤의 둘뿐이다. 저장소 전체에서 maxTotalBytes 접근자를 부르는 곳은 compact constructor 의 순서 가드와 테스트 단언 하나뿐이다.
GrpcMetadataBudget 참조 위치
:::evidence key="grpc-core-api-f05" alt="코드베이스에서 GrpcMetadataBudget 를 검색한 출력 26줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="GrpcMetadataBudget 코드베이스 검색 — 26줄 · exit 0" zoom="true" :::
그 판단은 옳다
자바독이 이유를 설명한다 — 하드 총계를 넘기는 것은 프레임워크가 던지는 전송 거절이고, 여기서 함께 검사하면 "고칠 수 있는 쪽" 과 "고칠 수 없는 쪽" 이 한 자리에서 발견된다. 다만 그 결과로 이 record 는 자기가 쓰지 않는 수를 성분으로 들고 있고, 이름은 그것이 강제된다고 읽힌다.
이름은 Bytes 인데 세는 것은 문자다
String.length(), 즉 UTF-16 코드 단위다. 키는 [a-z0-9._-] 로 제한되어 ASCII 지만 값에는 문자 집합 제약이 없으므로, 다중 바이트 문자를 담은 값은 실제 프레임보다 적게 계산된다.
실무에서는 대개 일치한다
gRPC 의 ASCII 메타데이터 값은 프로토콜 상 인쇄 가능 ASCII 여야 한다. 다만 그 제약을 이 클래스가 검사하지 않으므로, 일치는 보장이 아니라 관행이다. 수정은 둘 다 작다 — value.getBytes(StandardCharsets.US_ASCII).length 로 세거나 값의 문자 집합을 GrpcMetadataKey.Kind.ASCII 에 맞춰 검증하고, maxTotalBytes 는 성분에서 빼고 javadoc 의 서술로 남긴다.
확인하지 못한 것
다국어 헤더 값으로 문자 수와 바이트 수의 차이를 실행으로 관측하지 않았다. 계산 대상의 코드 형태로 판정했다.