データ転送 - lolly-backup バンドル

Lollyユーザーが蓄積するすべてのデータはそのデバイス上にあります - アカウントもクラウドもありません。データ転送バンドルはその価値を移動させる手段です:あるインストールでエクスポートし、任意の方法(USB、AirDrop、自分宛メール、ネットワーク共有)でファイルを運び、別のインストールでインポートします。ファイルそのものが転送手段です。転送先はオフラインでもオンラインでも構いません。サーバーと一切通信しないため、違いはありません。

インストール全体を移動する2つのボタン: Export my dataは1つのzipを書き出し、Import dataはそれを読み込みますsigned by Lollyvector SVG自分で確認するGet the signed file12 paths~5.1k nodes12 groups60 KBインストール全体を移動する2つのボタン: Export my dataは1つのzipを書き出し、Import dataはそれを読み込みますsigned by Lollyvector SVG自分で確認するGet the signed file12 paths~5.1k nodes12 groups60 KB

このページはフォーマット仕様です。エンドユーザー向けの手順はUsing Lolly → Moving to another deviceを参照してください。実装はshells/web/src/data-transfer.tsで、tests/data-transfer.test.tsがラウンドトリップの契約を固定しています。

範囲。 バンドルが運ぶのはユーザーデータであり、ツールではありません。ツールとカタログアセットは別途同期され、転送先にはすでに存在している(最悪の場合はより新しいバージョンで)ことが前提です。インポートがツールをインストールしたりアップグレードしたりすることは決してありません。

目標

エンベロープ

バンドルは通常の .zip です。ダウンロードは所有者にちなんで命名されます - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip(例:LollyTools-Ada-Lovelace-2026-06-26-1.zip)- これによりバックアップが溜まったDownloadsフォルダでも判読しやすくなります。名と姓の部分はプロフィールから取得され、未設定の場合は省略されます。プロフィールがない場合は LollyTools-2026-06-26-1.zip に、名だけの場合は LollyTools-Ada-2026-06-26-1.zip になります。各部分はファイル名に安全なトークンにサニタイズされます(Unicodeの文字・数字は保持し、スペース・句読点は除去、最大32文字)。<n> は日単位・デバイス単位の連番なので、同じ日に複数回エクスポートしても衝突せず順序が保たれます。名前の生成はshells/web/src/data-transfer.tsbackupFilename() が行います。zipの中身は名前に関わらず同一です。内訳:

パス必須内容
manifest.jsonはいフォーマットid、バージョン、件数、パートごとの整合性情報。リーダーが最初に確認する項目。
profile.json設定時のみユーザーの me レコード(氏名、連絡先、顔写真の参照、フラグ)。host.profile 経由で読み取られる。
sessions.jsonはい保存済みのすべてのセッション:スロット、ツールid/バージョン、ラベル、サムネイル(data-URL)、完全な入力データ。host.state 経由で読み取られる。
assets.jsonはいアップロードされた各アセット(画像、フォント、ブランドトークン)のメタデータ。それぞれ assets/blobs/ 以下の実バイトを指している。
assets/blobs/<n>.<ext>アセットごとアセットの生バイト(画像・フォントファイル)。無圧縮で保存(すでに圧縮済みのフォーマットのため)。拡張子は表示上のもの。正式なMIMEは assets.json 側が権威を持つ。
prefs.jsonはいユーザー所有のローカル環境設定: themesidebarWidthct-metrics のアクティビティ集計。
lolly.txtはいLollyを使わずzipを開いた人向けに、バンドルの内容(件数、プロフィール、ファイル名)を人間可読な形でまとめたもの。エクスポートのたびに再生成され、インポート時には認識されるため、スキップされたパートとしてカウントされることはない。整合性マップの後に書き込まれるため、その対象外となる。

バンドルはあえて通常のzipにしてあります。どんな転送手段でも無傷で残り、どの解凍ツールでも中身を確認できます。

profile.json は最小のパートであり、アプリ内でリーダーが最初に目にするものでもあります。作成者が一度だけ入力する詳細情報と、それをツールが利用できるようにするオプトインです。

profile.jsonのもとになるProfile詳細フォーム - 氏名、連絡先、顔写真、そして横にあるオプトインsigned by Lollyvector SVG自分で確認するGet the signed file18 paths~2.0k nodes41 groups30 KBprofile.jsonのもとになるProfile詳細フォーム - 氏名、連絡先、顔写真、そして横にあるオプトインsigned by Lollyvector SVG自分で確認するGet the signed file18 paths~2.0k nodes41 groups30 KB

manifest.json

