Pemindahan Data - bundel lolly-backup

Segala yang terkumpul oleh pengguna Lolly berada pada peranti mereka - tiada akaun, tiada awan. Bundel pemindahan data adalah cara nilai itu berpindah: eksportkannya pada satu pemasangan, bawa fail itu dengan apa cara sekalipun (USB, AirDrop, e-mel-kepada-diri-sendiri, perkongsian rangkaian) dan import pada yang lain. Fail itu ialah pengangkutan tersebut. Sasaran boleh berada dalam talian atau luar talian. Tiada bezanya, kerana tiada apa pun yang pernah berhubung dengan pelayan.

Dua butang yang memindahkan keseluruhan pemasangan: Export my data menulis satu zip, Import data membacanya semulasigned by Lollyvector SVGSemak sendiriGet the signed file12 paths~5.1k nodes12 groups60 KBDua butang yang memindahkan keseluruhan pemasangan: Export my data menulis satu zip, Import data membacanya semulasigned by Lollyvector SVGSemak sendiriGet the signed file12 paths~5.1k nodes12 groups60 KB

Halaman ini adalah spesifikasi format. Untuk panduan pengguna akhir lihat Using Lolly → Moving to another device. Pelaksanaannya ialah shells/web/src/data-transfer.ts, dan tests/data-transfer.test.ts mengunci kontrak pergi-balik itu.

Skop. Bundel membawa data pengguna, bukan alat. Alat dan aset katalog disegerakkan secara berasingan dan diandaikan sudah wujud pada sasaran (paling teruk pada versi yang lebih tinggi). Import tidak sekali-kali memasang atau menaik taraf sesuatu alat.

Matlamat

Sampul

Bundel adalah .zip biasa. Muat turun itu dinamakan sempena orang yang memilikinya - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip (contohnya LollyTools-Ada-Lovelace-2026-06-26-1.zip) - supaya folder Downloads penuh sandaran kekal mudah difahami. Bahagian nama pertama dan akhir datang daripada profil dan ditinggalkan apabila tidak ditetapkan. Tiada profil menghasilkan LollyTools-2026-06-26-1.zip, dan hanya nama pertama menghasilkan LollyTools-Ada-2026-06-26-1.zip. Setiap bahagian disanitasi kepada token selamat-nama-fail (huruf/angka Unicode dikekalkan, ruang/tanda baca dibuang, dihadkan pada 32 aksara). <n> adalah jujukan per-hari, per-peranti, jadi eksport berulang pada hari yang sama tidak berlanggar dan kekal tersusun. backupFilename() dalam shells/web/src/data-transfer.ts membina nama itu. Kandungan zip itu sama tanpa mengira nama. Di dalamnya:

LaluanDiperlukanKandungan
manifest.jsonyaId format, versi, kiraan dan integriti per-bahagian. Perkara pertama yang dilihat oleh pembaca.
profile.jsonapabila ditetapkanRekod me pengguna (nama, hubungan, rujukan gambar kepala, bendera). Dibaca melalui host.profile.
sessions.jsonyaSetiap sesi tersimpan: slot, id/versi alat, label, lakaran kecil (data-URL) dan data input penuh. Dibaca melalui host.state.
assets.jsonyaMetadata bagi setiap aset yang dimuat naik (imej, fon, token jenama), setiap satu menunjuk kepada baitnya di bawah assets/blobs/.
assets/blobs/<n>.<ext>setiap asetBait aset mentah (fail imej dan fon). Disimpan tanpa mampatan (format yang sudah dimampatkan). Sambungan itu bersifat kosmetik sahaja. MIME dalam assets.json yang muktamad.
prefs.jsonyaKeutamaan tempatan milik pengguna: theme, sidebarWidth dan kiraan aktiviti ct-metrics.
lolly.txtyaRingkasan bundel yang boleh dibaca manusia (kiraan, profil, nama fail) untuk sesiapa yang membuka zip itu tanpa Lolly. Dijana semula pada setiap eksport dan dikenali semasa import, jadi ia tidak sekali-kali dikira sebagai bahagian yang dilangkau. Ia ditulis selepas peta integriti, jadi ia kekal di luar peta itu.

Bundel itu sengaja dijadikan zip biasa: ia bertahan pada mana-mana pengangkutan tanpa rosak, dan mana-mana alat unzip boleh memeriksanya.

profile.json adalah bahagian terkecil dan yang pertama dilihat oleh pembaca dalam aplikasi: butiran yang diisi sekali oleh pengeluar, ditambah opt-in yang membenarkan alat menggunakannya.

Borang butiran Profile yang menjadi profile.json - nama, hubungan, gambar kepala dan opt-in di sebelahnyasigned by Lollyvector SVGSemak sendiriGet the signed file18 paths~2.0k nodes41 groups30 KBBorang butiran Profile yang menjadi profile.json - nama, hubungan, gambar kepala dan opt-in di sebelahnyasigned by Lollyvector SVGSemak sendiriGet 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-…"
  }
}
MedanMaksud
formatSentiasa lolly-backup. Fail tanpanya ditolak sebagai "bukan sandaran Lolly".
formatVersionSusun atur yang ditulis dengan bundel ini. Dinaikkan pada apa-apa perubahan set atau bentuk bahagian. Pembaca tidak menjadikannya syarat pengesahan.
minReaderVersi pembaca minimum yang diperlukan untuk mengimport bundel ini dengan selamat. Inilah medan yang dijadikan syarat oleh pembaca.
appId aplikasi yang menghasilkan, untuk diagnostik.
exportedAtCap masa ISO bila bundel itu dicipta.
countsApa yang dimasukkan oleh penulis, untuk paparan dan semakan kewarasan.
integrityPilihan. Memetakan setiap bahagian kecuali manifest.json kepada digest gaya-SRI sha256-<base64> bagi baitnya yang tidak dimampatkan.

