Dataöverföring - paketet lolly-backup

Allt en Lolly-användare samlar på sig finns på deras enhet - inget konto, inget moln. Dataöverföringspaketet är hur det värdet flyttas: exportera det från en installation, ta med filen på valfritt sätt (USB, AirDrop, e-post till dig själv, en nätverksdelning) och importera den på en annan. Filen är transporten. Målet kan vara offline eller online. Det spelar ingen roll, eftersom inget någonsin pratar med en server.

De två knapparna som flyttar en hel installation: Exportera mina data skriver en zip, Importera data läser in den igensigned by Lollyvector SVGKontrollera självGet the signed file12 paths~5.1k nodes12 groups60 KBDe två knapparna som flyttar en hel installation: Exportera mina data skriver en zip, Importera data läser in den igensigned by Lollyvector SVGKontrollera självGet the signed file12 paths~5.1k nodes12 groups60 KB

Den här sidan är formatspecifikationen. För slutanvändargenomgången, se Använda Lolly → Flytta till en annan enhet. Implementationen är shells/web/src/data-transfer.ts, och tests/data-transfer.test.ts fastställer kontraktet för tur-och-retur.

Omfattning. Ett paket bär användardata, inte verktyg. Verktyg och katalogtillgångar synkas separat och antas redan finnas på målet (i värsta fall i en högre version). Import installerar eller uppgraderar aldrig ett verktyg.

Mål

Kuvertet

Ett paket är en vanlig .zip. Nedladdningen namnges efter personen den tillhör - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip (till exempel LollyTools-Ada-Lovelace-2026-06-26-1.zip) - så att en Downloads-mapp full av säkerhetskopior förblir läsbar. Förnamns- och efternamnsdelarna kommer från profilen och utelämnas om de inte är ifyllda. Ingen profil ger LollyTools-2026-06-26-1.zip, och enbart förnamn ger LollyTools-Ada-2026-06-26-1.zip. Varje del saneras till en filnamnssäker token (Unicode-bokstäver/siffror behålls, mellanslag/skiljetecken tas bort, begränsat till 32 tecken). <n> är en sekvens per dag och enhet, så upprepade exporter samma dag inte krockar och förblir i ordning. backupFilename() i shells/web/src/data-transfer.ts bygger namnet. Zip-innehållet är identiskt oavsett namn. Innehåll:

SökvägKrävsInnehåll
manifest.jsonjaFormat-id, versioner, antal och integritet per del. Det första en läsare tittar på.
profile.jsonnär ifylldAnvändarens me-post (namn, kontaktuppgifter, referens till profilbild, flaggor). Läses via host.profile.
sessions.jsonjaVarje sparad session: plats, verktygs-id/version, etikett, miniatyrbild (data-URL) och all indata. Läses via host.state.
assets.jsonjaMetadata för varje uppladdad tillgång (bilder, typsnitt, varumärkestoken), var och en pekande på sina byte under assets/blobs/.
assets/blobs/<n>.<ext>per tillgångDe råa byten för tillgången (bild- och typsnittsfiler). Lagras okomprimerat (redan komprimerade format). Filändelsen är kosmetisk. MIME-typen i assets.json är auktoritativ.
prefs.jsonjaAnvändarägda lokala inställningar: theme, sidebarWidth och aktivitetsräknaren ct-metrics.
lolly.txtjaEn människoläsbar sammanfattning av paketet (antal, profil, filnamn) för den som öppnar zip:en utan Lolly. Genereras på nytt vid varje export och känns igen vid import, så den räknas aldrig som en överhoppad del. Den skrivs efter integritetskartan, så den ligger utanför den.

Paketet är avsiktligt en vanlig zip: det överlever alla transporter intakt, och vilket uppackningsverktyg som helst kan inspektera det.

profile.json är den minsta delen och den en läsare ser först i appen: uppgifterna som en producent fyller i en gång, plus samtycket som låter verktyg använda dem.

Profilformuläret med detaljer som blir profile.json - namn, kontaktuppgifter, profilbild och samtycket bredvid demsigned by Lollyvector SVGKontrollera självGet the signed file18 paths~2.0k nodes41 groups30 KBProfilformuläret med detaljer som blir profile.json - namn, kontaktuppgifter, profilbild och samtycket bredvid demsigned by Lollyvector SVGKontrollera självGet 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-…"
  }
}
FältBetydelse
formatAlltid lolly-backup. En fil utan det avvisas som "not a Lolly backup".
formatVersionLayouten det här paketet skrevs med. Höjs vid varje ändring av uppsättningen delar eller deras form. Läsare styr inte på den.
minReaderDen lägsta läsarversion som krävs för att importera det här paketet säkert. Det är det här fältet läsare styr på.
appId för den app som skapade paketet, för diagnostik.
exportedAtISO-tidsstämpel för när paketet skapades.
countsVad skribenten lade in, för visning och rimlighetskontroll.
integrityValfritt. Kopplar varje del utom manifest.json till ett SRI-liknande sha256-<base64>-hashvärde för dess okomprimerade byte.

