project format decision

.motion2dproj 保存形式判断メモ

作成日: 2026-05-13

現行実装

現行の .motion2dproj は単一JSONファイルで、正規化済みPNGを data:image/png;base64,... のData URLとして内包する。

保存対象:

  1. schemaVersion: 1
  2. app: "yurari"
  3. 正規化PNG Data URL
  4. パーツ
  5. メッシュ
  6. リグ値とキーフレーム
  7. マウス入力設定
  8. cameraTracking: "not_adopted"

保存しないもの:

  1. カメラ映像
  2. 音声
  3. 顔特徴量
  4. 外部モデル
  5. 絶対パス、OSユーザー名、デバイスID、ログ

初期仕様との差分

初期仕様では .motion2dproj はZIPコンテナで、manifest.jsonassets/source.pngparts/*.jsonmeshes/*.jsonrig/*.jsonsettings.jsonlicenses/THIRD_PARTY_NOTICES.md を含む想定だった。

現行実装は軽量MVPとして、ZIPコンテナではなく単一JSONに集約している。これにより実装と読み書きは単純だが、大きい画像ではJSONが肥大化しやすく、将来の差分保存やアセット分離には向かない。

今回の判断

今回はZIP化せず、スキーマ検証強化を先に実装する。

理由:

  1. 既存 .motion2dproj との後方互換を維持しながら、破損・過大・想定外データを先に安全に拒否できる。
  2. ZIP化にはZip Slip、ZIP爆弾、総展開サイズ、ファイル数、圧縮率、パス正規化、ライセンス同梱のテストが必要で、今回の優先タスクより変更範囲が大きい。
  3. 新規ZIP依存を追加する場合はライセンス、保守状況、CSP影響、バンドルサイズのレビューが必要になる。
  4. Rust側でZIP処理を行う場合はTauri権限とファイルIO境界の設計が必要になる。

実装した検証

src/lib/projectValidation.ts.motion2dproj 読み込み時の検証を追加した。

検証対象:

  1. JSONサイズ上限 75 MB
  2. schemaVersion
  3. app
  4. 画像サイズ、総ピクセル数、PNG Data URL形式、Data URL上限
  5. パーツID、種別、ラベル、点数、座標範囲、重複ID
  6. メッシュ数、頂点数、三角形数、頂点ID、三角形インデックス、パーツ参照整合性
  7. リグ値のパラメータ範囲、キーフレーム、頂点差分参照整合性
  8. 入力設定の範囲
  9. 禁止データを示すキーの拒否

後方互換:

  1. 既存の app: "single-image-motion-mvp" は読み込み時に yurari として正規化する。
  2. 既存プロジェクトに新しい入力設定がない場合は既定値を補う。
  3. JSON + PNG Data URL形式の読み込みは維持する。

ZIP化する場合の設計メモ

v0.2以降でZIP化する場合は、以下を満たすまで実装しない。

  1. 旧JSON形式の読み込み互換を維持する。
  2. 新形式は manifest.json を先に検証してから個別ファイルを読む。
  3. ZIP内パスに絶対パス、..、制御文字、予約デバイス名を許可しない。
  4. 総展開サイズ、個別ファイルサイズ、ファイル数、圧縮率の上限を設ける。
  5. 画像は assets/source.png として保存し、JSONへData URLを入れない。
  6. ZIP処理は可能ならRust側に寄せ、Tauri権限を必要最小限にする。
  7. ZIP化後もカメラ映像、音声、外部モデル、個人情報ログを含めない。
  8. ZIP依存を追加する場合は docs/dependency_review.md にライセンスと採用理由を追記する。