feat: add prerequisites, offline prerequisite setup and version tabs

- EXE versions: prerequisite list with the built-in catalog, custom
  installers, download link checks and install file analysis; entries
  are added by the user (no automatic adding), one "추가" dialog with
  기본 목록 / 직접 추가 tabs
- offline prerequisite setup: single exe made from PrerequisiteSetup.exe
  (Windows task dialog, no prerequisites) plus every installer, hash
  checked before, while and after appending; optional WebView2 Runtime
  chosen in the save dialog; replaces an existing file only after the
  user agrees (CLI --replace)
- desktop: progress popup with 생성위치 열기, save dialog fix for
  verbatim paths, EXE 서명 and 설치파일 생성 as version tabs, start
  screen 도구 › 서명하기 placeholder
- CLAUDE.md: results are overwritten only with the user's consent
- test kit and scripts for Windows Sandbox and Hyper-V checks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jychoi4andClaude Opus 5.5 committed 2026-11-13 16:26:24 +09:00
1 parent 366c8fe173
commit 4964f2ced4
110 files changed
+13960 -295

No files matched your search

+2 -2
View File
@@ -8,8 +8,8 @@
| 파일 | 내용 |
| --- | --- |
| `<이름>.isproj` (`formats.exe`) | `architecture`(x64·x86), `upgradeCode`(생성 시 대문자 `{GUID}`, 모든 버전 공유), `installScope`(`perMachine`만), `installRoot`(`[ProgramFiles64Folder]` 또는 x86의 `[ProgramFilesFolder]` + 안전한 상대 경로), `properties`(사용자 속성 `{name, value}`; 기본 속성은 `package_domain::BUILTIN_PROPERTIES`, 해석·치환은 `parse_formatted`·`expand_formatted`). 최상위 `files`·`registry`는 비어 있어야 한다(`VersionedContent`). 템플릿: [`ExeInstallerProject.isproj`](../../src/fixtures/ExeInstallerProject.isproj) |
| `<이름>.versions/<버전>.isver` (`ExeVersion`) | `version`(Major.Minor.Patch, 파일 이름과 같아야 함), `description`(제작자 메모, 1000자 이하, 없으면 빈 문자열, 설치 화면에 표시 안 함, `DescriptionTooLong`), `productCode`(대문자 `{GUID}`, UpgradeCode와 달라야 함. 메이저 버전마다 새 값, 패치 버전은 라인 메이저 버전과 같은 값), `updateType`(`major` 기본 / `patch`, [15 EXE 버전과 누적 패치](15-exe-versions-and-patches.md)), `locked`(사용자가 잠금·해제), `files`(파일 규칙), `registry`, `shortcuts`(`{id, location, folder, name, target, arguments}`; `target`은 그 버전의 설치 파일 중 하나, `arguments`는 서식 문자열). 스키마: `schemas/exe-version.schema.json`, 예제: [`exe.1.0.0.isver`](examples/exe.1.0.0.isver) |
| `<이름>.isproj` (`formats.exe`) | `architecture`(x64·x86), `upgradeCode`(생성 시 대문자 `{GUID}`, 모든 버전 공유), `installScope`(`perMachine`만), `installRoot`(`[ProgramFiles64Folder]` 또는 x86의 `[ProgramFilesFolder]` + 안전한 상대 경로. 상대 경로에는 `[Manufacturer]`·`[ProductName]`만 쓸 수 있고 실제 값으로 바꾼 뒤 검사한다. 템플릿 기본값은 `[ProgramFiles64Folder][Manufacturer]\[ProductName]`), `properties`(사용자 속성 `{name, value}`; 기본 속성은 `package_domain::BUILTIN_PROPERTIES`, 해석·치환은 `parse_formatted`·`expand_formatted`). 최상위 `files`·`registry`는 비어 있어야 한다(`VersionedContent`). 템플릿: [`ExeInstallerProject.isproj`](../../src/fixtures/ExeInstallerProject.isproj) |
| `<이름>.versions/<버전>.isver` (`ExeVersion`) | `version`(Major.Minor.Patch, 파일 이름과 같아야 함), `description`(제작자 메모, 1000자 이하, 없으면 빈 문자열, 설치 화면에 표시 안 함, `DescriptionTooLong`), `productCode`(대문자 `{GUID}`, UpgradeCode와 달라야 함. 메이저 버전마다 새 값, 패치 버전은 라인 메이저 버전과 같은 값), `updateType`(`major` 기본 / `patch`, [15 EXE 버전과 누적 패치](15-exe-versions-and-patches.md)), `locked`(사용자가 잠금·해제), `files`(파일 규칙), `registry`, `shortcuts`(`{id, location, folder, name, target, arguments}`; `target`은 그 버전의 설치 파일 중 하나, `arguments`는 서식 문자열), `prerequisites`(제품보다 먼저 설치할 프로그램. `{id, name, architecture, delivery, url, file, sha256, bytes, arguments, detect, rebootCodes}`; `delivery`는 `download`(설치 중 다운로드) / `bundled`(설치 파일에 포함), `file`은 소스 alias와 그 안의 경로, 없는 파일은 빈 목록으로 연다. [변경 기록](../changes/2026-11-12-exe-prerequisites.md)). 스키마: `schemas/exe-version.schema.json`, 예제: [`exe.1.0.0.isver`](examples/exe.1.0.0.isver) |
새 EXE 프로젝트는 버전 없이 시작하며, 첫 버전은 사용자가 번호를 지정해 빈 내용으로 만든다. 이후 버전은 선택한 버전을 복사하며, 메이저 버전은 새 ProductCode를 받고 패치 버전은 아래쪽 메이저 버전의 ProductCode를 이어받는다. 검증은 다른 버전과의 관계(`validate_version_line`: ProductCode 재사용, 패치 기준 잠금, 이전 버전 내용 제거·이동 금지)도 검사한다. 저장은 버전 파일마다 읽은 시점의 해시를 비교하고(`RevisionConflict`), 잠긴 버전의 내용 변경(`VersionLocked`)과 패치가 ProductCode를 이어받는 메이저 버전의 삭제(`VersionInUse`)를 거부한다. 화면은 잠긴 버전의 삭제 버튼을 숨기며, 잠금 해제와 삭제를 한 번에 저장하는 것은 허용한다. 바꾼 파일만 `.isver.bak`을 남기고 다시 쓰며, 삭제한 버전 파일은 `.isver.bak`으로 옮긴다. 검증은 공유 설정(`validate`)과 선택한 버전(`validate_version`, 필드 경로 `version.*`)을 함께 검사한다. 이전 단일 버전 EXE 형식(`msiVersion`·`productCode`·`shortcuts`가 `formats.exe`에 있는 파일)은 자동 변환하지 않고 열기를 거부한다. 버전 파일의 `installerUi`(설치 단계·화면 문구·모양·스크립트)는 [14 EXE 설치 UI](14-exe-installer-ui.md#제작기-설치화면-편집-2026-11-09)를 따르며, 없으면 표준 마법사로 연다. 아래 범용 예제의 나머지 EXE 필드(prerequisites, patchPolicy, installationFlow)는 아직 모델에 없으며 알 수 없는 필드로 거부한다.