{
  "format": "lolly-backup",
  "formatVersion": 1,
  "minReader": 1,
  "app": "lolly",
  "exportedAt": "2026-06-22T09:30:00.000Z",
  "counts": { "profile": true, "sessions": 2, "userAssets": 4, "prefs": 3 },
  "integrity": {
    "profile.json": "sha256-…",
    "sessions.json": "sha256-…",
    "assets.json": "sha256-…",
    "assets/blobs/0.webp": "sha256-…",
    "prefs.json": "sha256-…"
  }
}
フィールド意味
format常に lolly-backup。これがないファイルは「not a Lolly backup」として拒否される。
formatVersionこのバンドルが書き込まれた際のレイアウト。パート構成や形状の変更のたびに繰り上がる。リーダーはこれをゲート条件にはしない
minReaderこのバンドルを安全にインポートするために必要な最小のリーダーバージョン。リーダーがゲート条件とするのはこのフィールド。
app診断用の、生成したアプリのid。
exportedAtバンドルが作成されたISOタイムスタンプ。
counts書き込み側が入れた内容(表示と整合性チェック用)。
integrity任意。manifest.json を除くすべてのパートを、その無圧縮バイトのSRI形式 sha256-<base64> ダイジェストに対応付ける。

バージョンポリシー(前方互換性)

formatVersionminReader を分けていることが、古いインストールを取り残すことなくフォーマットを進化させられる理由です。

作成者向けの経験則: 既存のすべてのリーダーが、あなたの追加を無視しても正しく動作し続けるなら、それは加算的な変更です - formatVersion を繰り上げ、minReader はそのままにします。そうでなければ minReader を引き上げてください。

整合性

manifest.integrity が存在する場合、リーダーは何かを書き込む前に、記載された各パートのSHA-256を検証します。不一致(「failed its integrity check」)や欠落パート(「incomplete」)が見つかると、インポート全体が中止されます - 部分的な復元は行われません。これにより、ファイル転送によって生じうる破損(途切れたAirDrop、添付ファイルを再エンコードするメールゲートウェイ、不良なUSBセクタなど)を検出できます。

整合性チェックは設計上ベストエフォートです。書き込まれるのはWeb Cryptoが利用可能な環境(すべてのセキュアなブラウザコンテキストと最近のNode)のみで、検証されるのはマップとWeb Cryptoの両方が揃っている場合のみです。マップを持たないバンドル - 例えば整合性機能が存在する前に作られたもの - は、そのままインポートされます。「検証できない」ことが「破損している」と扱われることは決してありません。

マニフェストは、自分自身も再生成された lolly.txt READMEも一覧に含めません。ダイジェストが対象とするのは、マニフェストが保証するパートのみです。

インポートのセマンティクス

インポートはマージ・上書きであり、全置換になることは決してありません。

保存済みセッションは画像に自動的に再リンクされます:アセット参照はidで保持され、アップロード画像が復元された後にブリッジがそれらを再解決します(blob: URLはリロードを跨いで残らないため、いずれにせよ必要な処理です)。

インポートのサマリーは { profile, sessions, userAssets, prefs, skipped, failedAssets } を報告します。failedAssets は復元できなかったアップロード済みアセットの数です(例えばデバイスのストレージが満杯の場合など)。これは skipped とは別物で、skipped は前方互換な新しいライターに由来し、このビルドが認識しなかったパートの数を表します。UIは skipped を表示するため(「… · N newer items skipped」)、復元がどこを取りこぼしたかについて正直です。

転送されないもの

ストレージメーターも同じ区分けを項目別に示しています。保存済みセッションとMy imagesはバンドルに含まれます。その下にあるアセットキャッシュ、ツールプレビュー、オフラインピンはすべて再導出可能なため、残されます。

このデバイスのデータを名前付きカテゴリーに分解して表示するストレージメーター。Saved sessionsとMy imagesはAsset cacheとは別に集計されている。ここではまだすべてのカテゴリーが空の新規インストール状態signed by Lollyvector SVG自分で確認するGet the signed file25 paths~4.8k nodes46 groups59 KBこのデバイスのデータを名前付きカテゴリーに分解して表示するストレージメーター。Saved sessionsとMy imagesはAsset cacheとは別に集計されている。ここではまだすべてのカテゴリーが空の新規インストール状態signed by Lollyvector SVG自分で確認するGet the signed file25 paths~4.8k nodes46 groups59 KB

クロスシェルの保証

data-transfer.ts はケイパビリティブリッジ(host.profilehost.statehost.assets)と共有の localStorage prefs だけを通じて読み書きします。ブリッジが唯一の接点であるため、下層のストレージがシェルごとに異なっていても - web では IndexedDB、Tauri ではファイルシステム - 同じモジュールがどのシェルでもバイト単位で同一のバンドルを生成します。Tauri シェルはこのモジュールをそのまま再利用しており、異なるのは host.state の実装だけです。ヘッドレステストはインメモリのブリッジに対してラウンドトリップ全体を検証しており、そのためこのテストがすべてのシェルの代表となります。

この保証の外にあるシェルが2つあり、それぞれ理由が異なります。

予約された拡張ポイント

エンベロープはマニフェストと名前付きパーツの集合として設計されているため、新しい種類の移植可能なデータを破壊的変更なしに後から乗せられます。それらは追加的なパーツとして組み込まれ(新しい formatVersion、同じ minReader)、現在のリーダーは認識しないものをスキップします。これらはロードマップにあるもので、まだ実装されていません。将来これらが導入されたときにフォーマットの一貫性を保つため、名前だけをここで予約しています。

これらの予約名と上記のパーツ以外のものは、リーダーから見ると未知のパーツです。手を加えられずに残り、skipped にカウントされます。

リファレンス