egovframe-scaffold-mcp 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -44,7 +44,7 @@ Requires Node.js 18+. Downloads go to `codeload.github.com`, `raw.githubusercont
44
44
  | `EGOVFRAME_ALLOWED_ROOTS` | Optional sandbox: every directory argument (`projectDir`, `outputDir`) must be inside one of these roots (path-separator-delimited, realpath-checked). |
45
45
  | `EGOVFRAME_LANG` | `en` → English tool descriptions in `tools/list`. Responses stay Korean. |
46
46
 
47
- ## Tools (32)
47
+ ## Tools (34)
48
48
 
49
49
  | Tool | What it does |
50
50
  |---|---|
@@ -72,6 +72,8 @@ Requires Node.js 18+. Downloads go to `codeload.github.com`, `raw.githubusercont
72
72
  | `prepare_egovframe_offline_bundle` | For air-gapped (network-separated) environments: on an internet PC, bundle the full OSV Maven dump, the pinned common-components archive, the Initializr zip templates and a mirror of the official common-components tags with a sha256 manifest. On the air-gapped PC set `EGOVFRAME_OFFLINE_BUNDLE`: downloads are served from the bundle after fingerprint checks, OSV lookups use the local dump (snapshot date noted, warning after 30 days) and reassembly uses the mirror. The local dump matched online OSV on 73/73 queries |
73
73
  | `generate_egovframe_sbom` | CycloneDX 1.6 JSON (default) or SPDX 2.3 JSON (`bomFormat="spdx-json"`) SBOM without touching build files — Maven via cyclonedx-maven-plugin (hashes, licenses), Gradle from the resolved tree; baseline verdict per component (`egovframe:*` properties), optional OSV `vulnerabilities[]`; writes inside the project only, `dryRun` by default |
74
74
  | `check_egovframe_sbom` | Check an existing CycloneDX or SPDX 2.x SBOM (format detected) without changing it: the 7 minimum elements (supplier, name, version, unique identifier, dependency relationship, author, timestamp) per component with a ready / needs-work verdict, a purl-only re-check (changed baseline verdicts, OSV findings published since generation), a diff against `baselinePath`, and with `vex=true` a CycloneDX VEX draft (`in_triage`, BOM-Link) that keeps human decisions |
75
+ | `check_egovframe_secure_coding` | Scan sources for security weaknesses from the implementation-stage list of the Korean secure coding guide (MOIS/KISA 2021) that static patterns can find: SQL injection, XSS, path traversal, open redirect, OS commands, XXE, weak crypto, insecure random, hard-coded secrets, cookies, error exposure, empty catch, deserialization, debug code — file, line, CWE, severity, fix and origin (common component original/modified/unmanaged, project, test); exceptions need a reason and reviewer; baseline diff; SARIF 2.1.0. A pattern-based aid, not a certified diagnosis |
76
+ | `generate_egovframe_deploy` | Container and deployment files from the project diagnosis: multi-stage Dockerfile (Classic war unpacked as ROOT on Tomcat 10.1 or 11.0, Boot jar on the Temurin JRE; non-root, HEALTHCHECK; or a prebuilt artifact), `.dockerignore`, `deploy/docker-compose.yml` with a mysql/mariadb/postgres container initialised from the template SQL, and Kubernetes manifests (Deployment with probes and a hardened securityContext, Service, ConfigMap, Secret, optional Ingress). Database settings via Spring environment variables (Boot) or an overridden `globals.properties` (Classic); `imageRegistry` for air-gapped registries. New files only, `dryRun` by default |
75
77
  | `diagnose_egovframe_network` | Probe the hosts the server downloads from, classify failures (DNS, timeout, TLS, proxy auth) and prescribe environment settings as bash/cmd/PowerShell commands |
76
78
  | `generate_agents_md` | `AGENTS.md` for AI coding tools: build/test commands, RTE and migration status, components, rules, available MCP tools (ko/en) |
77
79
 
@@ -115,6 +117,25 @@ Public-sector SBOM submission in Korea is to be institutionalised by 2027. `chec
115
117
 
116
118
  When SPDX is required, `bomFormat="spdx-json"` writes the same content as SPDX 2.3 JSON: packages, `DESCRIBES` and `DEPENDS_ON` relationships (`NONE` for "no dependencies", so it differs from "unknown"), purl/cpe/swid external refs, supplier/originator, creators and created, checksums, declared licenses, OSV advisories (`SECURITY`/`advisory`) and the baseline verdicts (`egovframe:*` annotations). `check_egovframe_sbom` reads SPDX by mapping it onto the same checks (supplier = `PackageSupplier`/`PackageOriginator`, dependency relationship = `DEPENDS_ON` with the package as subject, author = `Person`/`Organization` creators). For the official web template built with real Maven, the SPDX document passes the official spdx-spec v2.3 schema and checks exactly like the CycloneDX one (67 components, same per-element counts, diff 0). VEX stays CycloneDX-only.
117
119
 
120
+ ## Secure coding weaknesses before delivery
121
+
122
+ ```text
123
+ check_egovframe_secure_coding(projectDir) # summary by severity, rule and origin
124
+ check_egovframe_secure_coding(projectDir, sarifPath="egovframe-secure.sarif", overwrite=true) # SARIF 2.1.0 for code scanning
125
+ check_egovframe_secure_coding(projectDir, baselinePath="reports/secure-prev.json") # only new findings
126
+ ```
127
+
128
+ Projects subject to information-system audits in Korea follow the MOIS/KISA software development security guide (2021: 20 design-stage requirements, 49 implementation-stage weaknesses). The tool checks the 14 implementation-stage items that static patterns can find with controlled false positives (20 rules as data in `catalog/secure-coding-rules.json`). Comments are stripped first — all 96 MyBatis `${…}` occurrences in the official common components v4.3.2 turned out to be comments saying they were changed to `#{…}` — and EL inside custom-tag attributes, `<c:out>`, placeholders and `ENC(…)` values are not reported. With the same rules the official common components drop from 516 findings (v4.3.2) to 38 (v5.0.7), and the official web and boot-web templates have none. Exceptions go into `.egovframe-secure-ignore.json` with a reason and reviewer. `generate_egovframe_ci(supplyChain=true, secureCoding=true)` adds a `secure --fail-on high` gate step and uploads the SARIF to GitHub code scanning. Design notes: [docs/design-secure-coding.md](docs/design-secure-coding.md).
129
+
130
+ ## Container and deployment files
131
+
132
+ ```text
133
+ generate_egovframe_deploy(projectDir, dryRun=false)
134
+ generate_egovframe_deploy(projectDir, dryRun=false, imageRegistry="harbor.example.go.kr/dockerhub", buildInImage=false)
135
+ ```
136
+
137
+ The tool writes a Dockerfile, `.dockerignore`, `deploy/docker-compose.yml` and `deploy/k8s/<app>.yaml` from the project diagnosis. Classic projects read `globals.properties` directly, so their WAR is unpacked into the image and a copy of that file (database host and password replaced) is mounted as a volume or Secret; Boot projects read settings through Spring's `Environment`, so `GLOBALS_MYSQL_URL`-style environment variables are enough. In CI, the official web (Classic) and boot-web (Boot) templates pass hadolint and kubeconform, build, start, answer HTTP 200 and report healthy as uid 10001; the official simple-backend starts with MySQL through `docker compose up` and serves the initialised data. Design notes: [docs/design-deploy.md](docs/design-deploy.md).
138
+
118
139
  ## Running in CI (CLI mode)
119
140
 
120
141
  ```bash
@@ -124,7 +145,7 @@ npx -y egovframe-scaffold-mcp sbom --project . --write
124
145
  npx -y egovframe-scaffold-mcp sbom-check --project . --offline=false --fail-on "minimum,newVulns"
125
146
  ```
126
147
 
127
- With no arguments the package starts the MCP stdio server as before; with a command (`assess`, `check`, `sbom`, `sbom-check`, `rehearse`, `bundle`, `migrate`, `validate`, `diagnose`, `network`) it runs that one tool through an in-memory MCP client and exits. Options use the tool parameter names (kebab-case allowed); `--json` prints the same object as MCP `structuredContent`; `--step-summary` appends the Markdown to `$GITHUB_STEP_SUMMARY`; `--fail-on` takes grade (`supplyChain:C`) or count (`vulnerabilities`, `manual>20`) conditions. Exit codes: 0 pass, 2 over the `--fail-on` threshold, 3 execution failure, 64 usage error. Write tools are not exposed. `generate_egovframe_ci(platform, supplyChain=true)` adds the same gate on GitHub Actions, GitLab CI (JUnit and CycloneDX reports, validated against the official GitLab CI schema in the tests) or Jenkins (Declarative, `sh` on Linux and `bat` on Windows agents): SBOM → `sbom-check --fail-on minimum` → assessment above `failOn` fails, with the reports and SBOM kept as artifacts; `npmRegistry` and `offlineBundle` become `NPM_CONFIG_REGISTRY` and `EGOVFRAME_OFFLINE_BUNDLE`. Design notes: [docs/design-cli.md](docs/design-cli.md) (Korean).
148
+ With no arguments the package starts the MCP stdio server as before; with a command (`assess`, `check`, `sbom`, `sbom-check`, `secure`, `rehearse`, `bundle`, `migrate`, `validate`, `diagnose`, `network`) it runs that one tool through an in-memory MCP client and exits. Options use the tool parameter names (kebab-case allowed); `--json` prints the same object as MCP `structuredContent`; `--step-summary` appends the Markdown to `$GITHUB_STEP_SUMMARY`; `--fail-on` takes grade (`supplyChain:C`) or count (`vulnerabilities`, `manual>20`) conditions. Exit codes: 0 pass, 2 over the `--fail-on` threshold, 3 execution failure, 64 usage error. Write tools are not exposed. `generate_egovframe_ci(platform, supplyChain=true)` adds the same gate on GitHub Actions, GitLab CI (JUnit and CycloneDX reports, validated against the official GitLab CI schema in the tests) or Jenkins (Declarative, `sh` on Linux and `bat` on Windows agents): SBOM → `sbom-check --fail-on minimum` → assessment above `failOn` fails, with the reports and SBOM kept as artifacts; `npmRegistry` and `offlineBundle` become `NPM_CONFIG_REGISTRY` and `EGOVFRAME_OFFLINE_BUNDLE`. Design notes: [docs/design-cli.md](docs/design-cli.md) (Korean).
128
149
 
129
150
  ## Reassembling copied common components
130
151
 
package/README.md CHANGED
@@ -13,11 +13,11 @@
13
13
  Claude, VS Code(Copilot), Cursor 등 MCP를 지원하는 AI 도구에서 **대화 중 즉시** 표준프레임워크
14
14
  프로젝트를 만들고 공통컴포넌트·AI 계층을 조립할 수 있습니다. 기존 프로젝트 진단, 리포트, 안전한 upstream 재동기화도 지원합니다.
15
15
 
16
- 현재 v0.43.0은 **도구 32종(title·annotations·구조화 출력 11종) + CLI 명령 10종, 공식 템플릿 22종, 설정 템플릿 21종, 5.x 전환 규칙(RTE 18모듈·클래스 331종 + 공통컴포넌트 1,089종 근거)과 적용·검증·재조립·사본 리허설, 의존성 기준(공식 parent 관리 좌표 139종+계열 6종+Spring Boot BOM 1,473종+RTE 전이 58종)·해석된 의존성 트리·CycloneDX·SPDX SBOM 생성·점검(최소 요소·비교·VEX), GitHub·GitLab·Jenkins CI 공급망 게이트, 규칙·기준 drift 감시, 폐쇄망 오프라인 번들, 네트워크 진단·AGENTS.md 생성, 공통컴포넌트 카탈로그 190항목(리프 176종+그룹 14종, v5.0.7)**을 제공합니다.
16
+ 현재 v0.45.0은 **도구 34종(title·annotations·구조화 출력 13종) + CLI 명령 11종, 공식 템플릿 22종, 설정 템플릿 21종, 5.x 전환 규칙(RTE 18모듈·클래스 331종 + 공통컴포넌트 1,089종 근거)과 적용·검증·재조립·사본 리허설, 의존성 기준(공식 parent 관리 좌표 139종+계열 6종+Spring Boot BOM 1,473종+RTE 전이 58종)·해석된 의존성 트리·CycloneDX·SPDX SBOM 생성·점검(최소 요소·비교·VEX), 개발보안 가이드 보안약점 점검(SARIF), 컨테이너·배포 산출물(Dockerfile·docker-compose·Kubernetes), GitHub·GitLab·Jenkins CI 공급망 게이트, 규칙·기준 drift 감시, 폐쇄망 오프라인 번들, 네트워크 진단·AGENTS.md 생성, 공통컴포넌트 카탈로그 190항목(리프 176종+그룹 14종, v5.0.7)**을 제공합니다.
17
17
 
18
- ## 진행 현황 (2026-10-11)
18
+ ## 진행 현황 (2026-10-13)
19
19
 
