{ "assetKey": "a06-f020-tls-stable-probe", "kind": "terminal", "command": "set -e\nD=$(mktemp -d)\ntrap 'rm -rf \"$D\"' EXIT\n\nprintf %s '' > \"$D/logback-off.xml\"\n\ncat > \"$D/TlsReachProbe.java\" <<'JAVA'\nimport com.mongodb.MongoClientSettings;\nimport dev.caskeleton.adapter.outbound.mongo.autoconfigure.MongoPlatformSettings;\nimport dev.caskeleton.adapter.outbound.mongo.autoconfigure.MongoProfileProperties;\nimport dev.caskeleton.adapter.outbound.mongo.client.MongoClientSettingsFactory;\nimport dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialReference;\nimport dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialResolver;\nimport io.micrometer.core.instrument.MeterRegistry;\nimport io.micrometer.core.instrument.simple.SimpleMeterRegistry;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport org.springframework.boot.autoconfigure.AutoConfigurations;\nimport org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;\nimport org.springframework.boot.mongodb.autoconfigure.MongoClientSettingsBuilderCustomizer;\nimport org.springframework.boot.test.context.assertj.AssertableApplicationContext;\nimport org.springframework.boot.test.context.runner.ApplicationContextRunner;\n\npublic final class TlsReachProbe {\n\n /** The URI the module README shows a deployment using. */\n private static final String README_URI = \"mongodb://canary-host:31337/portfolio\";\n\n private static final ApplicationContextRunner BASE =\n new ApplicationContextRunner()\n .withConfiguration(AutoConfigurations.of(\n dev.caskeleton.adapter.outbound.mongo.MongoRootAutoConfiguration.class,\n MongoAutoConfiguration.class))\n .withBean(MeterRegistry.class, SimpleMeterRegistry::new)\n .withPropertyValues(\"ca-skeleton.persistence-mongo.enabled=true\");\n\n public static void main(String[] args) {\n System.out.println(\"[속성 키] 같은 URI 를 두 키로 각각 넣어 본다\");\n hosts(\"spring.mongodb.uri \", \"spring.mongodb.uri=\" + README_URI);\n hosts(\"spring.data.mongodb.uri\", \"spring.data.mongodb.uri=\" + README_URI);\n System.out.println();\n\n MongoProfileProperties profile = MongoProfileProperties.production(\"secret://mongodb/uri\");\n MongoPlatformSettings settings =\n new MongoPlatformSettings(Map.of(\"default\", profile), false, false, null);\n System.out.println(\"[선언] production 프로파일이 말하는 값\");\n System.out.println(\" tlsRequired=\" + profile.tlsRequired()\n + \" stableApiStrict=\" + profile.stableApiStrict()\n + \" connectTimeout=\" + profile.connectTimeout().toMillis() + \"ms\"\n + \" serverSelection=\" + profile.serverSelectionTimeout().toMillis() + \"ms\"\n + \" poolMax=\" + profile.poolMaxSize()\n + \" uuid=\" + profile.uuidRepresentation());\n settings.validate();\n System.out.println(\" 이 선언을 설정 검증이 통과시킨다\");\n System.out.println();\n\n System.out.println(\"[실제] Boot 가 클라이언트를 만들 때 쓰는 설정 (커스터마이저 적용 후)\");\n BASE.withPropertyValues(\"spring.mongodb.uri=\" + README_URI)\n .run(context -> {\n System.out.println(\" 커스터마이저 \" + customizers(context).size() + \"개 적용\");\n print(\" \", effective(context));\n });\n System.out.println();\n\n System.out.println(\"[다른 경로] URI 를 건드리지 않고 ssl 속성만 켠다\");\n BASE.withPropertyValues(\"spring.mongodb.uri=\" + README_URI, \"spring.mongodb.ssl.enabled=true\")\n .run(context -> System.out.println(\n \" spring.mongodb.ssl.enabled=true -> sslEnabled=\"\n + effective(context).getSslSettings().isEnabled()));\n System.out.println();\n\n System.out.println(\"[미도달] 팩토리가 만들었을 설정\");\n print(\" \", new MongoClientSettingsFactory(settings, \"default\", resolver()).create());\n System.exit(0);\n }\n\n private static void hosts(String label, String property) {\n BASE.withPropertyValues(property)\n .run(context -> System.out.println(\n \" \" + label + \" -> \" + effective(context).getClusterSettings().getHosts()));\n }\n\n private static List customizers(\n AssertableApplicationContext context) {\n return context.getBeanProvider(MongoClientSettingsBuilderCustomizer.class)\n .orderedStream().toList();\n }\n\n /** What Boot hands the driver: the base bean with every customizer applied, as Boot does. */\n private static MongoClientSettings effective(AssertableApplicationContext context) {\n MongoClientSettings.Builder builder =\n MongoClientSettings.builder(context.getBean(MongoClientSettings.class));\n customizers(context).forEach(customizer -> customizer.customize(builder));\n return builder.build();\n }\n\n private static void print(String indent, MongoClientSettings built) {\n System.out.println(indent + \"sslEnabled=\" + built.getSslSettings().isEnabled());\n System.out.println(indent + \"connectTimeoutMs=\"\n + built.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)\n + \" serverSelectionTimeoutMs=\"\n + built.getClusterSettings().getServerSelectionTimeout(TimeUnit.MILLISECONDS));\n System.out.println(indent + \"poolMaxSize=\" + built.getConnectionPoolSettings().getMaxSize()\n + \" serverApi=\" + built.getServerApi()\n + \" uuidRepresentation=\" + built.getUuidRepresentation());\n }\n\n private static MongoCredentialResolver resolver() {\n return new MongoCredentialResolver() {\n @Override\n public T withConnectionString(\n MongoCredentialReference reference, Function use) {\n return use.apply(README_URI);\n }\n };\n }\n}\nJAVA\n\nCACHE=/root/.gradle/caches/modules-2/files-2.1\nLOCK=src/adapter/outbound/persistence-mongo/gradle.lockfile\nCP=src/adapter/outbound/persistence-mongo/build/classes/java/main\nwhile IFS= read -r line; do\n coord=${line%%=*}; confs=${line#*=}\n case \",$confs,\" in *\",testRuntimeClasspath,\"*) ;; *) continue ;; esac\n g=${coord%%:*}; r=${coord#*:}; n=${r%%:*}; v=${r##*:}\n jar=$(find \"$CACHE/$g/$n/$v\" -name '*.jar' ! -name '*sources*' ! -name '*javadoc*' 2>/dev/null | head -1)\n [ -n \"$jar\" ] && CP=\"$CP:$jar\"\ndone < <(grep -E '^[a-zA-Z0-9._-]+:[^=]+=' \"$LOCK\")\n\njavac -encoding UTF-8 -cp \"$CP\" -d \"$D\" \"$D/TlsReachProbe.java\"\njava -XX:+EnableDynamicAgentLoading -Dlogback.configurationFile=\"$D/logback-off.xml\" \\\n -Dstdout.encoding=UTF-8 -cp \"$D:$CP\" TlsReachProbe 2>/dev/null", "cwd": "/shared/codebase/clean-architecture-backend-template", "exitCode": 0, "executedAt": "2026-09-02T08:41:57+00:00", "sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916", "raw": "evidence/raw/a06-f020-tls-stable-probe.txt", "svg": "evidence/rendered/a06-f020-tls-stable-probe.svg", "rawSha256": "e652c8a0dd53f80f6f9085475701a2e8834dc69779f8d75c7f9e2787c66e0971", "lines": 21, "redaction": "SVG 렌더러가 secret: 로 시작하는 자격증명 참조 문자열을 가렸다 — 탐침 소스의 리터럴이고 실제 비밀값이 아니다" }