패키징과 테스트
.mplg 형식
.mplg는 content type application/vnd.morit.plugin+zip인 deterministic ZIP입니다. 최대 2 MiB,
entry 최대 64개이며 다음 안전 검사를 통과해야 합니다.
- 중복 entry 없음
- 절대 경로,
.., 역슬래시, symlink 없음 - 허용된 source·asset·child package만 포함
- compiled manifest가 package 파일과 일치
- 모든 entry digest를 포함한 embedded Ed25519 signature 유효
정상 signature 검증을 제거하거나 ZIP 검사 오류를 숨겨 설치하지 않습니다.
기본 자동 서명
공식 Node CLI build는 publisher별 key를 안전한 로컬 디렉터리에 만들고 자동 서명한 뒤 결과를 다시 검증합니다.
npx -y @morit/cli plugin build . --output ./dist/plugin.mplg
.mplg에는 public key와 signature만 들어갑니다. trusted publisher 등록은 선택 사항이지만 등록된
publisher key가 있으면 embedded key와 일치해야 합니다.
저장소 Python pipeline에서 조직의 고정 key를 사용할 때는 다음과 같습니다.
python tools/morit_plugin.py package . \
--private-key /secure/example.ed25519 \
--output ./dist/plugin.mplg
python tools/morit_plugin.py verify ./dist/plugin.mplg
build --unsigned는 별도 signing pipeline의 중간 파일을 만들 때만 사용합니다. unsigned package는
설치할 수 없으며 사용자에게 최종 .mplg로 제공하지 않습니다.
python tools/morit_plugin.py build . --unsigned --output ./dist/unsigned.mplg
python tools/morit_plugin.py sign ./dist/unsigned.mplg \
--private-key /secure/example.ed25519 \
--output ./dist/plugin.mplg
python tools/morit_plugin.py verify ./dist/plugin.mplg
Source ZIP과 package
Source ZIP은 편집 가능한 전체 프로젝트이고 .mplg는 설치에 필요한 compiled subset입니다.
서로 다른 artifact를 같은 확장자나 MIME으로 제공하지 않습니다.
테스트 층
1. Source 계약
npx -y @morit/cli plugin validate .
Manifest 필드, fragment 병합, 권한 부분집합, capability/runtime, UI tree·binding·route, Credential· Connector, source entrypoint, dependency를 검사합니다.
2. Preview
npx -y @morit/cli plugin preview . --output ./dist/preview.html
python tools/morit_plugin.py preview . --output ./dist/preview.html
정보 구조와 compiled manifest, light/dark partial theme를 점검합니다. Preview는 Flutter Host와 같은 state/binding/compound condition, form validation, autocomplete·searchable select, 순차·병렬 action flow, route parameter/result 규칙을 사용하며 Runtime Inspector로 변경을 확인할 수 있습니다. 실제 인증 Tool·native route stack·플랫폼 IME 동작은 Flutter 앱에서 최종 확인합니다.
3. Package reopen
npx -y @morit/cli plugin build . --output ./dist/plugin.mplg
python tools/morit_plugin.py verify ./dist/plugin.mplg
크기, SHA-256, entry, manifest, publisher, embedded signature를 확인합니다.
4. Backend/API
테스트 계정으로 설치 → 목록 → 활성화 → permission/settings → Connection → capability → 삭제 순서를 실행합니다. 위험한 ZIP, 위조 signature, 등록된 publisher key 불일치, 잘못된 manifest를 각각 차단하고 실패 뒤 부분 DB row와 package file이 남지 않는지 확인합니다.
5. 앱 실사용
- 앱 데이터 삭제 후 첫 설치
- Marketplace 조회·새로고침·재시도
- local file 설치
- 활성화와 권한 허용·거부
- 화면 loading·empty·error·retry
- 한국어 IME 입력 직후 Tool arguments, focus 전환과 controller 동기화
- autocomplete, searchable/async select, form validation, 순차·병렬 action flow
- route parameters·result 반환, permission/connection/platform/screen 복합 조건
- 홈·플러그인 화면·AI Response UI 간 source cache 재사용과 storage mutation 자동 refresh
- A2UI 답변 완료 후 즉시 렌더링, 실패 생략, 로딩 UI 미표시
- 미디어 overlay의 영상·MP3 옵션, 실제 변환·진행률·재시도·모바일 너비
- 시스템/라이트/다크 전환과 기존 theme 없는 package 호환
- Storage CRUD·검색·즉시 UI 갱신, AI read/read_write 권한
- 사용자·Installation·Instance·namespace 격리와 quota/revision/generation 충돌
- Storage migration, reset, purge/retain uninstall/reinstall
- 동일 package 재설치와 version update
- OAuth 여러 Connection과 재연결
- notification 실제 표시
- 삭제와 재설치
6. 회귀 검사
SDK, Python Host, Flutter schema/runtime, Local MCP, Remote MCP, Preview가 같은 contract와 경계를 반환하고 같은 fixture를 허용·거부하는지 확인합니다. capability input/output schema와 UI binding도 모든 validator에서 같이 실패해야 합니다. 문서 예제 JSON도 source 검증 과정에서 실행해 구현과 함께 변경합니다.
실패 시 원칙
validate, build, upload, DB install 단계 중 하나가 실패하면 성공 메시지나 artifact 링크를 반환하지 않습니다. 설치는 임시 package 검증 후 DB와 파일을 commit하고, 중간 실패 시 둘 다 정리합니다. 구체 오류 분류는 오류 해결을 참고하세요.