Files
document-haness/docs/clean-architecture-backend-template/notes/ssot-depth-audit.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

94 lines
15 KiB
Markdown

# Module SSOT depth audit
- audit date: 2026-08-31
- source revision: `21234e38cdb9a926cbc92bb97a2aee2e4a7d2916`
- included registered leaves: **61**
- excluded leaves: **1** (`sample-portfolio`)
- cycle 1 canonical analysis files for 61 leaves: **20 unique files**
- structural defect: `analysis/19-messaging-platform.md` was shared by 25 leaves, `analysis/20-grpc-platform.md` by 18 leaves.
- target: **61 distinct canonical module SSOTs**, plus optional family/integration documents.
## 판단
현재 문서 세트는 코드베이스 분석과 Root Tree 후보 추출에는 많은 근거를 제공하지만, **각 registered leaf의 장기 Tech Log SSOT라는 새 요구사항은 충족하지 못한다.** 특히 family 문서 두 개는 개별 leaf 책임·계약·실패 경로·테스트 증명 범위를 독립적으로 재개방하기 어렵다.
문서 길이를 persistence-jpa와 동일하게 맞추지는 않는다. 대신 persistence-jpa가 보여준 다음 성질을 기준으로 한다: 측정 가능한 denominator, 내부 package/sub-scope 지도, contract/invariant, 실제 wiring, success/failure mechanics, test가 증명하는 범위, negative-space probes, history/rationale, findings backlog, limitations, exact source/evidence provenance.
`application-core`는 1,021 source/test 파일을 FULL_READ로 기록했지만 379줄 문서 한 개가 23 top-level package를 압축하고 있어 module SSOT로는 보강이 필요하다. `shared-contract`도 82 FULL_READ에 161줄로 주요 contract를 요약해 두어 같은 이유로 보강 대상으로 둔다. 반대로 `domain-core`처럼 production 7개 수준의 작은 leaf는 200여 줄이어도 충분할 수 있다.
## Cycle 2 review matrix
| leaf | source path | review | cycle-1 document size/coverage | reason |
|---|---|---|---|---|
| `domain-core` | `src/domain-core` | `REVALIDATE_EXISTING_SSOT` | 215 lines; full 10 / structural 3 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `shared-contract` | `src/shared-contract` | `DEEPEN_REQUIRED` | 161 lines; full 82 / structural 4 | 단일 leaf 문서는 있으나 source 규모 대비 설명이 요약형; claim-level 추적/내부 sub-scope 보강 필요 |
| `application-core` | `src/application-core` | `DEEPEN_REQUIRED` | 379 lines; full 1021 / structural 0 | 단일 leaf 문서는 있으나 source 규모 대비 설명이 요약형; claim-level 추적/내부 sub-scope 보강 필요 |
| `adapter-outbound-support` | `src/adapter/outbound/support` | `REVALIDATE_EXISTING_SSOT` | 645 lines; full 8 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-persistence-jpa` | `src/adapter/outbound/persistence-jpa` | `REVALIDATE_EXISTING_SSOT` | 4674 lines; full 605 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-persistence-mongo` | `src/adapter/outbound/persistence-mongo` | `REVALIDATE_EXISTING_SSOT` | 1496 lines; full 497 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-identifier` | `src/adapter/outbound/identifier` | `REVALIDATE_EXISTING_SSOT` | 188 lines; full 10 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-fileserver` | `src/adapter/outbound/fileserver` | `REVALIDATE_EXISTING_SSOT` | 656 lines; full 119 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-objectstorage` | `src/adapter/outbound/objectstorage` | `REVALIDATE_EXISTING_SSOT` | 793 lines; full 206 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-cache-redis` | `src/adapter/outbound/cache-redis` | `REVALIDATE_EXISTING_SSOT` | 933 lines; full 390 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-httpclient` | `src/adapter/outbound/httpclient` | `REVALIDATE_EXISTING_SSOT` | 716 lines; full 370 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-messaging` | `src/adapter/outbound/messaging` | `REVALIDATE_EXISTING_SSOT` | 379 lines; full 69 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-outbound-notification` | `src/adapter/outbound/notification` | `REVALIDATE_EXISTING_SSOT` | 1062 lines; full 240 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-inbound-web` | `src/adapter/inbound/web` | `REVALIDATE_EXISTING_SSOT` | 1702 lines; full 638 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-inbound-grpc` | `src/adapter/inbound/grpc` | `REVALIDATE_EXISTING_SSOT` | 244 lines; full 18 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-inbound-graphql` | `src/adapter/inbound/graphql` | `REVALIDATE_EXISTING_SSOT` | 1122 lines; full 534 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `adapter-inbound-websocket` | `src/adapter/inbound/websocket` | `REVALIDATE_EXISTING_SSOT` | 546 lines; full 253 / structural 0 | 개별 SSOT 존재; cycle 2에서 새 completion gate 기준으로 재검증 |
| `app-bootstrap` | `src/app-bootstrap` | `DEEPEN_REVIEW` | 571 lines; full 455 / structural 0 | 개별 SSOT는 있으나 큰 composition leaf라 cycle 2에서 깊이 재검증 필요 |
| `sample-portfolio` | `src/sample-portfolio` | `EXCLUDED` | - | 사용자 지시(2026-08-30): 샘플 모듈은 분석 대상에서 제외. |
| `messaging-core-api` | `src/messaging/messaging-core-api` | `SPLIT_REQUIRED` | 1284 lines; full 46 / structural 49 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-schema-api` | `src/messaging/messaging-schema-api` | `SPLIT_REQUIRED` | 1284 lines; full 13 / structural 2 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-schema-json` | `src/messaging/messaging-schema-json` | `SPLIT_REQUIRED` | 1284 lines; full 5 / structural 1 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-schema-avro` | `src/messaging/messaging-schema-avro` | `SPLIT_REQUIRED` | 1284 lines; full 5 / structural 3 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-schema-protobuf` | `src/messaging/messaging-schema-protobuf` | `SPLIT_REQUIRED` | 1284 lines; full 5 / structural 1 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-cloudevents` | `src/messaging/messaging-cloudevents` | `SPLIT_REQUIRED` | 1284 lines; full 6 / structural 0 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-policy` | `src/messaging/messaging-policy` | `SPLIT_REQUIRED` | 1284 lines; full 18 / structural 14 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-transport-spi` | `src/messaging/messaging-transport-spi` | `SPLIT_REQUIRED` | 1284 lines; full 19 / structural 0 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-runtime-core` | `src/messaging/messaging-runtime-core` | `SPLIT_REQUIRED` | 1284 lines; full 12 / structural 0 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-observability` | `src/messaging/messaging-observability` | `SPLIT_REQUIRED` | 1284 lines; full 13 / structural 4 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-security` | `src/messaging/messaging-security` | `SPLIT_REQUIRED` | 1284 lines; full 14 / structural 3 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-kafka` | `src/messaging/messaging-kafka` | `SPLIT_REQUIRED` | 1284 lines; full 24 / structural 37 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-kafka-share-experimental` | `src/messaging/messaging-kafka-share-experimental` | `SPLIT_REQUIRED` | 1284 lines; full 5 / structural 2 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-rabbit` | `src/messaging/messaging-rabbit` | `SPLIT_REQUIRED` | 1284 lines; full 18 / structural 15 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-reliability-api` | `src/messaging/messaging-reliability-api` | `SPLIT_REQUIRED` | 1284 lines; full 15 / structural 0 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-outbox-jdbc-postgresql` | `src/messaging/messaging-outbox-jdbc-postgresql` | `SPLIT_REQUIRED` | 1284 lines; full 16 / structural 12 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-inbox-jdbc-postgresql` | `src/messaging/messaging-inbox-jdbc-postgresql` | `SPLIT_REQUIRED` | 1284 lines; full 9 / structural 4 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-claim-check` | `src/messaging/messaging-claim-check` | `SPLIT_REQUIRED` | 1284 lines; full 7 / structural 4 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-admin-api` | `src/messaging/messaging-admin-api` | `SPLIT_REQUIRED` | 1284 lines; full 10 / structural 18 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-admin-runtime` | `src/messaging/messaging-admin-runtime` | `SPLIT_REQUIRED` | 1284 lines; full 8 / structural 12 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-pulsar-experimental` | `src/messaging/messaging-pulsar-experimental` | `SPLIT_REQUIRED` | 1284 lines; full 7 / structural 5 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-nats-experimental` | `src/messaging/messaging-nats-experimental` | `SPLIT_REQUIRED` | 1284 lines; full 6 / structural 5 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-spring-cloud-stream-bridge` | `src/messaging/messaging-spring-cloud-stream-bridge` | `SPLIT_REQUIRED` | 1284 lines; full 7 / structural 3 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-spring-boot-starter` | `src/messaging/messaging-spring-boot-starter` | `SPLIT_REQUIRED` | 1284 lines; full 26 / structural 18 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `messaging-testkit` | `src/messaging/messaging-testkit` | `SPLIT_REQUIRED` | 1284 lines; full 16 / structural 7 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-core-api` | `src/grpc/grpc-core-api` | `SPLIT_REQUIRED` | 716 lines; full 3 / structural 38 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-proto-contract` | `src/grpc/grpc-proto-contract` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 11 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-codegen` | `src/grpc/grpc-codegen` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 16 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-policy` | `src/grpc/grpc-policy` | `SPLIT_REQUIRED` | 716 lines; full 21 / structural 61 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-server` | `src/grpc/grpc-server` | `SPLIT_REQUIRED` | 716 lines; full 2 / structural 22 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-client` | `src/grpc/grpc-client` | `SPLIT_REQUIRED` | 716 lines; full 2 / structural 17 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-discovery` | `src/grpc/grpc-discovery` | `SPLIT_REQUIRED` | 716 lines; full 1 / structural 10 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-admin` | `src/grpc/grpc-admin` | `SPLIT_REQUIRED` | 716 lines; full 1 / structural 18 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-observability` | `src/grpc/grpc-observability` | `SPLIT_REQUIRED` | 716 lines; full 2 / structural 5 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-operation-ledger-jpa` | `src/grpc/grpc-operation-ledger-jpa` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 7 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-spring-boot-starter` | `src/grpc/grpc-spring-boot-starter` | `SPLIT_REQUIRED` | 716 lines; full 3 / structural 5 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-testkit` | `src/grpc/grpc-testkit` | `SPLIT_REQUIRED` | 716 lines; full 4 / structural 32 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-bootstrap` | `src/grpc-advanced/grpc-advanced-bootstrap` | `SPLIT_REQUIRED` | 716 lines; full 1 / structural 12 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-edition` | `src/grpc-advanced/grpc-advanced-edition` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 11 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-streaming` | `src/grpc-advanced/grpc-advanced-streaming` | `SPLIT_REQUIRED` | 716 lines; full 1 / structural 19 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-resilience` | `src/grpc-advanced/grpc-advanced-resilience` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 23 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-compat` | `src/grpc-advanced/grpc-advanced-compat` | `SPLIT_REQUIRED` | 716 lines; full 2 / structural 23 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
| `grpc-advanced-diagnostics` | `src/grpc-advanced/grpc-advanced-diagnostics` | `SPLIT_REQUIRED` | 716 lines; full 0 / structural 8 | family 문서가 여러 registered leaf를 동시에 소유함; 개별 canonical SSOT 필요 |
## Completion rule
1. 각 included leaf는 `state.json.scopes[].analysisFile`이 서로 다른 canonical 문서를 가리킨다.
2. family/platform 문서는 `INTEGRATION_ONLY`이며 leaf SSOT를 대체하지 않는다.
3. 큰 leaf는 canonical 문서 + leaf-owned subdocument로 나눌 수 있다.
4. 각 canonical SSOT는 `deep-analysis-standard.md`의 completion gate를 충족한다.
5. 61개 leaf가 모두 COMPLETE 된 뒤 `99-cross-scope.md``final/document.md` → Root Tree를 다시 생성한다.
6. 그 전에는 Tech Log record generation을 금지한다.