Dasar versi (keserasian ke hadapan)

Pemisahan antara formatVersion dan minReader itulah yang membenarkan format ini berkembang tanpa mengabaikan pemasangan yang lebih lama:

Petua umum untuk pengarang: jika setiap pembaca sedia ada masih akan bertindak dengan betul dengan mengabaikan tambahan anda, ia adalah tambahan - naikkan formatVersion, tinggalkan minReader. Jika tidak, naikkan minReader.

Integriti

Apabila manifest.integrity hadir, pembaca mengesahkan SHA-256 setiap bahagian yang disenaraikan sebelum menulis apa-apa. Ketidakpadanan ("failed its integrity check") atau bahagian yang hilang ("incomplete") membatalkan keseluruhan import - tiada pemulihan separa. Ini menangkap kerosakan yang boleh diakibatkan oleh pengangkutan fail (AirDrop yang terputus, get laluan e-mel yang mengekod semula lampiran, sektor USB yang rosak).

Integriti direka secara usaha-terbaik: ia hanya ditulis di mana Web Crypto tersedia (setiap konteks pelayar selamat dan Node moden), dan hanya disahkan apabila kedua-dua peta dan Web Crypto hadir. Bundel tanpa peta itu - contohnya dari sebelum integriti wujud - diimport tanpa perubahan. "Tidak dapat disahkan" tidak sekali-kali dianggap sebagai "rosak".

Manifes itu tidak menyenaraikan dirinya sendiri mahupun README lolly.txt yang dijana semula. Digest itu meliputi bahagian yang dijamin oleh manifes.

Semantik import

Import adalah gabung-tulis-ganti, tidak sekali-kali ganti-semua:

Sesi tersimpan menyambung semula kepada imejnya secara automatik: rujukan aset dikekalkan mengikut id, dan jambatan itu menyelesaikannya semula selepas imej yang dimuat naik dipulihkan (ia memang mesti berbuat demikian, kerana URL blob: tidak bertahan selepas muat semula halaman).

Ringkasan import melaporkan { profile, sessions, userAssets, prefs, skipped, failedAssets }. failedAssets mengira aset yang dimuat naik yang tidak dapat dipulihkan (storan peranti penuh, contohnya). Ia berbeza daripada skipped, yang mengira bahagian daripada penulis lebih baharu serasi-hadapan yang tidak dikenali oleh binaan ini. UI memaparkan skipped ("… · N newer items skipped"), jadi pemulihan itu jujur tentang apa yang ditinggalkannya.

Apa yang tidak berpindah

Meter storan memerincikan pemisahan yang sama. Sesi tersimpan dan My images dibawa dalam bundel. Cache aset, pratonton alat dan sematan luar talian di bawahnya semuanya boleh diterbitkan semula, jadi ia kekal ditinggalkan.

Meter storan memecahkan data peranti ini kepada kategori bernama, dengan Saved sessions dan My images dijejaki berasingan daripada Asset cache, di sini pada pemasangan baharu di mana setiap kategori masih kosongsigned by Lollyvector SVGSemak sendiriGet the signed file25 paths~4.8k nodes46 groups59 KBMeter storan memecahkan data peranti ini kepada kategori bernama, dengan Saved sessions dan My images dijejaki berasingan daripada Asset cache, di sini pada pemasangan baharu di mana setiap kategori masih kosongsigned by Lollyvector SVGSemak sendiriGet the signed file25 paths~4.8k nodes46 groups59 KB

Jaminan merentas shell

data-transfer.ts membaca dan menulis secara eksklusif melalui capability bridge (host.profile, host.state, host.assets) dan localStorage prefs yang dikongsi. Oleh kerana bridge itu satu-satunya seam, modul yang sama menghasilkan bundle yang serupa bait demi bait pada setiap shell walaupun storan di bawahnya berbeza - IndexedDB pada web, sistem fail pada Tauri. Shell Tauri menggunakan semula modul ini tanpa perubahan. Hanya pelaksanaan host.state mereka yang berbeza. Ujian headless menjalankan round-trip penuh terhadap bridge dalam-memori, itulah sebabnya ia mewakili kesemuanya.

Dua shell berada di luar jaminan itu, atas sebab yang berbeza:

Titik lanjutan terpelihara

Envelope itu direka sebagai manifes ditambah satu set bahagian bernama, supaya jenis data mudah alih yang baharu boleh menumpang kemudian tanpa perubahan yang memecahkan (breaking change). Ia disisipkan sebagai bahagian tambahan (formatVersion baharu, minReader yang sama), dan pembaca hari ini melangkau apa yang tidak dikenalinya. Ini berada pada roadmap, belum lagi dilaksanakan. Nama-namanya diperuntukkan di sini supaya format kekal koheren apabila ia tiba kelak.

Apa-apa di luar nama terpelihara ini dan bahagian di atas adalah, bagi pembaca, bahagian yang tidak diketahui: dibiarkan tanpa disentuh dan dikira dalam skipped.

Rujukan