Versionspolicy (framåtkompatibilitet)

Uppdelningen mellan formatVersion och minReader är det som låter formatet växa utan att göra äldre installationer föräldralösa:

Tumregel för upphovspersoner: om varje befintlig läsare fortfarande skulle göra rätt genom att ignorera ditt tillägg, är det additivt - höj formatVersion, lämna minReader. Annars höj minReader.

Integritet

När manifest.integrity finns verifierar en läsare SHA-256 för varje listad del innan något skrivs. En avvikelse ("failed its integrity check") eller en saknad del ("incomplete") avbryter hela importen - det finns ingen delvis återställning. Det här fångar den skada en filtransport kan orsaka (en trunkerad AirDrop, en e-postgateway som kodat om bilagan, en dålig USB-sektor).

Integritet är avsiktligt best-effort: den skrivs bara där Web Crypto finns tillgängligt (varje säker webbläsarkontext och modern Node), och verifieras bara när både kartan och Web Crypto finns. Ett paket utan kartan - till exempel ett från innan integritet fanns - importeras oförändrat. "Cannot verify" behandlas aldrig som "corrupt".

Manifestet listar varken sig självt eller den återgenererade lolly.txt-README:n. Hashvärdena täcker de delar manifestet intygar för.

Importsemantik

Import är sammanfoga-och-skriva-över, aldrig ersätt-allt:

Sparade sessioner länkas automatiskt om till sina bilder: tillgångsreferenser bevaras via id, och bryggan löser upp dem på nytt efter att de uppladdade bilderna återställts (det måste den ändå göra, eftersom blob:-URL:er inte överlever en omladdning).

Importsammanfattningen rapporterar { profile, sessions, userAssets, prefs, skipped, failedAssets }. failedAssets räknar uppladdade tillgångar som inte kunde återställas (till exempel fullt enhetslagringsutrymme). Det skiljer sig från skipped, som räknar delar från en framåtkompatibel nyare skribent som den här versionen inte kände igen. Gränssnittet visar skipped ("… · N newer items skipped"), så återställningen är ärlig om vad den lämnade kvar.

Vad som inte följer med

Lagringsmätaren specificerar samma uppdelning. Saved sessions och My images följer med i ett paket. Tillgångscachen, verktygsförhandsvisningarna och offlinefästningarna under dem kan alla härledas på nytt, så de stannar kvar.

Lagringsmätaren som delar upp den här enhetens data i namngivna kategorier, med Saved sessions och My images spårade separat från Asset cache, här på en ny installation där varje kategori fortfarande är tomsigned by Lollyvector SVGKontrollera självGet the signed file25 paths~4.8k nodes46 groups59 KBLagringsmätaren som delar upp den här enhetens data i namngivna kategorier, med Saved sessions och My images spårade separat från Asset cache, här på en ny installation där varje kategori fortfarande är tomsigned by Lollyvector SVGKontrollera självGet the signed file25 paths~4.8k nodes46 groups59 KB

Garanti mellan skal

data-transfer.ts läser och skriver uteslutande via kapabilitetsbryggan (host.profile, host.state, host.assets) och de delade localStorage-inställningarna. Eftersom bryggan är den enda kontaktpunkten producerar samma modul en byte-identisk bunt på varje skal även om lagringen under skiljer sig - IndexedDB på webben, filsystemet på Tauri. Tauri-skalen återanvänder denna modul oförändrad. Endast deras host.state-implementation skiljer sig. Det huvudlösa testet kör hela tur-och-retur-flödet mot en in-memory-brygga, vilket är varför det får representera alla.

Två skal står utanför den garantin, av olika skäl:

Reserverade utökningspunkter

Kuvertet är ett manifest plus en uppsättning namngivna delar med avsikt, så att nya typer av portabel data kan ansluta senare utan en brytande ändring. De läggs till som additiva delar (ny formatVersion, samma minReader), och dagens läsare hoppar över det den inte känner igen. Dessa finns på färdplanen, ännu inte implementerade. Namnen är reserverade här så att formatet förblir sammanhängande när de väl landar.

Allt utanför dessa reserverade namn och delarna ovan är, för en läsare, en okänd del: lämnas orörd och räknas i skipped.

Referens