Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/207-inbound-graphql-autoconfigure-probes.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

182 lines
13 KiB
Plaintext

Sub-scope 01 (inbound-graphql) governance + autoconfigure + moduleboundary + architecture + api
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T08:27:13+00:00
=== OWNED FILES ===
434aeacc2a92ec3f812fd77999192c4410713c8a CLAUDE.md 224
7e3fc1f6019455df9a7a71ebe9ba67182b5cb0fa README.md 224
42cebcf264bcbd74dd6b843a0ea54b6113446b09 build.gradle 174
74f612c854c95a48370a3608825866d192098b1b gradle.lockfile 178
4c01cbfdef67b3705c97570c4c36d762786dd9f1 src/main/java/dev/caskeleton/HealthGraphqlController.java 25
f2c0492b134eab75b7da6067987a10cbee2a88c8 src/main/java/dev/caskeleton/api/GraphQlClientProfile.java 27
86602c8c38d90d35f8e18374efb87eb7de8e6af6 src/main/java/dev/caskeleton/api/GraphQlClientProfileName.java 50
061a5a56bb501104162e08369f27813b395e8f87 src/main/java/dev/caskeleton/api/GraphQlOperationId.java 24
25fbe6e3f919e5635b0173c32202e2a4ec4a38a6 src/main/java/dev/caskeleton/api/GraphQlOperationName.java 43
f9c4a18019af5ca8400bfea60815afc1aa923a64 src/main/java/dev/caskeleton/api/GraphQlSchemaCoordinate.java 61
d1abaaaedf7c0bfb8ae2e6541a82267eec218c61 src/main/java/dev/caskeleton/architecture/GraphQlAsyncReturnShape.java 72
47ba73dfbd1e5c732cd68006bdb53085415b9f4d src/main/java/dev/caskeleton/architecture/GraphQlControllerContractException.java 40
419ab3992b89c8cc5cbb802446b7b5f91998b36a src/main/java/dev/caskeleton/architecture/GraphQlControllerInspector.java 109
770738711cad63f25c19ca686717f36018e0a5b8 src/main/java/dev/caskeleton/architecture/GraphQlControllerTransactionRule.java 81
647166f486151c90a602dd54a571ebb46f3554ab src/main/java/dev/caskeleton/architecture/GraphQlInputTypePolicy.java 44
8986f2fb27b1ff10c3524710c5f863dffd8e450d src/main/java/dev/caskeleton/architecture/GraphQlResolverBoundaryRules.java 313
d4f7e591ad688299691fb26650c4e1c57d8148ec src/main/java/dev/caskeleton/architecture/GraphQlReturnTypePolicy.java 111
fc934d492e2ef4141a0ed46f8db15d96b0bdcb6b src/main/java/dev/caskeleton/architecture/GraphQlTransportTypeRules.java 87
a32cb82a95758cdafa33be8df27dd28a959ecb5d src/main/java/dev/caskeleton/architecture/GraphQlTypeGraph.java 112
346dc5a32d924565420ab6b61ed20595985522d2 src/main/java/dev/caskeleton/autoconfigure/GraphQlActivationEnvironmentPostProcessor.java 75
afae197bac923e62990079f5cd69853a4dde1891 src/main/java/dev/caskeleton/autoconfigure/GraphQlDeploymentMode.java 72
97477157ffdc72e2b41cf964e65a7ff6c74cb709 src/main/java/dev/caskeleton/autoconfigure/GraphQlOffAutoConfigurationImportFilter.java 60
2ad7108f3a7da65ad80031a3ad84651c271bc6fb src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformActuatorEndpoint.java 71
a3a2824a48c2f040bf58c3fe2bc10dfcda010b93 src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformAutoConfiguration.java 704
9f9aff73688ee5e8305dee46eb4c5a138320df65 src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformConfigurationException.java 31
8c0237214cff7d1a49aa664f0baf0e56f409dc1b src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformConfigurationReport.java 55
3cbba44d38253207d5e20ed839ef4de791b4bc81 src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformRuntime.java 43
dd6d37a76d8ecbce963f6d33ef08d8b000b98391 src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformSettings.java 307
bf93f72b05eb35e7c6bb338682f61168fa459683 src/main/java/dev/caskeleton/autoconfigure/GraphQlPlatformStartupValidator.java 185
55b71a3ccc5cbf053e58ca0316c9d35a5546b120 src/main/java/dev/caskeleton/autoconfigure/GraphQlRetiredSafetyAxis.java 62
a012a182cbf836c62382852f4aba7da5a23dbd6d src/main/java/dev/caskeleton/autoconfigure/GraphQlRootAutoConfiguration.java 33
2281a8283a6a70bfcf5bd5272630ec37a6ca5c0d src/main/java/dev/caskeleton/autoconfigure/GraphQlRuntimeTransport.java 44
434b330b37a4a8f0de417237985dd2cd42b311d8 src/main/java/dev/caskeleton/moduleboundary/GraphQlAdvancedModule.java 167
8d7b467dc93277674057822b4b9be70a1d24b9a7 src/main/java/dev/caskeleton/moduleboundary/GraphQlModuleBoundary.java 126
e86b13a08b20fa55da21c76675294c665207db53 src/main/java/dev/caskeleton/moduleboundary/GraphQlModulePurity.java 19
9a9c652043da9eb128ecf9c39d093ab9e325dbdd src/main/java/dev/caskeleton/moduleboundary/GraphQlStableModule.java 225
bc2a2210fa31d43cf623ed3c40f1b3e82f02ec1a src/main/resources/META-INF/spring.factories 4
0a4f208e8a07fb853e9e798007a3fed85c78b1ad src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1
c8093c523d6126bc7f77bdf31e46a7b7f0ed3d26 src/main/resources/graphql/skeleton.graphqls 10
de73f5a1d2eae599e16cbd6e3315abb77297be95 src/test/java/dev/caskeleton/api/GraphQlIdentifiersTest.java 76
d6e0f92cccd62bcab06ea64790db57ab741c20ee src/test/java/dev/caskeleton/architecture/GraphQlControllerInspectorTest.java 117
62b18a7b5fc5f6ae49df4d03876ca37d6c54cc82 src/test/java/dev/caskeleton/architecture/GraphQlGeneratedResolverBoundaryTest.java 114
e5adb01dd691ef265eb0f832dc06bc9eae21a09c src/test/java/dev/caskeleton/architecture/GraphQlResolverBoundaryRulesTest.java 92
68b6e28036582d7c452cd84ed8cfd8bcb873196a src/test/java/dev/caskeleton/architecture/GraphQlResolverGenericBoundaryTest.java 189
8bb61d7384f83054472b5a0d3d68b78f6bfa3aa3 src/test/java/dev/caskeleton/architecture/fixture/compliant/FindOrderUseCase.java 12
a38b669abca65734c5c09af9e836b538119c7b0e src/test/java/dev/caskeleton/architecture/fixture/compliant/OrderGraphQlController.java 31
be295c28ebde5dc0e1469d5386247c1b489907c2 src/test/java/dev/caskeleton/architecture/fixture/compliant/OrderView.java 9
b8584addc14a314faffec67f0a44bb6b6d1c8d0a src/test/java/dev/caskeleton/architecture/fixture/violating/LeakyGraphQlController.java 33
38bac70c896e5248fdde731a32b91e856c08d68b src/test/java/dev/caskeleton/architecture/fixture/violating/OrderRepository.java 12
f91fec9cc5d1b03a5a67701dababbc386519f2a6 src/test/java/dev/caskeleton/architecture/fixture/violating/Transactional.java 17
9a96cc94002d21e9763c80d009430dd7737114c4 src/test/java/dev/caskeleton/autoconfigure/GraphQlBatchLoaderWiringTest.java 54
f84ccbd8d86b7ee09e862316093a4798868e8648 src/test/java/dev/caskeleton/autoconfigure/GraphQlDeploymentModeContractTest.java 274
d0f5181e6b0e8bbb7725bc7fc615ee0d10f2aa9a src/test/java/dev/caskeleton/autoconfigure/GraphQlObservationWiringTest.java 62
73a31121c66bfbdf10aee97e592e33e86bb0d342 src/test/java/dev/caskeleton/autoconfigure/GraphQlPlatformAutoConfigurationTest.java 236
41cc6798cabe1267dbf2dd6708139e49ee41a63f src/test/java/dev/caskeleton/autoconfigure/GraphQlPlatformStartupValidatorTest.java 123
1dcaa60e23659d433354552a0de3bb7aa94c9b8b src/test/java/dev/caskeleton/autoconfigure/GraphQlPolicyRequestPathTest.java 112
ffbb69d6ce2236a42907d39019eb0c0450ab94f5 src/test/java/dev/caskeleton/autoconfigure/GraphQlTransportNeutralityTest.java 201
aca33a89df432c626eab84c545e73eed7931f04e src/test/java/dev/caskeleton/moduleboundary/GraphQlBuildModel.java 293
d324b1bc361a492cfc362ec1d2b8e6eedf9c75c6 src/test/java/dev/caskeleton/moduleboundary/GraphQlModuleBoundaryTest.java 190
143beb792061e08b66e2a2bb2519b771a39dea79 src/test/java/dev/caskeleton/moduleboundary/GraphQlSourceGraph.java 30
file_count=60
=== 8.1 조립 진입점과 컴포지션 루트의 관계 ===
$ cat adapter/inbound/graphql/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
dev.caskeleton.adapter.inbound.graphql.autoconfigure.GraphQlRootAutoConfiguration
exit=0
$ cat adapter/inbound/graphql/src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
dev.caskeleton.adapter.inbound.graphql.autoconfigure.GraphQlOffAutoConfigurationImportFilter
org.springframework.boot.EnvironmentPostProcessor=\
dev.caskeleton.adapter.inbound.graphql.autoconfigure.GraphQlActivationEnvironmentPostProcessor
exit=0
$ grep -n 'graphql' app-bootstrap/src/main/java/dev/caskeleton/bootstrap/CaSkeletonApplication.java
108: + "|dev\\.caskeleton\\.adapter\\.inbound\\.graphql\\..*"
exit=0
$ grep -rn 'inbound.graphql' --include=*.java app-bootstrap/src/main sample-portfolio/src/main | wc -l
0
exit=0
$ grep -n '@Import' -A 12 adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlRootAutoConfiguration.java
23:@Import({
24- GraphQlPlatformAutoConfiguration.class,
25- // The resolver for the schema's only field. It is a @Controller in a package the composition
26- // root's component scan excludes by regex — the exclusion that makes this capability optional —
27- // and no root imported it, so a deployment with GraphQL on served a schema declaring
28- // `_health: String!` with nothing to resolve it. Every query answered
29- // NullValueInNonNullableField. Its own tests passed throughout by registering the class
30- // themselves, which is the shape of the defect rather than a defence against it.
31- dev.caskeleton.adapter.inbound.graphql.HealthGraphqlController.class
32-})
33-public class GraphQlRootAutoConfiguration {}
exit=0
=== 8.2 off 계약: 프레임워크 자동설정 차단 ===
$ grep -c 'org.springframework.boot.graphql.autoconfigure' adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlOffAutoConfigurationImportFilter.java
10
exit=0
$ grep -n 'fails open silently' -B 2 -A 2 adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlOffAutoConfigurationImportFilter.java
16- * one whose project beans are absent while the framework serves it anyway.
17- *
18: * <p>A misspelled entry fails open silently — the filter simply never matches — so the test that
19- * protects this asserts a 404 on the real port rather than checking what this method returns.
20- */
exit=0
$ grep -rn 'backend.graphql.enabled=false' --include=*.java adapter/inbound/graphql/src | wc -l
0
exit=0
$ grep -n 'void \|@DisplayName\|statusCode' app-bootstrap/src/test/java/dev/caskeleton/bootstrap/activation/GraphQlShippedAndGatedTest.java | head -14
34: static void startAllOff() {
43: static void stop() {
50: @DisplayName("the GraphQL facade is on the shipped classpath")
51: void facadeIsShipped() throws ClassNotFoundException {
70: @DisplayName("GraphQL off publishes no endpoint")
71: void graphQlOffPublishesNoEndpoint() throws IOException, InterruptedException {
75: assertThat(graphQl.statusCode())
81: .isEqualTo(neverMapped.statusCode());
82: assertThat(graphQl.statusCode())
88: @DisplayName("GraphQL off holds no schema and no execution bean")
89: void graphQlOffHoldsNothing() {
exit=0
=== 8.3 은퇴한 설정 키를 무시가 아니라 거부 ===
$ grep -n 'RETIRED_KEYS' -A 10 adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlRetiredSafetyAxis.java | head -14
27: private static final Map<String, String> RETIRED_KEYS =
28- Map.of(
29- "backend.graphql.production",
30- "it drove anonymous principal handling and allow-by-default authorization while the "
31- + "environment enum drove introspection, so the two could disagree",
32- "backend.graphql.environment",
33- "it drove introspection and GraphiQL while the production boolean drove authorization, "
34- + "so the two could disagree");
35-
36- private GraphQlRetiredSafetyAxis() {}
37-
--
49: for (String key : RETIRED_KEYS.keySet().stream().sorted().toList()) {
50- if (environment.containsProperty(key)) {
exit=0
=== 8.4 시작 검증 규칙 수와 .imports 메타데이터 고정 ===
$ grep -c 'problems.add' adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlPlatformStartupValidator.java
21
exit=0
$ grep -c '@Bean' adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlPlatformAutoConfiguration.java
39
exit=0
$ grep -c '@ConditionalOn' adapter/inbound/graphql/src/main/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlPlatformAutoConfiguration.java
43
exit=0
$ grep -n 'theAutoConfigurationIsRegisteredInTheImportsMetadata' -A 14 adapter/inbound/graphql/src/test/java/dev/caskeleton/adapter/inbound/graphql/autoconfigure/GraphQlPlatformAutoConfigurationTest.java
186: void theAutoConfigurationIsRegisteredInTheImportsMetadata() {
187- String imports =
188- readClasspathResource(
189- "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
190-
191- assertThat(imports)
192- .as(
193- "the registered entry is the master-gated root, not the platform configuration it "
194- + "imports; registering the platform directly is what let a context assemble a "
195- + "GraphQL endpoint that no switch had asked for")
196- .contains(GraphQlRootAutoConfiguration.class.getName())
197- .doesNotContain(GraphQlPlatformAutoConfiguration.class.getName() + "\n");
198- }
199-
200- @Test
exit=0