Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/file-transfer-and-storage/case/case-analysis-finding-a09-f006.md
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

4.0 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, body, assets, evidence, source
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn body assets evidence source
CASE analysis-finding-a09-f006 nonce replay 경계가 결과를 읽고 버린다 file-transfer-and-storage clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 case:analysis-finding-a09-f006 2026-09-01 case-analysis-finding-a09-f006.body.md
key file
analysis-finding-a09-f006 ../../../final/evidence/rendered/analysis-finding-a09-f006.svg
../../../final/evidence/raw/analysis-finding-a09-f006.txt
원본 분석 절은 analysis/09-adapter-outbound-objectstorage.md#L589 이다.

nonce replay 경계가 결과를 읽고 버린다

인터페이스가 스스로를 내구적 비교 후 교체 재생 경계라고 부른다. 호출부는 청구 결과를 받아 변수에 담고, 어느 값이든 발행을 그대로 진행한다. 결과가 바꾸는 것은 종결 기록을 쓸지 여부뿐이다.

관계

  • 검사 결과를 읽고 버리면 검사가 아니다 이 사례가 그 규칙의 형태다.
  • 미배선 경계가 문서에만 있고 compile 경로에서 닫히지 않는다 같은 리프의 다른 경계 사례다.
  • 멱등은 결과를 같게 만들지만 경계를 대신하지는 않는다 피해가 제한된 이유이자 그것이 변명이 되지 않는 이유다.

문제

승인 문서의 논스가 한 번만 쓰인다는 성질을 지키는 저장소가 있다.

그 저장소의 청구 메서드를 호출부가 어떻게 쓰는지 확인했다.

결론

청구 결과를 변수에 담고, 다음 줄에서 발행을 부른다.

그다음에야 결과를 본다. 종결 재생이 아니면 종결 기록을 남긴다.

결과 값은 셋이다. 청구됨과 정확한 재생과 종결 재생이다.

어느 값이든 발행은 그대로 진행된다.

즉 청구 결과가 바꾸는 것은 종결 기록을 쓸지 여부뿐이다. 인터페이스 자바독은 자신을 내구적 비교 후 교체 재생 경계라고 부르는데, 경계로서 무엇도 막지 않는다.

실제 피해는 제한적이다.

발행이 연산 키 기반 멱등이다. 이미 소진된 논스로 다시 들어와도 결과는 재생됨이고 두 번째 객체가 생기지 않는다.

그래서 판정은 P3 다.

그럼에도 기록하는 이유는 셋이다.

이름이 약속하는 것과 다르다. 종결 기록에 넘기는 기대 개정 번호가 항상 0 이라 비교 후 교체의 인자로서도 고정값이다. 그리고 승인 문서의 논스가 한 번만 쓰인다는 성질이 이 코드로는 보장되지 않는다.

수정은 종결 재생에서 발행 전에 거부하는 것이다.

검증 환경

확인 방식 : 호출부와 인터페이스 자바독 대조 소스 수정 : x

재현 조건

원문은 final/evidence/raw/154 계열에 있다.

  1. 재생 저장소 인터페이스의 자바독을 읽는다.
  2. 청구 결과 열거값 셋을 확인한다.
  3. 호출부에서 결과가 어떻게 쓰이는지 확인한다.
  4. 발행 호출이 결과보다 앞인지 뒤인지 본다.
  5. 종결 기록에 넘기는 기대 개정 번호가 무엇인지 확인한다.

본문

ClaimResultCLAIMED / EXACT_REPLAY / TERMINAL_REPLAY 셋인데, 어느 값이든 발행은 그대로 진행된다. claim 결과가 바꾸는 것은 terminal 기록을 쓸지 여부뿐이다.

ClaimResult 참조 위치

:::evidence key="analysis-finding-a09-f006" alt="코드베이스에서 ClaimResult 를 검색한 출력 10줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="ClaimResult 코드베이스 검색 — 10줄 · exit 0" zoom="true" :::

경계라고 부르지만 아무것도 막지 않는다

인터페이스 javadoc은 자신을 "Durable compare-and-set nonce replay boundary"라고 부른다.

확인하지 못한 것

소진된 논스로 두 번 들어와 결과가 재생됨이 되는지 실행하지 않았다. 멱등 키 구현상 그 결과가 나온다.