20
- - **소스 기준**: v0.43.0(`package.json`), 도구 32종 + CLI 명령 10종·공식 템플릿 22종·설정 템플릿 21종·카탈로그 190항목(공통컴포넌트 v5.0.7).
20
+ - **소스 기준**: v0.45.0(`package.json`), 도구 34종 + CLI 명령 11종·공식 템플릿 22종·설정 템플릿 21종·카탈로그 190항목(공통컴포넌트 v5.0.7).
21
21
  - **안전성 기준선 완료**: [PR #7](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/7)~[#16](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/16)을 반영해 provenance·strict assertion·safe remove와 프로젝트 생성/레시피/직접 조립/AI 조립/업그레이드 transaction을 갖췄습니다.
22
22
  - **v0.22.0 추가**: `EGOVFRAME_ALLOWED_ROOTS`를 19개 도구 진입점에 적용해 `..`·symlink/junction 이탈을 차단하고, 실패 시 rollback 결과를 구조화해 반환합니다. [PR #16](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/16)은 7파일(+340/−31), 로컬 16종 스위트 전체 통과 후 병합됐습니다.
23
23
  - **v0.23.0 추가**: `build_egovframe_project` — 생성한 프로젝트를 실제로 빌드(maven/gradle·mvnw/gradlew 자동 감지)하고 컴파일·테스트 오류를 파일/라인 단위로 구조화해 생성→검증 루프를 완성합니다. 타임아웃·로그 상한·허용 root·dryRun 포함. [PR #18](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/18)은 4파일(+458/−3), 오프라인 40단언과 실제 spawn 경로를 검증했습니다.
@@ -32,6 +32,8 @@ Claude, VS Code(Copilot), Cursor 등 MCP를 지원하는 AI 도구에서 **대
32
32
  - **v0.30.0 추가**: `migrate_egovframe_project` 2단계(`apply=true`) — 진단의 auto 항목을 하나의 transaction 으로 실제 치환합니다(dryRun 기본, 원본 `migration-backup/` 보관, `migration-plan.json`, 실패 시 복구). 3.10 좌표·javax 픽스처를 적용한 뒤 JDK 17 `mvn compile` 통과를 CI 에서 확인합니다. `check_egovframe_dependencies` — 공식 5.x parent 2종에서 추출한 기준(관리 좌표 139종 + BOM 계열 7종, `catalog/dependency-baseline.json`)과 의존성을 대조해 기준 충족/미만/parent 관리/전환 대상/교체 필요/기준 없음으로 분류하고, 보안 설정(sec.security·CSRF·XSS 필터·보안 헤더·HTTPS 저장소) 존재 여부를 근거와 함께 보고합니다. 기본 오프라인, `offline=false` 면 OSV 취약점 조회(설계: [docs/design-dependency-check.md](docs/design-dependency-check.md)).
33
33
  - **v0.31.0 추가**: 운영 편의 — `diagnose_egovframe_network`(도구가 쓰는 호스트 7종에 DNS·HEAD 프로브, 실패 종류 분류, HTTPS_PROXY+NODE_USE_ENV_PROXY·IPv4 우선·사내 CA 처방을 bash/cmd/PowerShell 명령으로), 모든 다운로드 실패 메시지에 같은 처방 한 줄 부착, `generate_agents_md`(진단 결과로 AI 코딩 도구용 AGENTS.md, ko/en), 영문 README(`README.en.md`)와 `EGOVFRAME_LANG=en` 영문 도구 설명, MCP Registry 메타데이터(`server.json`·`mcpName`). 기획 3개 버전(v0.29–v0.31)이 모두 완료됐습니다.
34
34
  - **v0.32.0 추가**: MCP 프로토콜 현대화 — 도구 27종을 `registerTool` 로 전환해 `title`(ko/en)과 annotations(`readOnlyHint` 14종·`destructiveHint` 4종·`idempotentHint`·`openWorldHint`)를 `tools/list` 에 노출하고, `format=json` 을 제공하던 5종(`diagnose_egovframe_project`·`validate_egovframe_project`·`migrate_egovframe_project`·`check_egovframe_dependencies`·`diagnose_egovframe_network`)은 `outputSchema` 와 `structuredContent` 를 함께 돌려줍니다(기존 `text` 유지). 테스트 이식성 가드(`scripts/check-test-portability.mjs`, 게이트 포함)와 플랫폼 주입 단언으로 Windows 전용 실패 재발을 막습니다.
35
+ - **v0.45.0 추가**: 컨테이너·배포 산출물 — 새 도구 **`generate_egovframe_deploy`**(34번째)가 진단(빌드 도구·war/jar·Boot·웹·actuator·DbType·설정 파일)으로 Dockerfile(멀티 스테이지 Maven/Gradle 빌드 → Classic war 는 Tomcat 10.1 에 ROOT 로 풀어서, Boot jar 는 Temurin JRE — 비루트·HEALTHCHECK·Asia/Seoul·UTF-8, `buildInImage=false` 면 미리 빌드한 산출물), `deploy/docker-compose.yml`(앱 + DbType 별 mysql·mariadb·postgres 컨테이너, 템플릿 DDL·DATA 초기화), Kubernetes 매니페스트(Deployment 프로브·비루트 securityContext·리소스, Service, ConfigMap, Secret, 선택 Ingress)를 만듭니다. DB 설정은 Boot 는 Spring 환경 변수(`Globals.mysql.Url` → `GLOBALS_MYSQL_URL`), Classic 은 `globals.properties` 사본을 볼륨·Secret 으로 덮어쓰고, 기반 이미지는 `imageRegistry`(Dockerfile `BASE_REGISTRY`)로 사내 레지스트리에서 받습니다. 공식 web(Classic)·boot-web(Boot) 템플릿은 hadolint 경고 0·kubeconform 통과 후 실제 `docker build` → 기동 → HTTP 200·healthy·uid 10001, 공식 simple-backend 는 `docker compose up` 으로 MySQL 초기화 데이터가 API 로 나오는 것까지 CI 에서 확인합니다.
36
+ - **v0.44.0 추가**: 납품 전 보안약점 점검 — 새 도구 **`check_egovframe_secure_coding`**(33번째)이 행정안전부·KISA 「소프트웨어 개발보안 가이드」(2021, 구현단계 보안약점 49개) 중 정적 패턴으로 오탐을 통제할 수 있는 14개 항목(규칙 20종 — SQL 삽입·크로스사이트 스크립트·경로 조작·URL 자동접속·운영체제 명령어·XML 외부개체·취약한 암호·부적절한 난수·하드코드된 중요정보·쿠키·오류 정보노출·오류상황 대응 부재·역직렬화·디버그 코드)을 소스에서 찾습니다. 규칙은 데이터(`catalog/secure-coding-rules.json`)이고, 주석(공식 공통컴포넌트 매퍼의 `${…}` 96건은 전부 "#{} 로 변경" 주석)·`<c:out>`·커스텀 태그 속성·자리표시자 같은 오탐을 실측으로 걸러 냅니다. 항목마다 공통컴포넌트 원본·수정본·매니페스트 없음·프로젝트·테스트 출처를 붙이고, 예외 파일(사유·검토자 필수)·이전 결과와 비교(새 항목만)·**SARIF 2.1.0**(GitHub code scanning, OASIS 공식 스키마 통과)을 지원합니다. 같은 규칙으로 공식 공통컴포넌트는 v4.3.2 516건 → **v5.0.7 38건**(`escapeXml="false"` 304 → 6)이라 업그레이드 효과가 숫자로 보이고, 공식 web·boot-web 템플릿은 0건입니다. 평가서 4절, CLI `secure`, `generate_egovframe_ci(secureCoding=true)` 게이트 단계(GitHub 은 SARIF 업로드).
35
37
  - **v0.43.0 추가**: CI·제출 형식 다변화 — `generate_egovframe_ci(platform="gitlab"|"jenkins")` 가 GitHub Actions 와 같은 빌드·공급망 게이트를 `.gitlab-ci.yml`(JUnit·CycloneDX 리포트)·`Jenkinsfile`(Declarative, Linux `sh`·Windows `bat` 공용)로 만들고, 게이트에 **SBOM 최소 요소 점검**(`sbom-check --fail-on minimum`)을 세 플랫폼 모두 추가했습니다. 사내 npm 레지스트리(`npmRegistry`)·오프라인 번들 경로(`offlineBundle`)는 환경 변수로 들어가고, 공급자 단서가 없으면 게이트가 실패할 것을 미리 알립니다. SBOM 은 **SPDX 2.3 JSON** 으로도 냅니다 — `generate_egovframe_sbom(bomFormat="spdx-json")` 이 패키지·`DEPENDS_ON` 관계(의존 없음은 `NONE`)·purl·공급자·creators·created·체크섬·선언 라이선스·OSV 권고·기준 판정(annotations)을 담고, `check_egovframe_sbom` 은 형식을 자동 판별해 SPDX 도 같은 최소 요소 7종·재판정·비교로 점검합니다(VEX 는 CycloneDX 만). 공식 web 템플릿을 실제 Maven 으로 만든 SBOM 은 SPDX 로 바꿔도 component 67·최소 요소 판정(요소별 충족 수까지)이 같고 SPDX ↔ CycloneDX 비교 차이 0 이며, 생성 `.gitlab-ci.yml` 은 GitLab 공식 CI 스키마를, SPDX 출력은 공식 spdx-spec v2.3 스키마를 통과합니다. 도구 수는 32종 그대로입니다.
36
38
  - **v0.42.0 추가**: 폐쇄망(망분리) 운영 — 새 도구 **`prepare_egovframe_offline_bundle`**(32번째)이 인터넷 PC 에서 OSV Maven 취약점 전체 덤프(≈10MB, 7,190건)·고정 공통컴포넌트 아카이브(sha256 검증)·Initializr zip 템플릿(고정 지문)·재조립용 공식 공통컴포넌트 태그 22개 미러(≈37MB)를 한 디렉터리에 담고 `bundle-manifest.json`(파일별 sha256·크기·출처 URL·받은 시각)을 씁니다. 폐쇄망 PC 에서 `EGOVFRAME_OFFLINE_BUNDLE` 만 지정하면 다운로드는 번들 파일을 지문 검증 후 쓰고(변조 거부), `offline=false` 의 OSV 조회는 로컬 덤프로 판정하며(스냅숏 기준일 표시, 30일 넘으면 경고), 재조립은 번들 미러를 씁니다. 같은 날 받은 덤프의 로컬 판정이 온라인 OSV 와 **질의 73/73·ID 134/134 일치**했고, 네트워크를 막은 상태에서 프로젝트 생성·공통컴포넌트 조립·재조립 미리보기·SBOM 재점검이 번들만으로 끝나는 것(네트워크 시도 0건)을 CI 에서 확인합니다. CLI `bundle`, 네트워크 진단의 오프라인 번들 처방.
37
39
  - **v0.41.0 추가**: 전환 리허설 — 새 도구 **`rehearse_egovframe_migration`**(31번째)이 프로젝트를 건드리지 않고 사본에서 공통컴포넌트 재조립 → 전환 자동 항목 적용 → 컴파일 → pom 을 공식 공통컴포넌트 v5.0.7 기준으로 맞춤 → 다시 컴파일까지 돌려 "자동 단계 뒤 사람이 고칠 것이 실제로 몇 건인가"를 잽니다(javac 의 오류 100개 상한 없이 전부 셈, 실행 전후 지문으로 원본 불변 확인). 공식 공통컴포넌트 **v4.3.2 전체 트리**(6,523 파일)는 자동 단계 뒤 컴파일 오류 **6,003건**(CI·JDK 17, JDK 21 은 6,335건) 중 4건을 뺀 전부가 누락 패키지와 그 연쇄(pom 의존성, 그 때문에 Lombok 이 돌지 못한 getter 등)였고, pom 을 맞추면 **1건**(GPKI 벤더 jar 의 javax 참조)만 남습니다 — CI 가 이 값을 기대값으로 고정합니다. 실측 중 찾은 두 결함도 고쳤습니다: 재조립은 전환 적용보다 **먼저** 해야 원본 태그가 식별되고(반대로 하면 4.3.2 가 v5.0.1 로 오인), 4.x 의 `org.egovframe.rte` 좌표가 5.x 로 분류되던 문제와 Maven 경고·fork 형식이 컴파일 오류로 잘못 읽히던 문제를 바로잡았습니다. 평가서 6절에 최근 리허설 실측이 함께 나옵니다.
@@ -43,7 +45,7 @@ Claude, VS Code(Copilot), Cursor 등 MCP를 지원하는 AI 도구에서 **대
43
45
  - **v0.35.0 추가**: 릴리스 자동화 — `main` 에서 CI 가 성공하면 `release.yml` 이 네 조건(`server.json` 버전 일치·변경 이력 항목·태그 없음·npm 미배포)을 검사해 npm(OIDC trusted publishing, provenance 자동) → 그 커밋에 태그 → GitHub Release(변경 이력에서 추출) → MCP Registry(GitHub OIDC) 순으로 게시합니다. 사람은 PR 병합만 합니다. 게이트에 `test:release`(판정 함수·릴리스 노트·`npm pack` 내용·크기 상한)와 `server.json` 설명 100자 제한(레지스트리 검증 조건 — 실제 `mcp-publisher validate` 로 발견한 결함 수정)을 추가했습니다.
44
46
  - **v0.34.0 추가**: 의존성 기준 완성 + 규칙·기준 drift 감시 — `check_egovframe_dependencies` 의 기준에 **Spring Boot BOM 전체**(`spring-boot-dependencies` 3.5.6 직접 항목 + BOM import 44종을 한 단계 풀어 1,473 좌표)와 **RTE 모듈 18종의 전이 의존성**(58 좌표, 어느 모듈이 끌어오는지)을 더해 항목마다 기준 출처(parent 직접·계열·Boot BOM·RTE 전이·전환 규칙)를 표시하고, 국내 벤더·기관 배포 좌표는 `vendor` 로, EOL·이전 좌표(옛 MySQL/Oracle 드라이버·Jackson 1·xmlbeans·Ehcache 2·HttpClient 4·ANTLR 3·Spring Social)는 교체 규칙으로 분류해 공식 공통컴포넌트 3.10 pom 의 '기준 없음'을 17 → 1 로 줄였습니다. `sync_egovframe_templates` 가 동봉 규칙·기준의 upstream drift(`egovframe-runtime`·공통컴포넌트 새 태그, 공식 parent 새 버전, 고정 pom sha256 변화)를 갱신 절차와 함께 보고합니다. 기준 parent 를 5.0.2 로 올렸습니다.
45
47
  - **v0.33.0 추가**: `migrate_egovframe_project` 3단계 — `verify=true` 가 compile 을 실행해 컴파일 오류를 수동 항목과 연결하고 "처리하면 해결될 오류 수" 순 작업 목록을 냅니다(javac `symbol:`/`location:` 파싱). 규칙 카탈로그(schemaVersion 2)에 공통컴포넌트 3.x→5.x 대응표(`egovframe-common-components` v3.10.0↔v5.0.6, 제거 54·이동 4)를 추가해 `egovframework.com.*` 제거·이동 클래스를 진단하고, 3.x 공통컴포넌트 소스가 섞인 프로젝트에는 컴포넌트 단위 재조립 권고(`skipComponents` 로 치환 제외)를 냅니다.
46
- - **다음 계획**: v0.41–v0.43 기획을 모두 마쳤습니다([기획 원문과 결과](#다음-버전-기획-v041v043)). 다음 세 버전 기획은 아직 없습니다.
48
+ - **다음 계획**: v0.46 5.x 최신 유지 + 생성 CI 실행 검증. [다음 버전 기획](#다음-버전-기획-v044v046) 참조.
47
49
  - **배포 상태**: npm 최신 배포 버전은 상단 npm 배지와 [npm 패키지 페이지](https://www.npmjs.com/package/egovframe-scaffold-mcp)를 단일 출처로 확인합니다. 이 문서의 버전 표기는 저장소 소스(`package.json`) 기준이며, git 태그 `vX.Y.Z`가 해당 배포본의 커밋을 가리킵니다.
48
50
 
49
51
  ## 제공 도구
@@ -81,6 +83,8 @@ Claude, VS Code(Copilot), Cursor 등 MCP를 지원하는 AI 도구에서 **대
81
83
  | `prepare_egovframe_offline_bundle` | **폐쇄망 오프라인 번들** — 인터넷 PC 에서 OSV Maven 덤프·고정 공통컴포넌트 아카이브·Initializr zip 템플릿·공통컴포넌트 태그 미러를 sha256 manifest 와 함께 새 디렉터리에 담음(dryRun 기본). 폐쇄망에서는 `EGOVFRAME_OFFLINE_BUNDLE` 로 다운로드·OSV·재조립 원본을 번들로 대체 |
82
84
  | `generate_egovframe_sbom` | **SBOM 생성** — Maven/Gradle 프로젝트의 CycloneDX 1.6 JSON(기본) 또는 SPDX 2.3 JSON(`bomFormat="spdx-json"`)을 빌드 파일 변경 없이 생성(Maven: cyclonedx-maven-plugin makeAggregateBom, 해시·라이선스 포함 / Gradle: 해석된 의존성 트리로 구성). `enrich` 로 component 마다 기준 판정(`egovframe:status·basis·baseline`) 속성, `offline=false` 로 OSV 취약점을 `vulnerabilities[]` 에 포함. 출력은 프로젝트 안 경로(기본 `sbom/bom.cdx.json`, SPDX 는 `sbom/bom.spdx.json`), 기존 파일은 `overwrite` 없이는 거부, `dryRun`(기본)은 계획만 |
83
85
  | `check_egovframe_sbom` | **SBOM 점검** — 기존 CycloneDX·SPDX 2.x SBOM(형식 자동 판별)의 최소 요소 7종(공급자·구성요소명·버전·고유식별자·의존관계·작성자·생성 시각) 충족 여부와 빠진 component, 빌드 도구 없이 purl 로 기준 재판정·OSV 재조회(생성 이후 새 취약점), `baselinePath` 와 비교(추가·제거·버전·판정·취약점), `vex=true` 면 CycloneDX VEX 초안(`in_triage`, BOM-Link, 사람의 판단 보존, CycloneDX 입력만). SBOM 파일은 바꾸지 않음 |
86
+ | `check_egovframe_secure_coding` | **보안약점 점검** — 행안부·KISA 개발보안 가이드(2021) 구현단계 보안약점 중 정적 패턴 14개 항목(규칙 20종: SQL 삽입·XSS·경로 조작·URL 자동접속·OS 명령·XXE·약한 암호·난수·하드코드 정보·쿠키·오류 노출·빈 catch·역직렬화·디버그 코드)을 파일·라인·CWE·등급·조치·출처(공통컴포넌트 원본/수정본/매니페스트 없음·프로젝트·테스트)로. 예외 파일(사유·검토자), `baselinePath` 비교(새 항목), SARIF 2.1.0(`format=sarif`·`sarifPath`). 진단 보조이며 공인 진단을 대체하지 않음 |
87
+ | `generate_egovframe_deploy` | **컨테이너·배포 산출물** — Dockerfile(멀티 스테이지·Classic war → Tomcat 10.1(Servlet 6.1+ 는 11.0) ROOT, Boot jar → Temurin JRE, 비루트·HEALTHCHECK, `buildInImage=false` 면 미리 빌드한 산출물)·`.dockerignore`·`deploy/docker-compose.yml`(DbType 별 DB 컨테이너·초기화 SQL)·`deploy/k8s/<app>.yaml`(Deployment·Service·ConfigMap·Secret·선택 Ingress). DB 설정은 Boot 환경 변수·Classic 설정 파일 덮어쓰기, `imageRegistry`(폐쇄망), `dockerfilePath`(템플릿 자체 Dockerfile 과 공존). 새 파일만, `dryRun` 기본 |
84
88
  | `generate_agents_md` | 프로젝트 진단 결과로 AI 코딩 도구용 `AGENTS.md` 생성 — 빌드·테스트 명령(래퍼 감지), RTE·5.x 전환 상태, DbType, 기본 패키지·설정 디렉터리, 설치 컴포넌트(매니페스트 여부), 규칙(좌표·백업 디렉터리·비밀 정보·의존성 기준), MCP 도구 목록. 기존 파일은 `overwrite` 없이는 거부, `dryRun`, ko/en, 파일명 변경(`CLAUDE.md` 등) |
85
89
 
86
90
  ### create_egovframe_project 파라미터
@@ -233,6 +237,50 @@ check_egovframe_sbom(projectDir, baselinePath="sbom/bom-2026Q3.cdx.json", offlin
233
237
 
234
238
  제출처가 SPDX 를 요구하면(가이드라인 1.0 은 SPDX·CycloneDX 를 모두 언급) `bomFormat="spdx-json"` 으로 같은 내용을 SPDX 2.3 JSON 으로 냅니다. 체크섬·선언 라이선스(이름만 있는 라이선스는 `LicenseRef-` + `hasExtractedLicensingInfos`)·OSV 권고(`SECURITY`/`advisory` externalRefs)·기준 판정(`egovframe:*` annotations)도 옮기므로, SPDX 로 낸 뒤 `check_egovframe_sbom(sbomPath="sbom/bom.spdx.json")` 의 재판정·비교가 CycloneDX 와 같은 결과를 냅니다. SPDX 3.0, 취약점 판단 자동화(VEX 상태는 사람의 결정), 중앙 저장소 제출 API 는 범위 밖입니다.
235
239
 
240
+ ### 컨테이너·배포 산출물 (`generate_egovframe_deploy`)
241
+
242
+ ```text
243
+ generate_egovframe_deploy(projectDir) # 미리보기(dryRun) — 파일 내용과 사용법
244
+ generate_egovframe_deploy(projectDir, dryRun=false) # Dockerfile·.dockerignore·deploy/docker-compose.yml·deploy/k8s/<app>.yaml
245
+ generate_egovframe_deploy(projectDir, dryRun=false, imageRegistry="harbor.example.go.kr/dockerhub", buildInImage=false) # 폐쇄망
246
+ generate_egovframe_deploy(projectDir, dryRun=false, dockerfilePath="deploy/Dockerfile", ingressHost="egov.example.go.kr") # 템플릿 자체 Dockerfile 과 공존
247
+ ```
248
+
249
+ | 프로젝트 | 실행 이미지 | DB 설정 주입 | 헬스체크 |
250
+ |---|---|---|---|
251
+ | Classic(war) — web·template·mobile 등 | `tomcat:10.1-jdk17-temurin`(Servlet 6.1 이상 직접 선언 시 11.0), WAR 를 `webapps/ROOT` 로 풀어 둠 | `globals.properties` 사본(DB 호스트·비밀번호만 바꿈)을 compose 볼륨·Kubernetes Secret 으로 `WEB-INF/classes/…` 에 덮어씀 | `/` |
252
+ | Boot(jar) — boot-web·simple-backend·batch-web 등 | `eclipse-temurin:17-jre`, `exec java $JAVA_OPTS -jar` | Spring 환경 변수(`Globals.mysql.Url` → `GLOBALS_MYSQL_URL`, `spring.datasource.url` → `SPRING_DATASOURCE_URL`) | actuator 프로브가 있으면 `/actuator/health/liveness`·`readiness`, 아니면 `/` |
253
+ | Boot 배치(웹 없음) | 위와 같음 | 위와 같음 | 없음(포트·Service 없이, Job·CronJob 안내) |
254
+ | 멀티 모듈·라이브러리 jar·빌드 파일 없음 | — | — | 만들지 않고 이유를 돌려줌 |
255
+
256
+ - **DB**: mysql 8.4·mariadb 11.4·postgres 16 은 compose 에 DB 컨테이너를 붙이고 템플릿의 DDL·DATA 를 초기화 스크립트로 마운트합니다(`--lower-case-table-names=1`, utf8mb4). 오라클·티베로·알티베이스·큐브리드는 연결 정보만 쓰고, Kubernetes 는 클러스터 밖 DB 를 가정해 `CHANGE_ME_DB_HOST`·Secret 자리표시자를 둡니다.
257
+ - **보안 기본값**: 비루트(uid 10001)·`runAsNonRoot`·`seccompProfile RuntimeDefault`·`allowPrivilegeEscalation false`·`capabilities drop ALL`·리소스 요청/제한·startup/readiness/liveness 프로브.
258
+ - **폐쇄망**: 기반 이미지는 `ARG BASE_REGISTRY`(기본 `imageRegistry`)로 사내 레지스트리에서 받고, `# syntax` 지시어를 쓰지 않아 BuildKit 프론트엔드 이미지를 받지 않습니다. 컨테이너 안에서 Maven 저장소에 닿지 않으면 `buildInImage=false` 로 호스트에서 빌드한 산출물만 담습니다. 반입할 이미지: `tomcat:10.1-jdk17-temurin`·`eclipse-temurin:17-jre`·`eclipse-temurin:17-jdk`(미리 빌드할 때)·`maven:3.9-eclipse-temurin-17`(이미지 안에서 빌드할 때)·DB 이미지(`docker save`/`docker load` 또는 사내 Harbor 프록시 캐시).
259
+ - **실측**: 공식 web(Classic)·boot-web(Boot) 템플릿은 hadolint 경고 0·kubeconform(쿠버네티스 1.31) 통과, 실제 빌드·기동에서 HTTP 200·healthy·uid 10001. 공식 simple-backend(Boot + MySQL)는 compose 로 readiness UP·`/mainPage` 가 MySQL 초기화 데이터를 돌려주고, 공식 portal-site(Classic + MySQL)는 설정 파일 덮어쓰기로 MySQL 사용자 `pst` 에 연결해 메인 페이지가 열립니다. 설계: [docs/design-deploy.md](docs/design-deploy.md).
260
+
261
+ ### 납품 전 보안약점 점검 (`check_egovframe_secure_coding`)
262
+
263
+ 감리 대상 사업은 「소프트웨어 개발보안 가이드」(행정안전부·KISA, 2021)의 구현단계 보안약점 49개를 지켜야 하고, 납품 전 진단에서 지적된 항목은 재작업이 됩니다. 이 도구는 그중 정적 패턴으로 근거 있게 찾을 수 있는 항목을 먼저 찾아 진단 전에 고칠 목록을 만듭니다(데이터 흐름 분석이 아닌 패턴 기반 진단 보조 — 공인 진단을 대체하지 않습니다).
264
+
265
+ ```text
266
+ check_egovframe_secure_coding(projectDir) # 등급·항목·출처별 요약 + 상위 40건
267
+ check_egovframe_secure_coding(projectDir, format="json") # 전체(지문 포함) — 다음 비교의 baseline
268
+ check_egovframe_secure_coding(projectDir, baselinePath="reports/secure-prev.json") # 새로 생긴 것만 🆕
269
+ check_egovframe_secure_coding(projectDir, sarifPath="egovframe-secure.sarif", overwrite=true) # SARIF 2.1.0
270
+ ```
271
+
272
+ | 가이드 항목 (규칙) | 찾는 것 | 걸러 내는 것 |
273
+ |---|---|---|
274
+ | SQL 삽입 (`sql-mybatis-dollar`·`sql-ibatis-dollar`·`sql-jdbc-concat`) | 매퍼의 `${…}`·`$…$`, JDBC 호출의 문자열 연결 | XML 주석, 스프링 설정의 `${Globals…}`, `?` 바인딩 — ORDER BY 다음의 `${}` 는 중간(허용 목록 검증 안내) |
275
+ | 크로스사이트 스크립트 (`xss-jsp-request`·`xss-jsp-el-param`·`xss-cout-unescaped`) | `<%= request.getParameter %>`, 본문·HTML 속성의 `${param.x}`, `<c:out escapeXml="false">` | `<c:out>`·`fn:escapeXml`, `<c:if test>`·`<spring:message code>` 같은 태그 속성, 상수 값, JSP 주석 |
276
+ | 경로 조작·URL 자동접속·운영체제 명령어·XML 외부개체 | 요청 파라미터로 만든 파일 경로·리다이렉트, 명령 실행(같은 줄에 요청 값이면 높음), 보호 설정 없는 XML 파서 | 고정 경로, `disallow-doctype-decl` 등 보호 설정이 있는 파일 |
277
+ | 취약한 암호·부적절한 난수·하드코드된 중요정보·쿠키 | MD5·SHA-1·DES·ECB(`"AES"` 단독), 보안 문맥의 `Random`, 코드·설정·docker-compose 의 평문 비밀번호, HttpOnly·Secure 없는 쿠키 | `ENC(…)`·`${…}`·숫자·가림·자리표시자, 파라미터 이름·경로 상수, 메시지 번들 |
278
+ | 오류 정보노출·오류상황 대응 부재·역직렬화·디버그 코드 | `printStackTrace()`, 빈 `catch`(주석만 있어도), `ObjectInputStream.readObject`, `System.out` | 로그 처리한 catch |
279
+
280
+ - **출처**: 공통컴포넌트 매니페스트의 해시로 "원본(업그레이드·예외·upstream 보고)"과 "수정본(직접 수정)"을 나누고, 매니페스트 없이 복사된 공통컴포넌트는 재조립을 안내합니다. 같은 규칙으로 공식 공통컴포넌트 v4.3.2 는 516건(중간 314), **v5.0.7 은 38건**(중간 16)입니다.
281
+ - **예외**: `.egovframe-secure-ignore.json` 에 `{"ignores":[{"rule":"debug-code","path":"src/main/java/egovframework/com/**","reason":"upstream 원본, 업그레이드 대기","reviewer":"홍길동"}]}` — 사유·검토자가 없는 항목은 적용하지 않고 목록으로 돌려줍니다.
282
+ - **CI**: `npx -y egovframe-scaffold-mcp secure --project . --sarif-path egovframe-secure.sarif --overwrite --fail-on high`, 또는 `generate_egovframe_ci(supplyChain=true, secureCoding=true)` 게이트 단계(GitHub 는 code scanning 에 SARIF 업로드). 평가서 4절에 요약이 나오며 등급 산식에는 넣지 않습니다. 설계: [docs/design-secure-coding.md](docs/design-secure-coding.md).
283
+
236
284
  ### generate_egovframe_report 파라미터 (전환 준비도 평가서)
237
285
 
238
286
  - `projectDir` — 평가할 프로젝트(허용 root 적용)
@@ -393,6 +441,7 @@ npx -y egovframe-scaffold-mcp rehearse --project . --fail-on "errors>50"
393
441
  | `sbom` | `generate_egovframe_sbom` | `--write` 가 있어야 파일을 씀(기본 계획만), `--bom-format spdx-json` 이면 SPDX 2.3 |
394
442
  | `bundle` | `prepare_egovframe_offline_bundle` | 인터넷 PC 용, `--output-dir` 필수, `--write` 가 있어야 받음(기본 목록만) |
395
443
  | `rehearse` | `rehearse_egovframe_migration` | 사본에서 실측(원본 불변), 지표 `errors`(최종)·`automation`·`aligned`·`files`·`unlinked`·`failedSteps` |
444
+ | `secure` | `check_egovframe_secure_coding` | `high`·`medium`·`low`·`total`·`new`(baseline 대비), `--sarif-path` 로 SARIF |
396
445
  | `sbom-check` | `check_egovframe_sbom` | CycloneDX·SPDX 자동 판별, `minimum`(보완 필요면 1)·`gaps`·`newVulns`·`changed`·비교 `added`·`removed`·`versionChanged`·`diffVulns`·VEX `triage`, `--write` 면 VEX 작성·갱신 |
397
446
  | `migrate` | `migrate_egovframe_project` | 진단만(`--apply` 차단), `manual`·`auto`·`items` |
398
447
  | `validate` · `diagnose` · `network` | 같은 이름의 도구 | `invalid`·`missing` · `issues` · `failed` |
@@ -415,6 +464,7 @@ generate_egovframe_ci(projectDir="/work/my-egov-app", platform="jenkins", supply
415
464
  npmRegistry="https://nexus.example.go.kr/repository/npm-group/", offlineBundle="/opt/egov-bundle")
416
465
  ```
417
466
 
467
+ - v0.44: `secureCoding=true` 면 sbom-check 다음에 보안약점 점검(`secure --fail-on high`, `egovframe-secure.sarif`) 단계가 들어갑니다. GitHub 는 `security-events: write` 권한으로 code scanning 에 SARIF 를 올리며(Advanced Security 가 없는 비공개 저장소에서도 게이트가 흔들리지 않게 `continue-on-error`), GitLab·Jenkins 는 SARIF 를 아티팩트로 보관합니다.
418
468
  - `npmRegistry` 는 `NPM_CONFIG_REGISTRY`(npx 가 이 서버를 받는 사내 레지스트리), `offlineBundle` 은 `EGOVFRAME_OFFLINE_BUNDLE`(러너·에이전트에서 본 번들 경로)로 들어갑니다. 값은 따옴표·`$`·줄바꿈 없는 URL·절대 경로만 허용합니다(설정 파일 주입 차단).
419
469
  - 공급자 단서가 없으면(`supplier` 미지정, pom `<organization><name>` 없음) SBOM 의 주 component 공급자·작성자가 비어 `sbom-check` 단계가 실패하므로, 생성 응답이 이를 미리 알립니다.
420
470
  - GitLab 이미지는 공개 Docker Hub 기준입니다. 폐쇄망에서는 사내 레지스트리의 같은 이미지(JDK + Node.js 18 이상)로 바꾸세요. Jenkins 는 Pipeline 기본 단계(`sh`·`bat`·`archiveArtifacts`)만 쓰며 에이전트에 JDK·Maven·Node.js 가 있어야 합니다.
@@ -440,6 +490,8 @@ export EGOVFRAME_OFFLINE_BUNDLE=/opt/egov-bundle # cmd: setx EGOVFRAME_OF
440
490
  | `templates/<id>.zip` (Initializr zip 템플릿) | `create_egovframe_project` 의 zip 템플릿 | 템플릿 고정 sha256·크기 |
441
491
  | `origin/…git` (공식 태그 22개, 내용 포함) | 재조립·리허설의 원본 태그 식별·패치 | 원격 조회 없이 로컬 미러만 |
442
492
 
493
+ 컨테이너 이미지는 번들에 담지 않습니다 — `generate_egovframe_deploy` 가 쓰는 기반 이미지는 `docker save`/`docker load` 나 사내 레지스트리로 반입하고 `imageRegistry` 로 지정하세요(「컨테이너·배포 산출물」 참조).
494
+
443
495
  번들 파일은 쓸 때마다 manifest 의 sha256·크기와 대조하고 다르면 거부합니다. 번들에 없는 URL 은 평소처럼 네트워크로 가므로, 저장소 템플릿(`simple-backend` 등)이 필요하면 `--templates` 로 지정해 함께 담으세요. Maven 의존성 jar 는 번들에 넣지 않습니다 — 기관 Nexus·Artifactory 미러를 `settings.xml` 에 지정하세요. upstream 대조 도구(`sync_egovframe_*`)와 가이드 문서 조회는 인터넷이 필요합니다. 설계: [docs/design-offline-bundle.md](docs/design-offline-bundle.md).
444
496
 
445
497
  ## 리소스·프롬프트 (MCP Resources/Prompts)
@@ -507,10 +559,12 @@ curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.Eri
507
559
  - 네트워크 진단 레벨: 오류 분류 8종, 프로브·DNS 주입으로 7가지 시나리오(전부 도달, 405/404/407/503, 프록시+타임아웃, 프록시 없음+IPv6 혼재, TLS, DNS, 필터)의 처방·안내·자격 증명 가림·셸별 명령을 단언하고, `fetchWithTimeout` 실패 메시지에 처방이 붙는지 확인 (`npm run test:network`, 33단언, 네트워크 불필요). 실제 호스트 7종 프로브는 CI 통합 job (`npm run test:network-live`)
508
560
  - AGENTS.md 레벨: 5.x(매니페스트·래퍼·컴포넌트 2종·백업 디렉터리)와 3.x gradle 픽스처, 빈 디렉터리에서 사실 수집·ko/en 렌더링·dryRun 무기록·기존 파일 거부·overwrite·파일명 검증·staging 정리 (`npm run test:agents-md`, 22단언, 네트워크 불필요)
509
561
  - 레지스트리 메타데이터 레벨: `server.json` ↔ `package.json` 의 이름(`mcpName`)·버전·npm 좌표·스키마 URL·환경변수 문서화 정합 (`npm run test:registry`, 네트워크 불필요)
510
- - 프로토콜 레벨(추가): `EGOVFRAME_LANG=en` 으로 띄운 서버의 도구 32종 설명이 모두 영문이고 표에 빠진 도구가 없는지, `tools/list` 에 `title`·annotations(readOnly 13종·destructive 5종)·`outputSchema` 11종이 노출되는지 확인 (`npm run test:handshake`)
562
+ - 프로토콜 레벨(추가): `EGOVFRAME_LANG=en` 으로 띄운 서버의 도구 34종 설명이 모두 영문이고 표에 빠진 도구가 없는지, `tools/list` 에 `title`·annotations(readOnly 13종·destructive 5종)·`outputSchema` 13종이 노출되는지 확인 (`npm run test:handshake`)
511
563
  - SBOM·해석 레벨: Maven·Gradle 트리 파서(실제 출력 픽스처), `resolve=true` 의 전이 항목·경로·선언/해석 차이·실패 경로, CycloneDX 문서 구성·보강·취약점 병합·출력 경로 거부·overwrite·dryRun (`npm run test:dependencies`, `npm run test:sbom`, 네트워크 불필요); CI 통합이 공식 `egovframe-web` 템플릿을 실제 Maven 으로 해석하고 SBOM 을 생성 (`npm run test:sbom-live`)
512
564
  - 오프라인 번들 레벨: Maven 버전 비교(숫자·한정자 순서·같은 표기), OSV 범위(여러 구간·fixed·last_affected), 덤프 색인(Maven 만·철회 제외·GIT 범위 무시)과 querybatch 같은 모양의 결과, 번들 만들기(dryRun·manifest 지문·고정 지문 불일치 거부·실패 시 무흔적·덮어쓰기 거부·로컬 git 원본 미러), 번들 읽기(fetch 훅·POST 제외·변조 거부·깨진 manifest), 원본 미러(태그·커밋·트리·blob, 없는 태그 안내), OSV 출처 노트와 30일 경고, 의존성 점검 연동, 네트워크 진단 처방 (`npm run test:offline-bundle`, 30단언, 네트워크 불필요); CI 통합이 실제 번들을 만들고 로컬 OSV 와 온라인 OSV 를 대조(97% 이상 일치 요구, 실측 100%)한 뒤 fetch 를 막고 생성·조립·재조립 미리보기·SBOM 재점검을 번들만으로 확인 (`npm run test:bundle-live`)
513
565
  - 전환 리허설 레벨: pom 맞춤(parent 추가·교체, 누락 좌표, 버전·scope, parent 관리 속성, 주석·dependencyManagement·plugin 제외, 멱등), 누락 패키지·연쇄·수동 항목 분류와 후보 좌표, Maven fork 형식·경고 제외 파서, 사본 제외 규칙·원본 지문 불변, 단계 순서(재조립 → 적용 → 컴파일 → pom 맞춤 → 컴파일)·javac 상한 해제 인자, 단계 실패 계속, 기록과 평가서 6절 (`npm run test:rehearse`, 38단언, 네트워크 불필요); CI 통합이 공식 공통컴포넌트 v4.3.2 전체 트리를 실제로 리허설해 재조립·적용 수와 오류 6,003(±10%, 누락 패키지·연쇄 95% 이상)→≤5 를 단언 (`npm run test:rehearse-live`)
566
+ - 배포 산출물 레벨: 분석(Classic war·Boot jar·Gradle 배치·Boot `server.port`·context-path·actuator 프로브·Servlet 6.1 → Tomcat 11·`Globals.<type>.Url`/`Globals.Url`/`spring.datasource.url`·DB 별칭·초기화 SQL 선택·지원 안 함 3종), Dockerfile(멀티 스테이지·캐시 마운트·5xx 재시도·WAR 풀기·비루트·HEALTHCHECK·레지스트리 ARG·미리 빌드), 생성 `docker-compose.yml` 의 공식 Compose 스키마(compose-spec 고정물) 통과·DB 컨테이너·초기화 순서·설정 볼륨, Kubernetes(보안 설정·프로브·ConfigMap/Secret 분리·Classic Secret subPath·Ingress), 입력 주입 거부·새 파일만·부분 충돌 시 무기록 (`npm run test:deploy`, 49단언, 네트워크 불필요). 실제 빌드·기동·compose 는 CI 통합 `test:deploy-live`(hadolint·kubeconform 포함)
567
+ - 보안약점 점검 레벨: 규칙 20종 데이터 검증(가이드 7개 유형·항목·CWE·컴파일), Java·XML·JSP 주석 제거(문자열·텍스트 블록 보존, HTML 주석 안 EL 유지), 규칙마다 양성·음성 픽스처(오탐 방지 사례 — `<c:out>`·커스텀 태그 속성·`fn:escapeXml`·상수 c:out·`ENC()`·자리표시자·파라미터 이름·보호 설정 있는 XML 파서 등), ORDER BY 강등·요청 값 동반 승격·보안 문맥 난수, 출처(매니페스트 원본·수정본·매니페스트 없음), 예외 파일(사유·검토자 없으면 미적용), baseline(JSON·SARIF, 줄 이동에도 같은 항목), SARIF 2.1.0 OASIS 공식 스키마(테스트 고정물) (`npm run test:secure-coding`, 52단언, 네트워크 불필요). 공식 공통컴포넌트 v3.10.0·v4.3.2 의 규칙별 건수는 회귀 코퍼스 기대값(±1%), 공식 템플릿은 CI 통합 `test:secure-live`(Initializr 고정 템플릿은 단언, 저장소 브랜치 템플릿은 drift 로그)
514
568
  - SPDX 레벨: 실제 플러그인 출력 고정물을 SPDX 2.3 으로 바꿔 공식 spdx-spec v2.3 스키마 통과, 패키지 68·`DEPENDS_ON` 간선 수 = CycloneDX 의존 간선·의존 없음 `NONE`·체크섬·라이선스(LicenseRef)·DESCRIBES, 되읽었을 때 최소 요소 요소별 충족 수·purl·의존 간선·기준 판정(annotations)·취약점(advisory) 보존, 다른 도구 모양 SPDX(`DEPENDENCY_OF`·`NOASSERTION`·여러 DESCRIBES·Person/Organization/Tool)의 필드 대응, `bomFormat="spdx-json"` 생성·SPDX 입력 점검(형식 판별·CycloneDX 와 같은 판정·SPDX↔CycloneDX 비교 차이 0·VEX 거부)·outputSchema (`npm run test:spdx`, 43단언, 네트워크 불필요). 실제 Maven SBOM 의 SPDX 판정 일치는 CI 통합 `test:sbom-live` 가 확인
515
569
  - SBOM 운영 레벨: 실제 플러그인 출력 고정물(공식 web 템플릿 67 component)로 최소 요소 7종(빠진 항목별)·공급자 표 보완·purl 재판정·가짜 OSV(새/사라진 ID)·비교(추가·제거·버전·판정·취약점)·VEX 생성/판단 보존/같은 ID 의 새 영향 component·깨진 VEX 중단을 단언하고, 생성 SBOM·VEX 를 CycloneDX 1.6 공식 JSON 스키마(specification 1.6.1)로 검증 (`npm run test:sbom-check`, 54단언, 네트워크 불필요); CI 통합이 실제 SBOM 으로 보완 필요(주 component 공급자·작성자) → supplier·author 로 보완(환경에 따른 다른 공백은 `info:` 로그), 두 SBOM 비교 차이 0, 실제 OSV VEX 초안·판단 보존을 확인 (`npm run test:sbom-live`)
516
570
  - 메타데이터·구조화 출력 레벨: `TOOL_META` ↔ 등록 도구 일치, 읽기 전용·파괴·네트워크 힌트 배정, 영문 title, 7종 도구의 실제 결과(진단·검증·전환 진단/적용·의존성·네트워크·리포트, 빈 프로젝트 포함)가 `outputSchema` 를 통과하고 최상위 키가 전부 선언돼 있으며 잘못된 값은 거부 (`npm run test:output-schemas`, 47단언, 네트워크 불필요). MCP 프로토콜 경유 호출 시 SDK 가 `structuredContent` 를 스키마로 검증합니다
@@ -541,7 +595,7 @@ curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.Eri
541
595
 
542
596
  v0.31.0까지 프로젝트·CRUD 생성, 검증된 공통컴포넌트 실행 자산 조립, 안전성 기반(테스트 판정 강제·사용자 파일 보호·전 도구 트랜잭션·허용 root·구조화 rollback 보고), 생성→검증 루프(실제 빌드·오류 구조화·테스트 리포트 구조화), 공식 템플릿 카탈로그 단일화와 커버리지 확대(22종 중 21종), 설정 파일 생성, 5.x 전환(진단·적용), 의존성 점검, 운영 편의(네트워크 진단·AGENTS.md·영문 설명·레지스트리 메타데이터)를 완료했습니다.
543
597
 
544
- v0.32–v0.34 로 MCP 프로토콜 현대화, 5.x 전환 3단계(검증)와 공통컴포넌트 대응표, 의존성 기준 완성과 규칙·기준 drift 감시를, v0.35–v0.37 로 릴리스 자동화, 해석된 의존성 트리와 SBOM, 전환 준비도 평가서와 회귀 코퍼스를, v0.38–v0.40 으로 공통컴포넌트 재조립 실행, CLI 모드와 CI 공급망 게이트, SBOM 운영(최소 요소·비교·VEX)을, v0.41–v0.43 으로 전환 리허설, 폐쇄망 오프라인 번들, GitLab·Jenkins CI 와 SPDX 를 마쳤습니다(기획 원문과 결과: [v0.41–v0.43](#다음-버전-기획-v041v043) · [v0.38–v0.40](#이전-기획-v038v040-완료) · [v0.35–v0.37](#이전-기획-v035v037-완료)). Homebrew 탭은 후순위에서 내렸습니다(npx 로 충분).
598
+ v0.32–v0.34 로 MCP 프로토콜 현대화, 5.x 전환 3단계(검증)와 공통컴포넌트 대응표, 의존성 기준 완성과 규칙·기준 drift 감시를, v0.35–v0.37 로 릴리스 자동화, 해석된 의존성 트리와 SBOM, 전환 준비도 평가서와 회귀 코퍼스를, v0.38–v0.40 으로 공통컴포넌트 재조립 실행, CLI 모드와 CI 공급망 게이트, SBOM 운영(최소 요소·비교·VEX)을, v0.41–v0.43 으로 전환 리허설, 폐쇄망 오프라인 번들, GitLab·Jenkins CI 와 SPDX 를 마쳤습니다(기획 원문과 결과: [v0.41–v0.43](#이전-기획-v041v043-완료) · [v0.38–v0.40](#이전-기획-v038v040-완료) · [v0.35–v0.37](#이전-기획-v035v037-완료)). 다음 세 버전(v0.44–v0.46)의 범위는 [다음 버전 기획](#다음-버전-기획-v044v046)에 있습니다. Homebrew 탭은 후순위에서 내렸습니다(npx 로 충분).
545
599
 
546
600
  | 버전 | 핵심 기능 | 목표 |
547
601
  |---|---|---|
@@ -569,10 +623,98 @@ v0.32–v0.34 로 MCP 프로토콜 현대화, 5.x 전환 3단계(검증)와 공
569
623
  | **v0.41 완료** | 전환 리허설 | `rehearse_egovframe_migration`: 프로젝트 사본에서 migrate apply → reassemble → JDK 17 compile 을 돌려 남는 컴파일 오류 수·분포와 "처리하면 오류가 가장 많이 줄어드는 작업" 목록을 실측(원본 불변), 평가서 등급 옆 실측 표시, CLI `rehearse` — 공식 공통컴포넌트 v4.3.2 전체 트리 기대값 고정 |
570
624
  | **v0.42 완료** | 폐쇄망 운영: 오프라인 번들 | `prepare_egovframe_offline_bundle`: OSV Maven 덤프·고정 컴포넌트 아카이브·Initializr zip·원본 태그 미러 + sha256 manifest, `EGOVFRAME_OFFLINE_BUNDLE` 로 모든 다운로드·OSV 조회를 번들로 대체(스냅숏 기준일 표시·오래됨 경고) |
571
625
  | **v0.43 완료** | CI·제출 형식 다변화 | `generate_egovframe_ci(platform=gitlab\|jenkins)`(GitLab 공식 스키마 통과·Declarative Jenkinsfile)와 세 플랫폼 게이트에 `sbom-check --fail-on minimum`, 사내 npm 레지스트리·오프라인 번들 변수, SBOM SPDX 2.3 JSON 출력·점검(공식 spdx-spec v2.3 스키마, 실제 Maven SBOM 에서 CycloneDX 와 판정 일치) |
626
+ | **v0.44 완료** | 보안약점 점검 | `check_egovframe_secure_coding`: 행안부·KISA 개발보안 가이드 구현단계 보안약점 중 정적 패턴 항목(SQL 삽입·XSS·경로 조작·XXE·약한 암호·하드코드 정보·오류 노출 등)을 데이터 규칙으로, 공통컴포넌트 출처 구분, SARIF 2.1.0·CI 게이트·평가서 4절 |
627
+ | **v0.45 완료** | 컨테이너·배포 산출물 | `generate_egovframe_deploy`: Classic war(Tomcat 10.1)·Boot jar 멀티 스테이지 Dockerfile, DbType 별 docker-compose, Kubernetes 매니페스트, 폐쇄망 레지스트리 — hadolint·kubeconform·실제 빌드·기동 검증 |
628
+ | **v0.46 계획** | 5.x 최신 유지 + CI 실행 검증 | `migrate_egovframe_project(target="5.0.2")` 로 5.x 프로젝트 parent·RTE 갱신(적용·컴파일 검증), 생성 `Jenkinsfile`·`.gitlab-ci.yml` 을 실제 Jenkins·GitLab 실행기로 검증 |
629
+
630
+ ## 다음 버전 기획 (v0.44–v0.46)
631
+
632
+ v0.43.0 까지 끝난 상태(2026-10-12, 도구 32종 + CLI 명령 10종, npm 0.43.0 자동 배포)에서 다음 세 릴리스를 아래 순서로 진행합니다. 공통 원칙은 이전과 같습니다 — 규칙은 데이터로, 근거는 공식 문서·저장소에서, 쓰기 도구는 dryRun·transaction, 각 버전은 "완료 정의"를 만족해야 릴리스합니다. 이번 세 버전의 공통 주제는 **납품 품질** 입니다 — 감리·보안약점 진단에서 지적되는 코드 패턴을 미리 찾고(v0.44), 공공 클라우드 전환에 맞춰 컨테이너·배포 산출물을 같은 기준으로 만들며(v0.45), 만든 5.x 프로젝트를 최신 기준으로 유지하고 생성한 CI 를 실제 빌드 서버에서 돌려 확인합니다(v0.46). 선행 조사 근거는 맨 아래 "선행 조사 결과 (2026-10-12)"에 있습니다.
633
+
634
+ ### v0.44.0 — 보안약점 점검 (`check_egovframe_secure_coding`)
635
+
636
+ **목표**: 행정안전부·KISA 「소프트웨어 개발보안 가이드」(2021, 설계단계 20개·구현단계 49개 보안약점)는 정보시스템 감리 대상 사업에 적용되고, 납품 전 보안약점 진단에서 지적된 항목은 그대로 재작업이 됩니다. 지금 서버는 의존성·보안 설정(`sec.security`·CSRF·XSS 필터·보안 헤더)까지만 보고 **소스 코드 패턴**은 보지 않습니다. 공통컴포넌트·생성 코드·사용자 코드에서 정적 패턴으로 근거 있게 잡을 수 있는 구현단계 항목을 먼저 찾아, 진단 전에 고칠 목록을 만듭니다.
637
+
638
+ **범위 (포함)**
639
+ - 새 도구 `check_egovframe_secure_coding(projectDir, rules?, paths?, baselinePath?, format="markdown"|"json"|"sarif", outputPath?)`(33번째, 읽기 전용): 규칙은 `catalog/secure-coding-rules.json` 데이터 — 항목마다 가이드의 보안약점 이름·유형(입력데이터 검증 및 표현·보안기능·에러처리·코드오류·캡슐화·API 오용), CWE 번호, 대상 파일 종류, 패턴, 예외 조건, 심각도, 조치 예시를 둡니다. 1차 규칙(구현단계 49개 중 정적 패턴으로 오탐을 통제할 수 있는 것):
640
+ - **SQL 삽입**: MyBatis·iBATIS 매퍼의 `${…}`(정렬 컬럼처럼 값 목록 검증이 필요한 경우를 구분해 안내), JDBC 문자열 연결 `executeQuery("…" + …)`
641
+ - **크로스사이트 스크립트**: JSP 의 `<%= request… %>`·`${param.…}` 직접 출력, `<c:out escapeXml="false">`
642
+ - **경로 조작**·**신뢰되지 않는 URL 리다이렉트**: `new File(request.getParameter(…))`, `sendRedirect(request.getParameter(…))`
643
+ - **XML 외부 개체 참조(XXE)**: 외부 엔티티를 막지 않은 `DocumentBuilderFactory`·`SAXParserFactory`·`XMLInputFactory`
644
+ - **취약한 암호화 알고리즘·해시**: `MessageDigest.getInstance("MD5"|"SHA-1")`, `Cipher.getInstance("DES…"|"…/ECB/…")`
645
+ - **적절하지 않은 난수**: 보안 문맥(토큰·비밀번호·세션)의 `java.util.Random`
646
+ - **하드코드된 중요정보**: 비밀번호·키 문자열 상수(테스트·예제 경로는 별도 등급)
647
+ - **오류 메시지 정보노출**·**오류 상황 대응 부재**: `printStackTrace()`, 빈 `catch`
648
+ - **신뢰할 수 없는 데이터의 역직렬화**: `ObjectInputStream.readObject` 직접 사용
649
+ - **쿠키·세션 보안 속성**: `HttpOnly`·`Secure` 없이 만드는 `Cookie`, `web.xml`/Boot 설정의 세션 쿠키 속성
650
+ - 결과: 항목별 파일·라인·코드 한 줄·조치 예시, 공통컴포넌트 매니페스트로 **공통컴포넌트 출처**(upstream 원본 그대로인지·사용자 수정인지)를 표시해 "공통컴포넌트 업그레이드로 해결" 과 "직접 수정" 을 나눕니다. `baselinePath` 와 비교(새로 생긴 것만), 예외 처리 파일(`.egovframe-secure-ignore.json` — 규칙·경로·사유·검토자, 사유 없는 예외 거부).
651
+ - **SARIF 2.1.0** 출력 — GitHub code scanning(`upload-sarif`)과 GitLab 보안 리포트에 그대로 올라가게 합니다. `generate_egovframe_ci(supplyChain=true)` 게이트에 `secure --fail-on high` 단계(세 플랫폼)를 선택으로 더합니다.
652
+ - 평가서 4절(보안)에 보안약점 건수·심각도·출처 요약, 공급망 등급 산식에 반영할지는 실측 후 결정(산식 변경 시 문서화). CLI `secure`(지표 `high`·`medium`·`total`·`new`).
653
+
654
+ **범위 (제외)**: 설계단계 20개 항목(요구사항·설계 문서 대상), 데이터 흐름(taint) 분석 — 패턴 기반이며 공인 진단도구를 대체하지 않는다는 점을 결과에 명시, 자동 수정(조치 예시까지)
655
+
656
+ **검증 기준**: 규칙마다 양성·음성 픽스처(오탐 방지 사례 포함), 공식 공통컴포넌트 v3.10.0·v4.3.2 회귀 코퍼스와 공식 5.x 템플릿 2종의 규칙별 건수를 `catalog/migration-corpus.json` 에 기대값으로 고정(±1%), 공식 템플릿에서 높음 등급 0건이 아니면 근거를 README 에 기록, SARIF 출력이 OASIS SARIF 2.1.0 공식 JSON 스키마(테스트 고정물) 통과, Windows 게이트 통과
657
+
658
+ **완료 정의**: 도구 33종, `docs/design-secure-coding.md`(규칙 표·근거·오탐 통제), README 「납품 전 보안약점 점검」 절과 CI 예시(SARIF 업로드)
572
659
 
573
- ## 다음 버전 기획 (v0.41–v0.43)
660
+ **결과(2026-10-13) — 완료**: `src/secure-coding.ts`(규칙 엔진·주석 제거·출처·예외·지문·SARIF)와 규칙 데이터 20종(가이드 항목 14개). 실측: 공식 공통컴포넌트 v3.10.0 495건·v4.3.2 516건(둘 다 높음 0 — 중간은 대부분 `<c:out escapeXml="false">` 302/304건, 낮음은 디버그 출력·`printStackTrace`), **v5.0.7 전체 트리 38건**(`escapeXml="false"` 6·디버그 7), 공식 web·boot-web 템플릿 0건, 저장소 템플릿은 simple-backend 11(디버그)·simple-homepage 7(`escapeXml="false"`)·portal-site 6(docker-compose·설정 평문 비밀번호)·enterprise-business 1. 계획과 달라진 점: (a) **주석 제거가 오탐 통제의 핵심**이었습니다 — 선행 조사에서 센 매퍼의 `${…}` 96건(v4.3.2)은 전부 "`${searchKeyword}` 를 `#{searchKeyword}` 로 변경" 주석이라 실제 SQL 삽입 패턴은 0 입니다. 반대로 JSP 의 HTML 주석 안 EL 은 서버에서 실행되므로 지우지 않습니다. (b) JSP 의 EL 은 **태그 속성 안이면 출력되지 않는다**는 점을 규칙(`stripCustomTags`)에 넣어 `<c:if test="${param.x}">`·`<spring:message code="${param.x}">` 오탐을 없앴고, `<c:out>` 값 안의 `'<br/>'` 때문에 170건을 놓치던 정규식을 따옴표 단위로 고쳤습니다. (c) 공급망 등급 산식에는 넣지 않았습니다 — 패턴 기반이라 확정 판정이 아니고, 공통컴포넌트 전체를 담은 트리는 이미 D 입니다. (d) GitLab 의 보안 대시보드는 SARIF 를 직접 받지 않아 아티팩트 보관으로 바꿨고, GitHub 업로드는 Advanced Security 가 없는 비공개 저장소에서도 게이트 판정을 흔들지 않게 `continue-on-error` 로 둡니다. (e) 공식 템플릿 기대값은 Initializr 고정 commit 템플릿만 단언하고, 브랜치 기준 저장소 템플릿은 차이를 로그로 남깁니다(upstream 변경 가능).
574
661
 
575
- v0.40.0 까지 끝난 상태(2026-10-07, 도구 30종 + CLI 명령 8종, 테스트 약 1,600건, npm 0.40.0 자동 배포)에서 다음 세 릴리스를 아래 순서로 진행합니다. 공통 원칙은 이전과 같습니다 — 규칙은 데이터로, 근거는 공식 저장소에서, 쓰기 도구는 dryRun·transaction, 각 버전은 "완료 정의"를 만족해야 릴리스합니다. 이번 세 버전의 공통 주제는 **현장에서 그대로 쓰기** 입니다 — 자동 단계를 모두 돌린 뒤 사람이 고칠 것이 실제로 얼마나 남는지를 사본에서 재고(v0.41), 망분리된 공공 개발 환경에서도 인터넷 없이 같은 결과를 내며(v0.42), GitHub Actions 와 CycloneDX 밖의 빌드 서버·제출 형식(Jenkins·GitLab, SPDX)으로 넓힙니다(v0.43). 선행 조사 근거는 맨 아래 "선행 조사 결과 (2026-10-07)"에 있습니다.
662
+ ### v0.45.0 — 컨테이너·배포 산출물 (`generate_egovframe_deploy`)
663
+
664
+ **목표**: 공공 정보시스템의 클라우드 네이티브 전환이 진행되면서 표준프레임워크 프로젝트도 컨테이너 이미지와 쿠버네티스 매니페스트를 함께 납품하는 일이 늘었습니다. 지금은 사업마다 Dockerfile 을 손으로 쓰며 Classic(war)·Boot(jar)·DB 종류·`globals.properties` 설정 주입이 매번 달라집니다. 진단 결과(빌드 도구·패키징·DbType·템플릿 종류)로 같은 기준의 배포 산출물을 만듭니다.
665
+
666
+ **범위 (포함)**
667
+ - 새 도구 `generate_egovframe_deploy(projectDir, targets=["docker","compose","k8s"], jdk="17", imageRegistry?, appName?, dryRun=true)`(34번째, 새 파일만):
668
+ - **Dockerfile**(멀티 스테이지): 빌드 스테이지(Maven/Gradle·래퍼, 의존성 캐시 레이어) → 실행 스테이지 — Classic `war` 는 `tomcat:10.1-jdk17-temurin`(Jakarta EE 9+ 를 지원하는 Tomcat 10.1, ROOT 배포), Boot `jar` 는 `eclipse-temurin:17-jre`. 비루트 사용자, `HEALTHCHECK`, 시간대(`Asia/Seoul`)·인코딩, `.dockerignore`.
669
+ - **docker-compose**: 앱 + DbType 에 맞는 DB(mysql·mariadb·postgres; oracle·tibero·altibase·cubrid 는 외부 DB 로 연결 정보만), `globals.properties`·`application.yml` 의 DB 키를 환경 변수로 덮어쓰는 방법(템플릿별 키 표를 데이터로).
670
+ - **Kubernetes**: Deployment(readiness·liveness 프로브, 리소스 요청·제한, 비루트 securityContext)·Service·ConfigMap·Secret(값은 자리표시자)·선택 Ingress.
671
+ - `imageRegistry` 로 기반 이미지 레지스트리를 바꿔 폐쇄망(사내 Harbor 등)에 대응하고, 오프라인 번들 문서에 이미지 반입 절차를 더합니다.
672
+ - 템플릿 종류별 지원표: Classic web·template 4종(war), Boot web·simple-backend·batch-web(jar), 배치 commandline·scheduler(jar, Service 없음), MSA·모바일·프론트엔드 템플릿은 1차 제외(자체 배포 구성이 있거나 정적 자산)를 데이터로 두고 미지원이면 이유를 돌려줍니다.
673
+
674
+ **범위 (제외)**: Helm 차트·Kustomize 오버레이, 레지스트리 push·클러스터 배포 실행, 운영 DB 이관
675
+
676
+ **검증 기준**: 생성 Dockerfile 이 hadolint(고정 버전) 경고 0, 매니페스트가 kubeconform(쿠버네티스 1.31 공식 스키마) 통과, CI 통합에서 공식 `egov-web`(Classic war)·`egov-boot-web`(Boot jar) 템플릿으로 실제 `docker build` → 컨테이너 기동 → HTTP 200 과 HEALTHCHECK healthy, docker-compose(mysql) 기동 후 앱이 DB 에 연결, 게이트에서는 템플릿 종류별 생성 결과 구조 단언·dryRun 무기록·기존 파일 거부
677
+
678
+ **완료 정의**: 도구 34종, `docs/design-deploy.md`, README 「컨테이너·배포 산출물」 절(폐쇄망 이미지 반입 포함)
679
+
680
+ **결과(2026-10-13) — 완료**: `src/deploy.ts`(분석·렌더러)와 규칙 데이터 `catalog/deploy-rules.json`(기반 이미지·DB 서비스·외부 DB·지원 안 함). 실측: 공식 web(Classic)·boot-web(Boot) 템플릿의 Dockerfile 은 hadolint 2.14 경고 0, 매니페스트는 kubeconform 0.7(쿠버네티스 1.31) 통과, 빌드·기동 후 HTTP 200·HEALTHCHECK healthy·실행 uid 10001. 공식 simple-backend(Boot + MySQL 8.4)는 `docker compose up` 후 readiness UP·`/mainPage` 가 초기화 데이터(공지 게시물)를 돌려줘 환경 변수 주입이 동작함을 확인했고, 공식 portal-site(Classic + MySQL)는 설정 파일 덮어쓰기로 사용자 `pst`·비밀번호 `CHANGE_ME` 로 연결돼 메인 페이지가 열렸습니다. 계획과 달라진 점: (a) **Classic 의 DB 설정은 환경 변수로 덮을 수 없었습니다** — Classic 템플릿은 `EgovProperties` 가 `globals.properties` 를 직접 읽어서, WAR 를 이미지 안에서 풀어 두고 설정 파일 사본을 볼륨·Secret 으로 덮어쓰는 방식으로 바꿨습니다(Boot 템플릿은 Spring `Environment` 로 읽어 환경 변수가 그대로 동작). (b) Classic 템플릿의 키는 `Globals.Url`·`Globals.UserName`(Boot 템플릿은 `Globals.<DbType>.Url`)이라 두 형식을 모두 읽습니다. (c) 공식 simple-backend·portal-site 등은 **자체 Dockerfile·compose·k8s 를 갖고 있어** 덮어쓰지 않고 알리며, `dockerfilePath`(예: `deploy/Dockerfile`, `.dockerignore` 는 BuildKit 규칙대로 `<경로>.dockerignore`)로 공존시킵니다. (d) 폐쇄망을 위해 `# syntax` 지시어를 쓰지 않고(BuildKit 내장 프론트엔드), 컨테이너 안에서 Maven 저장소에 닿지 않는 환경을 위해 `buildInImage=false`(미리 빌드한 산출물) 경로를 더했습니다 — 개발 환경 실측도 이 경로로 했고, CI 는 이미지 안에서 빌드합니다. (e) Servlet 6.1 이상을 직접 선언한 프로젝트는 Tomcat 11.0 을 고릅니다(5.x 공식 parent 는 Servlet 5.0·fileupload2 servlet6 이라 기본 10.1).
681
+
682
+ ### v0.46.0 — 5.x 최신 유지 + 생성 CI 실행 검증
683
+
684
+ **목표**: 공식 Initializr 템플릿은 여전히 parent 5.0.0 으로 만들어져(공식 parent 최신 5.0.2) 새 프로젝트가 만들어지는 순간부터 기준 미만입니다. 3.x/4.x → 5.x 전환(`migrate`)은 있지만 **5.x 안의 갱신**(parent·RTE 5.0.x·Spring Boot 패치, 공통컴포넌트 5.0.x → 5.0.7)은 사람이 합니다. 또 v0.43 의 GitLab·Jenkins 설정은 스키마·구조만 확인했고 실제 빌드 서버에서 돌려 보지 않았습니다.
685
+
686
+ **범위 (포함)**
687
+ - `migrate_egovframe_project(target="5.0.2")` — 이미 5.x 인 프로젝트의 갱신 모드: parent 버전, RTE 모듈 좌표, parent 관리 속성(`spring.version` 등)을 공식 parent 5.0.2 기준으로 맞추는 auto 항목과 5.0.0 → 5.0.2 사이 RTE 변경(공식 `egovframe-runtime` 태그 비교로 생성한 규칙 데이터)의 manual 항목, `apply=true`(transaction·백업)와 `verify=true`(compile). 공통컴포넌트는 기존 `upgrade_egovframe_project` 로 5.0.7 까지 이어 주는 안내와 평가서 2절 "5.x 최신 유지" 항목.
688
+ - `create_egovframe_project(alignParent=true)` 선택 옵션 — 생성 직후 같은 갱신을 적용(기본은 공식 템플릿 그대로).
689
+ - 생성 CI 실행 검증(CI 통합): (1) **Jenkins** — 공식 `jenkins/jenkins` LTS 컨테이너에 Pipeline 플러그인을 고정 버전으로 설치하고, 선언형 문법 검증(declarative linter) 후 생성 `Jenkinsfile` 을 공식 web 템플릿 작업공간에서 실제로 실행해 Build·SBOM·SBOM check·Assessment 단계와 보관 산출물을 확인, (2) **GitLab** — 생성 `.gitlab-ci.yml` 을 로컬 실행기로 돌려 build·supply-chain job 성공과 산출물을 확인(실행기 선택은 선행 조사에서 확정).
690
+ - 보류였던 브랜치 보호 설정을 README 운영 절차로 확정.
691
+
692
+ **범위 (제외)**: 5.x 의 마이너 이상 갱신(5.1 등 미출시), Jenkins·GitLab 서버 설정 자동화, 공통컴포넌트 사용자 수정의 자동 재적용
693
+
694
+ **검증 기준**: Initializr 고정 commit 의 공식 web·boot-web 템플릿을 5.0.2 로 갱신 → JDK 17 `mvn compile` 통과·의존성 점검 기준 미만 감소(실측값 고정)·평가서 공급망 등급 변화 기록, 갱신 dryRun 무기록·fault-injection 롤백, Jenkins·GitLab 실행 검증 통과(CI 통합)
695
+
696
+ **완료 정의**: 도구 34종(변화 없음), `docs/design-migration.md` 에 5.x 갱신 절, README 「CI 설정 생성」 절에 실행 검증 결과
697
+
698
+ ### 보류·운영 항목
699
+
700
+ - **브랜치 보호(소유자 1회)**: `main` 에 "Require status checks to pass"(gate 6 + integration)를 켜면 실패 상태 병합이 재발하지 않습니다(v0.46 에서 운영 절차로 확정). `gh api -X PUT repos/EricSeokgon/egovframe-scaffold-mcp/branches/main/protection --input protection.json`(`required_status_checks.contexts` 에 체크 이름 7개, `enforce_admins: false`, `required_pull_request_reviews: null`, `restrictions: null`).
701
+ - **Initializr upstream**: 템플릿 pom parent 5.0.0 문제를 포함한 기존 4건은 upstream 이슈로 제출할 가치가 있습니다(v0.46 의 갱신 모드는 그동안의 우회).
702
+ - **기준 없음 잔여**: `xerces:xercesImpl` 은 공개 기준이 없어 그대로 둡니다.
703
+ - **응답 본문 영문화**: 평가서·점검 결과의 라벨·헤더 영문화(`--lang en`)는 계속 후순위입니다.
704
+ - **MCP 신기능**: `tasks`(장시간 도구의 비동기 실행)는 SDK 1.32.1 에서도 `experimental/tasks` 아래에 있어 보류합니다. 안정 API 로 올라오면 리허설·번들·배포 이미지 빌드처럼 수 분 걸리는 도구부터 적용합니다.
705
+
706
+ ### 선행 조사 결과 (2026-10-12)
707
+
708
+ - **upstream 태그**: `egovframe-runtime` 최신 v5.0.2-Final, `egovframe-common-components` v5.0.7(`7912e13`), `egovframe-vscode-initializr` 최신 태그 v5.0.6(`84d3682`)·`main` `bc18641`, `egovframe-development` v5.0.2, `egovframe-ai-rag` v5.0.0 — 지난 기획(2026-10-07) 이후 새 태그 없음.
709
+ - **개발보안 기준**: 행정안전부·KISA 「전자정부 SW 개발·운영자를 위한 소프트웨어 개발보안 가이드」(2021 개정)는 설계단계 보안요구 20개·구현단계 보안약점 49개를 두고, 정보시스템 감리 대상 사업에 적용됩니다(개발보안 의무화 2012-12). 항목 이름·유형은 가이드 원문 표기로 규칙 데이터에 옮깁니다.
710
+ - **코퍼스 실측(패턴 빈도, 회귀 코퍼스 부분 트리)**: 공식 공통컴포넌트 v3.10.0 / v4.3.2 — MyBatis·iBATIS 매퍼 중 `${…}` 를 쓰는 파일 42 / 48개(84 / 96건), JSP 스크립틀릿 출력 `<%=` 192 / 195건, `printStackTrace()` 22 / 47건, 약한 해시·암호 호출 1 / 1건, `new Random(` 4 / 3건. 매퍼의 `${…}` 는 정렬 컬럼·테이블 접두어처럼 바인딩으로 바꿀 수 없는 경우가 섞여 있어 규칙의 예외 조건(허용 목록 검증 여부)이 오탐 통제의 핵심입니다.
711
+ - **배포 기반 이미지**: Docker Hub 공식 `tomcat:10.1-jdk17-temurin`(Jakarta EE 9+ 서블릿 — 5.x 템플릿의 `jakarta.servlet-api` 5.0 과 호환)과 `eclipse-temurin:17-jre` 태그가 있습니다.
712
+ - **Jenkins 실행 검증**: `jenkinsci/jenkinsfile-runner` 는 2022년 이후 이미지 갱신이 없어(마지막 태그 1.0-beta-32) 쓰지 않고, 공식 `jenkins/jenkins` LTS + 고정 플러그인 방식으로 검증합니다.
713
+ - **도구 의존성**: `@modelcontextprotocol/sdk` 최신 1.32.1(동봉과 같음), `tasks` 는 여전히 `experimental` 경로.
714
+
715
+ ## 이전 기획 (v0.41–v0.43, 완료)
716
+
717
+ v0.40.0 까지 끝난 상태(2026-10-07, 도구 30종 + CLI 명령 8종, 테스트 약 1,600건, npm 0.40.0 자동 배포)에서 다음 세 릴리스를 아래 순서로 진행했습니다. 세 버전 모두 2026-10-12 까지 완료했으며 기획 원문은 기록으로 남기고 결과를 항목 아래에 적었습니다. 공통 원칙은 이전과 같습니다 — 규칙은 데이터로, 근거는 공식 저장소에서, 쓰기 도구는 dryRun·transaction, 각 버전은 "완료 정의"를 만족해야 릴리스합니다. 이번 세 버전의 공통 주제는 **현장에서 그대로 쓰기** 입니다 — 자동 단계를 모두 돌린 뒤 사람이 고칠 것이 실제로 얼마나 남는지를 사본에서 재고(v0.41), 망분리된 공공 개발 환경에서도 인터넷 없이 같은 결과를 내며(v0.42), GitHub Actions 와 CycloneDX 밖의 빌드 서버·제출 형식(Jenkins·GitLab, SPDX)으로 넓힙니다(v0.43). 선행 조사 근거는 맨 아래 "선행 조사 결과 (2026-10-07)"에 있습니다.
576
718
 
577
719
  ### v0.41.0 — 전환 리허설 (`rehearse_egovframe_migration`)
578
720
 
@@ -626,7 +768,7 @@ v0.40.0 까지 끝난 상태(2026-10-07, 도구 30종 + CLI 명령 8종, 테스
626
768
 
627
769
  **결과(2026-10-11) — 완료**: `src/ci-config.ts`(세 플랫폼이 같은 게이트 명령 목록 `supplyChainCommands` 를 씀)와 `src/spdx.ts`(`cdxToSpdx`·`spdxToCdx`). 실측: 공식 web 템플릿을 실제 Maven·cyclonedx-maven-plugin 으로 만든 SBOM(67 component, OSV 27건)을 SPDX 2.3 으로 바꾸면 패키지 68·관계 165 로 공식 spdx-spec v2.3 스키마를 통과하고, SPDX 를 점검한 결과가 CycloneDX 점검과 **component 67·최소 요소 7종의 요소별 충족 수(68/68 …)·판정 ready 까지 같으며** 둘을 비교하면 차이 0 입니다. 생성 `.gitlab-ci.yml` 은 maven·gradle·게이트 유무·환경 변수 조합 4가지 모두 GitLab 공식 CI 스키마(v19.4.1-ee 고정물)를 통과합니다. 계획과 달라진 점: (a) **SPDX 점검은 별도 규칙을 두지 않고** SPDX 를 내부 CycloneDX 모양으로 옮겨 같은 최소 요소·재판정·비교 코드를 그대로 씁니다 — 대응(공급자 = `PackageSupplier`/`PackageOriginator`, 의존관계 = 그 패키지가 주어인 `DEPENDS_ON`, 작성자 = `creators` 의 Person·Organization)은 `src/spdx.ts` 머리 주석과 「SBOM 제출 준비」 표에 있습니다. (b) "의존 없음"과 "모름"을 구분하려고 의존이 없는 패키지는 `DEPENDS_ON NONE`(SPDX 2.3 §11.1)으로 쓰고, `NOASSERTION` 은 모름으로 읽습니다. (c) 기준 판정(`egovframe:*`)과 OSV 결과를 SPDX 의 annotations·`SECURITY`/`advisory` externalRefs 로 옮겨, SPDX 로 낸 뒤에도 재판정의 "생성 이후 바뀐 판정"·"새로 알려진 취약점"이 동작합니다. (d) 생성 시각은 SPDX 필수 항목이라 원본에 없으면 변환 시각을 넣고 알립니다(이 경우만 판정이 달라질 수 있음). (e) 게이트의 `sbom-check --fail-on minimum` 은 공급자 단서(`supplier` 또는 pom `<organization>`)가 없으면 실패하므로 `supplier` 파라미터를 더하고 생성 응답이 미리 알립니다. (f) GitLab 은 JUnit 리포트와 `artifacts:reports:cyclonedx`, Jenkins 는 Linux·Windows 에이전트 공용 실행(`isUnix()` 로 `sh`/`bat`)을 넣었습니다. Jenkins 실제 실행 검증은 보류 항목으로 남깁니다.
628
770
 
629
- ### 보류·운영 항목
771
+ ### 보류·운영 항목 (당시)
630
772
 
631
773
  - **Jenkins 실행 검증**: 생성 `Jenkinsfile` 은 Declarative 구조만 단언합니다. 실제 Jenkins(컨테이너)에서 돌리는 통합 검증은 아직 없습니다.
632
774
  - **브랜치 보호(소유자 1회)**: `main` 에 "Require status checks to pass"(gate 6 + integration)를 켜면 실패 상태 병합이 재발하지 않습니다. `gh api -X PUT repos/EricSeokgon/egovframe-scaffold-mcp/branches/main/protection --input protection.json`(`required_status_checks.contexts` 에 체크 이름 7개, `enforce_admins: false`, `required_pull_request_reviews: null`, `restrictions: null`).
@@ -940,6 +1082,8 @@ v0.28.1 까지의 상태에서 다음 세 릴리스를 아래 순서로 진행
940
1082
 
941
1083
  ## 변경 이력
942
1084
 
1085
+ - **0.45.0** — 컨테이너·배포 산출물(도구 33 → 34종). (1) 새 도구 `generate_egovframe_deploy(projectDir, targets=["docker","compose","k8s"], jdk="17"|"21", imageRegistry="docker.io/library", image?, appName?, buildInImage=true, dockerfilePath="Dockerfile", ingressHost?, dryRun=true, format)`: `src/deploy.ts` — `analyzeDeploy`(빌드 도구·래퍼·war/jar·Boot·웹·actuator 프로브·Tomcat 10.1/11·포트·컨텍스트 경로·DB: `Globals.<type>.Url`/`Globals.Url`/`spring.datasource.url`, 별칭, 초기화 SQL, 지원 안 함 3종), `renderDockerfile`(멀티 스테이지 Maven·Gradle 캐시 마운트·Maven 5xx 재시도·plain 산출물 제외·WAR 풀기·비루트 uid 10001·TZ·UTF-8·MaxRAMPercentage·HEALTHCHECK·`ARG BASE_REGISTRY`·미리 빌드 경로), `.dockerignore`(미리 빌드 시 산출물 화이트리스트), `renderCompose`(DB 컨테이너 mysql 8.4·mariadb 11.4·postgres 16, 초기화 마운트, 헬스체크 후 기동, `.env.example`), `renderClassicConfig`(설정 사본), `renderKubernetes`(ConfigMap·Secret·Deployment 프로브·보안 설정·리소스·Service·Ingress). 규칙 데이터 `catalog/deploy-rules.json`. 새 파일만(하나라도 있으면 무기록), 템플릿 자체 배포 구성 안내. 도구 메타 비읽기·비파괴, outputSchema(13종), 영문 설명, AGENTS.md. (2) 테스트: 신규 `test:deploy` 49단언(게이트, 공식 Compose 스키마 고정물), `test:deploy-live`(CI 통합: hadolint 2.14·kubeconform 0.7 sha256 고정 다운로드, 공식 web·boot-web 빌드·기동·헬스·비루트, simple-backend compose + MySQL 데이터 확인, `DEPLOY_LIVE_PREBUILT=1` 로 미리 빌드 경로), `output-schemas`·`handshake` 34종·13종. 설계: [docs/design-deploy.md](docs/design-deploy.md). `server.json` 0.45.0.
1086
+ - **0.44.0** — 보안약점 점검(도구 32 → 33종). (1) 새 도구 `check_egovframe_secure_coding(projectDir, rules?, paths?, includeTests=true, baselinePath?, sarifPath?, overwrite=false, maxFindings=2000, top=40, format="markdown"|"json"|"sarif")`: `src/secure-coding.ts` — 규칙 데이터 `catalog/secure-coding-rules.json`(schemaVersion 1, 20종·가이드 항목 14개, 유형·CWE·등급·대상·패턴·`unless`·`fileHas`/`fileLacks`·`downgrade`/`escalate`/`requireNear`·`stripCustomTags`·`scope`), Java 주석 렉서·XML/JSP 주석 제거(줄 수 유지), 대상 판별(java·jsp·mapper·sqlmap·config, 메시지 번들 제외), 테스트 코드 등급 낮춤, 출처(매니페스트 해시로 원본·수정본·매니페스트 없음·프로젝트·테스트), 예외 파일 `.egovframe-secure-ignore.json`(사유 5자 이상·검토자 필수, glob·라인), 지문(규칙·파일·정규화한 줄·순번)과 baseline(JSON·SARIF), SARIF 2.1.0(규칙·CWE taxonomy·security-severity·partialFingerprints) 기록(transaction, overwrite). 도구 메타 비읽기·비파괴·멱등, outputSchema(12종), 영문 설명, AGENTS.md. (2) 평가서 4절에 보안약점 요약(등급 산식 미반영), 회귀 코퍼스 기대값에 규칙별 건수(`scripts/corpus-lib.mjs` `secure`), `catalog/migration-corpus.json` `secureTemplates`. (3) CLI `secure`(명령 11종, 지표 high·medium·low·total·new), `generate_egovframe_ci(secureCoding=true)` — 세 플랫폼 게이트에 `secure --fail-on high` 단계, GitHub 은 `security-events: write`·`upload-sarif`(continue-on-error), GitLab·Jenkins 는 SARIF 보관. (4) 테스트: 신규 `test:secure-coding` 52단언(게이트, OASIS SARIF 2.1.0 스키마 고정물)·`test:secure-live`(CI 통합: 공식 템플릿 건수·SARIF 스키마), `test:ci` 에 secureCoding(GitHub 권한·업로드, GitLab 스키마, Jenkins 단계), `output-schemas`·`handshake` 33종·12종, `cli` 11종, CI 통합의 actionlint 대상 워크플로에 SARIF 업로드 포함. 설계: [docs/design-secure-coding.md](docs/design-secure-coding.md). `server.json` 0.44.0.
943
1087
  - **0.43.0** — CI·제출 형식 다변화: GitLab·Jenkins, SPDX(도구 32종 유지). (1) `generate_egovframe_ci` 에 `platform="github"|"gitlab"|"jenkins"`: `src/ci-config.ts` — `generateGitlabCi`(`.gitlab-ci.yml`, `maven:3.9-eclipse-temurin-<JDK>`·`eclipse-temurin:<JDK>` 이미지, 로컬 저장소 캐시, JUnit 리포트, `supply-chain` job 은 `needs: []`·Node 준비·`artifacts:reports:cyclonedx`)·`generateJenkinsfile`(Declarative — options·environment·`Build`/`SBOM`/`SBOM check`/`Assessment` 단계·`post { always { archiveArtifacts } }`, `isUnix()` 로 `sh`/`bat`), 세 플랫폼 공통 게이트 명령 `supplyChainCommands`(sbom → **`sbom-check --fail-on minimum`**(GitHub 게이트에도 추가) → assess), 새 파라미터 `supplier`(SBOM 공급자)·`npmRegistry`(`NPM_CONFIG_REGISTRY`)·`offlineBundle`(`EGOVFRAME_OFFLINE_BUNDLE`) — 모두 형식 제한으로 설정 파일 주입 차단, 공급자 단서가 없으면 게이트 실패 예고(`notes`). (2) SPDX 2.3: `src/spdx.ts` — `cdxToSpdx`(패키지·`DESCRIBES`·`DEPENDS_ON`(의존 없음 `NONE`)·purl/cpe/swid externalRefs·supplier/originator·creators·created·체크섬·선언 라이선스(`LicenseRef-` + `hasExtractedLicensingInfos`)·OSV 권고 `SECURITY`/`advisory`·`egovframe:*` annotations, serialNumber UUID 로 결정적 namespace)·`spdxToCdx`(점검용, `*_DEPENDENCY_OF` 뒤집기·`NOASSERTION` 은 모름). `generate_egovframe_sbom(bomFormat="spdx-json")`(기본 경로 `sbom/bom.spdx.json`, 최소 요소는 SPDX 를 되읽어 판정), `check_egovframe_sbom` 이 CycloneDX·SPDX 2.x 자동 판별(`document.format`, 형식이 다른 baseline 은 purl 로 비교, SPDX 의 `vex=true` 는 거부). CLI `sbom --bom-format spdx-json`. (3) 테스트: 신규 `test:spdx` 43단언(게이트, 공식 spdx-spec v2.3 스키마 고정물), `test:ci` 에 GitLab 공식 CI 스키마(gitlab v19.4.1-ee 고정물, devDependency `yaml`)·Jenkinsfile 구조·주입 거부, `test:sbom-live`(CI 통합)에 실제 Maven SBOM 의 SPDX 스키마·판정 일치, `test:sbom-check` 의 비 CycloneDX 거부 단언을 SPDX 3.0 등으로 갱신. (4) CI: integration job 의 Maven 이 원격 저장소 5xx(502 등)를 3초 간격 최대 5회 재시도(#53). (5) `generate_egovframe_sbom`: cyclonedx-maven-plugin 출력에 `metadata.timestamp` 가 없으면(CI 러너에서 실측) 생성 시각으로 채우고 알림 — v0.40 이후 간헐적이던 sbom-live 최소 요소 실패의 원인. `server.json` 0.43.0.
944
1088
  - **0.42.0** — 폐쇄망 오프라인 번들(도구 31 → 32종). (1) 새 도구 `prepare_egovframe_offline_bundle(outputDir, include=["osv","components","templates","origin"], templates?, dryRun=true, format)`: `src/offline-bundle.ts`·`src/offline-bundle-plan.ts` — OSV Maven 전체 덤프(`osv-vulnerabilities/Maven/all.zip`, 레코드 수·원본 갱신 시각 기록), 카탈로그 고정 커밋의 공통컴포넌트 아카이브(sha256·크기 검증), 템플릿(기본: 고정 지문이 있는 Initializr zip 12종, 저장소 템플릿은 지정 시 codeload zip), 공식 공통컴포넌트 태그 전부의 내용 포함 bare 미러(`git fetch --depth 1 +refs/tags/*`)를 임시 디렉터리에 받아 `bundle-manifest.json`(schemaVersion 1, 파일별 path·kind·url·sha256·bytes·fetchedAt)과 함께 새(또는 빈) 디렉터리로 옮김, 고정 지문 불일치·실패 시 무흔적. 도구 메타 비읽기·비파괴·openWorld, outputSchema(11종), 영문 설명, AGENTS.md 도구 목록. (2) `EGOVFRAME_OFFLINE_BUNDLE`: `fetchWithTimeout`(GET)과 카탈로그 아카이브 다운로드가 manifest 의 같은 URL 을 지문 검증 후 번들에서 돌려줌(변조 거부, 프로세스당 1회 검증), `defaultOsvQuery` 가 로컬 덤프로 판정(`buildOsvIndex`·`queryOsvIndex`·`inOsvRange`·`compareMavenVersions` — Maven ComparableVersion 요지, `versions` 목록 또는 ECOSYSTEM 범위, 철회 제외), `GitOriginSource` 가 번들 미러를 씀(`for-each-ref` 태그 목록, 원격 fetch 없음, 없는 태그 안내), OSV 를 쓴 결과(의존성 점검·SBOM 생성·SBOM 점검)에 스냅숏 기준일 노트와 30일 경고(`EGOVFRAME_BUNDLE_MAX_AGE_DAYS`). (3) `diagnose_egovframe_network` 가 실패 시 오프라인 번들 처방(bash·cmd·PowerShell)과 사용 중 표시, CLI `bundle`(`--write` 로만 받음, `--output-dir` 는 현재 디렉터리 기준), `server.json` 환경변수 `EGOVFRAME_OFFLINE_BUNDLE`(4종). (4) 테스트: 신규 `test:offline-bundle` 30단언(게이트)·`test:bundle-live`(CI 통합: 실제 번들, 로컬 OSV = 온라인, fetch 차단 상태의 생성·조립·재조립·SBOM 재점검), `registry` 환경변수 4종, `output-schemas`·`handshake` 32종·11종, `cli` 명령 10종. 설계: [docs/design-offline-bundle.md](docs/design-offline-bundle.md). (5) 런타임 의존성 `handlebars` 4.7.9 → 4.7.10(GHSA-xw65-4hp5-5hc7·GHSA-8r5x-fm3f-whwj·GHSA-p8wg-vrv2-v86f, `npm audit --omit=dev` 게이트). `server.json` 0.42.0.
945
1089
  - **0.41.0** — 전환 리허설(도구 30 → 31종). (1) 새 도구 `rehearse_egovframe_migration(projectDir, steps=["reassemble","migrate","verify","align-pom"], components?, sourceTag="auto", keepWorkspace=false, timeoutMs=900000, topN=20, format)`: `src/rehearse.ts` — 사본(`EGOVFRAME_CACHE_DIR/rehearsal`, 빌드 산출물·VCS·백업 제외, 작업 디렉터리가 프로젝트 안이면 거부)에서 재조립 → 전환 적용 → 컴파일(Maven 은 `-Dmaven.compiler.fork=true`·`JDK_JAVAC_OPTIONS=-Xmaxerrs 100000`) → `alignPomToReference`(공식 공통컴포넌트 고정 태그 pom 기준: parent 추가·교체, 누락 좌표 추가(test 제외), 버전·scope 정렬, parent 가 정의하는 속성의 프로젝트 재정의 삭제, 주석·dependencyManagement·plugin·profiles 제외, 멱등) → 컴파일. `analyzeErrors`(누락 패키지 — "package X does not exist"·symbol 의 package·파일 import 문으로 찾은 타입의 패키지, 연쇄 — 같은 파일·누락 패키지가 있는 파일이 선언한 타입의 멤버·Lombok 생성 멤버, 기타; 연쇄는 파일의 첫 누락 패키지에 귀속, 후보 좌표 `packageHint`, 기타 오류는 수동 항목·규칙과 연결, 디렉터리·파일 상위), 작업 목록(pom 맞춤이 없애는 오류 수 → 누락 패키지 → 파일), pom 패치(400줄 상한), 실행 전후 지문(`fingerprintTree`)으로 원본 불변 확인, 단계 실패는 기록하고 계속, 최근 결과를 `rehearsal/records/<경로 해시>.json` 에 저장. 도구 메타 비읽기·비파괴·멱등·openWorld, outputSchema(10종), 영문 설명, AGENTS.md 도구 목록. (2) 평가서 6절에 최근 리허설 실측(등급 산식과 별개), 맺음말의 재조립 안내를 `reassemble_egovframe_components`(전환 적용보다 먼저)로 정정. (3) CLI `rehearse`(지표 `errors`·`automation`·`aligned`·`files`·`unlinked`·`failedSteps`). (4) 수정: `parseBuildErrors` 가 Maven `[WARNING]`·javac 린트 경고(`[removal]` 등) 줄을 오류로 세던 문제와 fork 형식의 `error:` 접두, 4.x 의 `org.egovframe.rte` 좌표(버전 4.*)를 5.x 세대로 분류하던 문제(재조립 후보 태그가 5.x 로만 좁혀짐). `runBuild(extraArgs, env)`·`ResolvedCommand.env`, pom 에 소스 인코딩이 없으면 리허설 컴파일에 UTF-8. (5) 테스트: 신규 `test:rehearse` 42단언(게이트)·`test:rehearse-live`(CI 통합: 공식 v4.3.2 전체 트리 리허설 기대값 `catalog/migration-corpus.json` 의 `rehearsal`), `test:output-schemas` 54·`handshake` outputSchema 10종·`test:cli` 명령 9종. 설계: [docs/design-migration.md](docs/design-migration.md) 리허설 절. `server.json` 0.41.0.
@@ -0,0 +1,114 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "surveyedAt": "2026-10-13",
4
+ "note": "generate_egovframe_deploy(v0.45) 의 기반 이미지·DB 서비스·설정 주입 규칙. 이미지 태그는 Docker Hub 공식 이미지 기준이며 BASE_REGISTRY 로 사내 레지스트리(프록시 캐시)로 바꿀 수 있다.",
5
+ "jdks": [
6
+ "17",
7
+ "21"
8
+ ],
9
+ "images": {
10
+ "maven": "maven:3.9-eclipse-temurin-{jdk}",
11
+ "jdk": "eclipse-temurin:{jdk}-jdk",
12
+ "tomcat": "tomcat:10.1-jdk{jdk}-temurin",
13
+ "jre": "eclipse-temurin:{jdk}-jre",
14
+ "tomcat11": "tomcat:11.0-jdk{jdk}-temurin"
15
+ },
16
+ "runtime": {
17
+ "tomcat": {
18
+ "port": 8080,
19
+ "webapps": "/usr/local/tomcat/webapps",
20
+ "note": "Classic war — 기본 Tomcat 10.1(Servlet 6.0, 5.x 템플릿의 jakarta.servlet-api 5.0·6.0 과 commons-fileupload2-jakarta-servlet6 호환), pom 이 jakarta.servlet-api 6.1 이상을 직접 선언하면 Tomcat 11.0. ROOT 로 풀어서 배포"
21
+ },
22
+ "boot": {
23
+ "port": 8080,
24
+ "note": "Boot 실행 jar — java -jar"
25
+ }
26
+ },
27
+ "user": {
28
+ "uid": 10001,
29
+ "name": "app"
30
+ },
31
+ "timezone": "Asia/Seoul",
32
+ "databases": {
33
+ "mysql": {
34
+ "image": "mysql:8.4",
35
+ "port": 3306,
36
+ "rootUser": "root",
37
+ "env": {
38
+ "rootPassword": "MYSQL_ROOT_PASSWORD",
39
+ "database": "MYSQL_DATABASE",
40
+ "user": "MYSQL_USER",
41
+ "password": "MYSQL_PASSWORD"
42
+ },
43
+ "command": [
44
+ "--character-set-server=utf8mb4",
45
+ "--collation-server=utf8mb4_unicode_ci",
46
+ "--lower-case-table-names=1"
47
+ ],
48
+ "healthcheck": "mysqladmin ping -h 127.0.0.1 -uroot -p\"$$MYSQL_ROOT_PASSWORD\" --silent",
49
+ "data": "/var/lib/mysql",
50
+ "initdb": "/docker-entrypoint-initdb.d"
51
+ },
52
+ "maria": {
53
+ "image": "mariadb:11.4",
54
+ "port": 3306,
55
+ "rootUser": "root",
56
+ "env": {
57
+ "rootPassword": "MARIADB_ROOT_PASSWORD",
58
+ "database": "MARIADB_DATABASE",
59
+ "user": "MARIADB_USER",
60
+ "password": "MARIADB_PASSWORD"
61
+ },
62
+ "command": [
63
+ "--character-set-server=utf8mb4",
64
+ "--collation-server=utf8mb4_unicode_ci",
65
+ "--lower-case-table-names=1"
66
+ ],
67
+ "healthcheck": "healthcheck.sh --connect --innodb_initialized",
68
+ "data": "/var/lib/mysql",
69
+ "initdb": "/docker-entrypoint-initdb.d"
70
+ },
71
+ "postgres": {
72
+ "image": "postgres:16",
73
+ "port": 5432,
74
+ "rootUser": "postgres",
75
+ "env": {
76
+ "rootPassword": "POSTGRES_PASSWORD",
77
+ "database": "POSTGRES_DB",
78
+ "user": "POSTGRES_USER",
79
+ "password": "POSTGRES_PASSWORD"
80
+ },
81
+ "command": [],
82
+ "healthcheck": "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\"",
83
+ "data": "/var/lib/postgresql/data",
84
+ "initdb": "/docker-entrypoint-initdb.d"
85
+ }
86
+ },
87
+ "dbAliases": {
88
+ "mariadb": "maria",
89
+ "postgresql": "postgres",
90
+ "pgsql": "postgres"
91
+ },
92
+ "externalDatabases": {
93
+ "oracle": "라이선스로 공개 이미지를 쓰지 않습니다 — 기관 DB 또는 별도 컨테이너를 연결 정보로만 연결",
94
+ "tibero": "상용 DB — 연결 정보로만 연결",
95
+ "altibase": "상용 DB — 연결 정보로만 연결",
96
+ "cubrid": "공식 이미지 태그·초기화 방식이 템플릿 스크립트와 맞지 않아 연결 정보로만 연결",
97
+ "goldilocks": "상용 DB — 연결 정보로만 연결",
98
+ "hsql": "내장(메모리) DB — DB 컨테이너 없이 앱만 띄움"
99
+ },
100
+ "unsupported": [
101
+ {
102
+ "id": "no-build-file",
103
+ "reason": "pom.xml·build.gradle 이 없습니다(프론트엔드·정적 자산 템플릿은 각자의 배포 방식을 쓰세요)"
104
+ },
105
+ {
106
+ "id": "multi-module",
107
+ "reason": "멀티 모듈(pom <modules>·settings.gradle include) 프로젝트 — 모듈별로 이미지를 만들어야 해 1차 범위 밖입니다(MSA 템플릿은 저장소의 자체 배포 구성을 쓰세요)"
108
+ },
109
+ {
110
+ "id": "not-runnable",
111
+ "reason": "war 도 실행 jar(Spring Boot)도 아닌 라이브러리 jar — 실행할 수 있는 배포 단위가 없습니다"
112
+ }
113
+ ]
114
+ }