매니페스트가 선언한 inputSchema는 외부가 정하는 입력이다. JSON Schema 검증기는 문서 밖 $ref를 만나면 그 주소로 직접 조회하므로 매니페스트가 서버의 outbound 호출 대상을 정하는 통로가 된다. pattern은 joni와 graal-js가 없어 java.util.regex의 백트래킹 경로로 처리되고, 인증이 없는 경계(ADR-0006)라 호출 빈도를 줄여 주는 계층도 없다. ToolSchemaReferencePolicy가 문서 밖 참조와 미지원 dialect를 막고, ToolSchemaPatternPolicy가 정규식 길이·무한 수량자 개수·중첩 반복을 검사하며 pattern을 쓰는 필드에 maxLength를 요구한다. 길이를 묶을 수 없는 patternProperties는 거부한다. 검사는 ToolMetadata의 표준 생성자 한 곳에서만 한다. Portal 매니페스트 파싱, local 파일 로딩, Redis snapshot 역직렬화가 모두 이 생성자를 지나므로 조회 경로가 늘어도 검사 지점은 하나로 남는다. 위반은 IllegalStateException이라 기존 매니페스트 형식 오류와 같게 다뤄지고 bundle 단위 실패 격리가 그대로 적용된다. 근거와 한계는 ADR-0011, ADR-0012에 있다. ADR-0012가 classpath 근거로 인용하는 docs/sbom도 함께 가져온다. 192개 테스트 전부 통과. 기존 169건은 새 검사에 걸리지 않는다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
4.5 KiB
Markdown
75 lines
4.5 KiB
Markdown
# SBOM — AXHUB MCP&Tool Service
|
|
|
|
- 산출물: `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx` (검토용)
|
|
- 대상: AXHUB MCP Server와 Tool Service의 공통 스택 (Java 21 / Spring Boot 3.5.11)
|
|
- 산출 기준 빌드: `ax-hub-mcp-server@0.1.0`
|
|
- 생성 기준일: 2026-08-18
|
|
|
|
## 대상 범위
|
|
|
|
MCP Server와 Tool Service는 같은 기술 스택과 같은 MCP SDK를 쓰므로 이 SBOM을 공통으로 적용한다.
|
|
`build.gradle`이 직접 선언한 오픈소스는 `io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0`
|
|
하나이며, 이 SBOM은 그 **런타임 전이 의존 전체**와 **빌드 환경**을 담는다. Spring Boot starter
|
|
계열(web / validation / data-redis / actuator)은 glow f/w가 제공하는 플랫폼 구성이라 범위 밖이다.
|
|
|
|
다만 목록은 **MCP Server 빌드(`ax-hub-mcp-server@0.1.0`) 하나에서 산출했다.** Tool Service가 이
|
|
스택 밖의 의존(예: DB 드라이버, 연계 라이브러리)을 추가하면 그만큼은 이 SBOM에 없으므로, 해당
|
|
빌드에서 다시 산출해 합쳐야 한다.
|
|
|
|
| 구분 | 개수 | 내용 |
|
|
|---|---|---|
|
|
| 런타임 의존성 (scope: required) | 12 | 실행 산출물 classpath에 올라가는 라이브러리 |
|
|
| 빌드 환경 (scope: optional) | 2 | JDK 21, Gradle 8.14.3 |
|
|
| 합계 | 14 | |
|
|
|
|
라이선스는 Apache-2.0 9건, MIT 3건, MIT-0 1건, GPL-2.0 with Classpath Exception 1건(JDK)이다.
|
|
라이브러리 12건은 모두 permissive이고, copyleft는 JDK 하나뿐이다. JDK는 Classpath Exception이
|
|
있어 이 JDK로 실행하는 애플리케이션에 소스 공개 의무가 생기지 않는다.
|
|
|
|
JDK 배포판은 표준가이드가 정한 Eclipse Temurin
|
|
(`openjdk21u-jdk_x64_windows_hotspot_21.0.5`)이며, `build.gradle`의 toolchain에
|
|
`vendor = JvmVendorSpec.ADOPTIUM`으로 고정해 다른 배포판으로 빌드되지 않게 했다. 실행 컨테이너도
|
|
같은 계열인 `eclipse-temurin:21-jre`를 쓴다.
|
|
|
|
## 제외 항목
|
|
|
|
제외 항목과 사유는 엑셀 `Exclusions` 시트가 정본이다. 요약하면 다음과 같다.
|
|
|
|
- **test scope와 annotationProcessor** — 선언 4건. 산출물에 포함되지 않는다.
|
|
- `spring-boot-starter-test`, `com.squareup.okhttp3:mockwebserver:4.12.0`,
|
|
`org.junit.platform:junit-platform-launcher` (test scope)
|
|
- `org.springframework.boot:spring-boot-configuration-processor` (annotationProcessor)
|
|
- `joni`, `graal-js`, `graal-sdk` — json-schema-validator의 `optional`. ECMA262 정규식 검증을
|
|
쓰지 않아 해석되지 않으므로 약 50MB가 빠진다.
|
|
- `jakarta.servlet-api:6.1.0` — mcp-core의 `provided`. 산출물에 포함되지 않고 서블릿 컨테이너가 제공한다.
|
|
- `mcp:2.0.0`(aggregate), `mcp-json-jackson3:2.0.0` — Jackson 3 경로를 쓰지 않아 선언하지 않는다.
|
|
자세한 배경은 [mcp-java-sdk-adoption.md](../mcp-java-sdk-adoption.md) 참고.
|
|
|
|
## 산출 방법과 한계
|
|
|
|
버전과 해시는 `build.gradle` 선언에서 출발해 Gradle 로컬 캐시의 실제 `pom`을 따라가 그래프를
|
|
만들고, 캐시된 실제 jar 바이너리에서 SHA-512 / SHA-1을 직접 계산했다. Gradle 배포본의 SHA-256은
|
|
wrapper의 `distributionSha256Sum` 값을 그대로 옮겼다.
|
|
|
|
`gradlew dependencies`로 해석 결과를 대조하려 했으나 sandbox에서 gradle daemon이 뜨지 않아
|
|
(`Unable to establish loopback connection`) 실행하지 못했다. 따라서 다음 버전 정렬은 pom과
|
|
Spring Boot BOM 판독에 근거한 것이며, 빌드 환경에서 한 번 확인해야 한다.
|
|
|
|
```bash
|
|
./gradlew dependencies --configuration runtimeClasspath
|
|
```
|
|
|
|
| 컴포넌트 | pom 요청 버전 | 수록 버전 | 근거 |
|
|
|---|---|---|---|
|
|
| jackson-databind | 2.20.1 (mcp-json-jackson2) | 2.19.4 | Spring Boot 3.5.11 → jackson-bom 2.19.4 |
|
|
| jackson-databind | 2.18.3 (json-schema-validator) | 2.19.4 | 위와 동일 |
|
|
| reactor-core | 3.7.0 (mcp-core) | 3.7.16 | Spring Boot 3.5.11 → reactor-bom 2024.0.15 |
|
|
| slf4j-api | 2.0.16 (mcp-core) | 2.0.17 | Spring Boot 3.5.11 관리 버전 |
|
|
|
|
가장 확인이 필요한 항목은 jackson-databind다. SDK가 요청한 2.20.1이 `io.spring.dependency-management`에
|
|
의해 2.19.4로 내려가므로, initialize / tools/list / tools/call 직렬화 계약 테스트로 동작을 확인한다.
|
|
|
|
CycloneDX 1.5 공식 JSON Schema 원본 대조는 폐쇄망이라 수행하지 않았다. 대신 생성 시점에
|
|
`dependencies`의 모든 `ref` / `dependsOn`이 실재하는 `bom-ref`를 가리키는지, 컴포넌트가 빠짐없이
|
|
`dependencies`에 등장하는지 구조 점검을 통과시켰다.
|