{ "assetKey": "a14-f018-webplatformstartupvalidator-run", "kind": "terminal", "command": "set -e\nset -o pipefail\nD=$(mktemp -d); trap 'rm -rf \"$D\"' EXIT\nC=/shared/codebase/clean-architecture-backend-template\nM=$C/src/adapter/inbound/web\nCACHE=/root/.gradle/caches/modules-2/files-2.1\njava -version 2>&1 | grep version\ncp=\"\"\nwhile IFS= read -r line; do\n coord=${line%%=*}; confs=${line#*=}\n case \",$confs,\" in *\",testRuntimeClasspath,\"*) ;; *) continue ;; esac\n g=${coord%%:*}; rest=${coord#*:}; n=${rest%%:*}; v=${rest##*:}\n jar=$(find \"$CACHE/$g/$n/$v\" -name '*.jar' ! -name '*sources*' ! -name '*javadoc*' 2>/dev/null | head -1) || true\n [ -n \"$jar\" ] && cp=\"$cp:$jar\"\ndone < <(grep -E '^[a-zA-Z0-9._-]+:[^=]+=' \"$M/gradle.lockfile\")\nSIB=$(find \"$C/src\" -path '*/build/libs/*+21234e38cdb9*.jar' ! -name '*-testkit.jar' | sort | tr '\\n' ':')\n\ncat > \"$D/ValidatorProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.inbound.web.admin.platform.WebPlatformSnapshot;\nimport dev.caskeleton.adapter.inbound.web.admin.platform.WebPlatformStartupValidator;\nimport java.util.List;\nimport java.util.Map;\nimport org.springframework.context.annotation.AnnotationConfigApplicationContext;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n/** 검증기를 직접 돌려 보고, 출하 조립이 그것을 빈으로 갖는지 본다. */\npublic final class ValidatorProbe {\n\n /** 출하 루트가 이 리프에 대해 거는 것과 같은 컴포넌트 스캔. CaSkeletonApplication:44. */\n @Configuration(proxyBeanMethods = false)\n @ComponentScan(basePackages = \"dev.caskeleton.adapter.inbound.web.admin\")\n static class ShippingScan {}\n\n /** 시험이 쓰는 것과 같은 모양의 스냅숏. 통제 목록만 갈아 끼운다. */\n private static WebPlatformSnapshot snapshot(Map controls) {\n return new WebPlatformSnapshot(\n \"servlet\",\n List.of(1),\n List.of(\"VALIDATION_FAILED\", \"INTERNAL_ERROR\"),\n Map.of(\"standard\", \"8MiB body\"),\n Map.of(\"global-write\", \"32 concurrent\"),\n List.of(\"sensitive\", \"revalidated\"),\n controls);\n }\n\n public static void main(String[] args) {\n var validator = new WebPlatformStartupValidator(List.of(\"rate-limit\", \"budget\", \"problem-catalog\"));\n\n System.out.println();\n System.out.println(\"[선언된 통제 셋 중 하나가 배선되지 않은 스냅숏을 넣는다]\");\n var missing = snapshot(Map.of(\"rate-limit\", true, \"budget\", true, \"problem-catalog\", false));\n System.out.printf(\" 스냅숏이 보고하는 미설치 통제 : %s%n\", missing.uninstalledControls());\n try {\n validator.validate(missing);\n System.out.println(\" 결과 : 통과\");\n } catch (RuntimeException refused) {\n System.out.println(\" 결과 : \" + refused.getClass().getSimpleName());\n System.out.println(\" \" + refused.getMessage());\n }\n\n System.out.println();\n System.out.println(\"[셋 다 배선된 스냅숏을 넣는다]\");\n var complete = snapshot(Map.of(\"rate-limit\", true, \"budget\", true, \"problem-catalog\", true));\n validator.validate(complete);\n System.out.println(\" 결과 : 통과\");\n\n System.out.println();\n System.out.println(\"[출하 루트와 같은 스캔을 admin 패키지에 걸어 본다]\");\n try (var context = new AnnotationConfigApplicationContext(ShippingScan.class)) {\n System.out.printf(\n \" 올라온 WebPlatformStartupValidator 빈 : %d 개%n\",\n context.getBeanNamesForType(WebPlatformStartupValidator.class).length);\n System.out.printf(\n \" 올라온 WebPlatformSnapshot 빈 : %d 개%n\",\n context.getBeanNamesForType(WebPlatformSnapshot.class).length);\n System.out.println(\" 스캔이 집어 갈 스테레오타입이 두 클래스에 없다.\");\n }\n }\n}\nJAVA\njavac -encoding UTF-8 -cp \"$SIB$cp\" -d \"$D/out\" \"$D/ValidatorProbe.java\" 2>&1 | head -8\nprintf '%s\\n' '' > \"$D/out/logback.xml\"\njava -Dstdout.encoding=UTF-8 -cp \"$D/out:$SIB$cp\" ValidatorProbe 2>&1 | grep -vE '^[0-9]{4}-|^\\s+at |WARN|INFO'\n", "cwd": "/shared/codebase/clean-architecture-backend-template/src", "exitCode": 0, "executedAt": "2026-09-03T08:09:07+00:00", "sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916", "raw": "evidence/raw/a14-f018-webplatformstartupvalidator-run.txt", "svg": "evidence/rendered/a14-f018-webplatformstartupvalidator-run.svg", "rawSha256": "614c3ee7eefb7cfdb9dcacc3d12928b1e9d78083fa49ecd25bea0fda553d177f", "lines": 14, "redaction": "코드베이스 측정과 실행 결과로 교체" }