Přenos dat - balíček lolly-backup

Vše, co uživatel Lolly nashromáždí, žije na jeho zařízení - žádný účet, žádný cloud. Balíček pro přenos dat je způsob, jak se tato hodnota přesouvá: exportuj ho na jedné instalaci, přenes soubor jakýmkoli způsobem (USB, AirDrop, e-mail sám sobě, síťové sdílení) a naimportuj ho na jiné. Soubor je přenos. Cíl může být offline nebo online. Nehraje to roli, protože nic nikdy nekomunikuje se serverem.

Dvě tlačítka, která přesunou celou instalaci: Exportovat má data zapíše jeden zip, Importovat data ho zase načtesigned by Lollyvector SVGOvěř si to sámGet the signed file12 paths~5.1k nodes12 groups60 KBDvě tlačítka, která přesunou celou instalaci: Exportovat má data zapíše jeden zip, Importovat data ho zase načtesigned by Lollyvector SVGOvěř si to sámGet the signed file12 paths~5.1k nodes12 groups60 KB

Tato stránka je specifikace formátu. Návod pro koncového uživatele najdeš v Používání Lolly → Přechod na jiné zařízení. Implementace je shells/web/src/data-transfer.ts a tests/data-transfer.test.ts fixuje kontrakt zpětné kompatibility (round-trip).

Rozsah. Balíček nese uživatelská data, ne nástroje. Nástroje a assety z katalogu se synchronizují zvlášť a předpokládá se, že na cílovém zařízení už jsou (v nejhorším případě ve vyšší verzi). Import nikdy nenainstaluje ani neaktualizuje nástroj.

Cíle

Obálka

Balíček je obyčejný .zip. Stažený soubor je pojmenovaný podle osoby, které patří - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip (například LollyTools-Ada-Lovelace-2026-06-26-1.zip) - takže složka se zálohami ve Stažených souborech zůstává přehledná. Části se jménem a příjmením pocházejí z profilu a při jejich absenci se vynechají. Bez profilu vznikne LollyTools-2026-06-26-1.zip a jen s křestním jménem LollyTools-Ada-2026-06-26-1.zip. Každá část se převede na token bezpečný pro název souboru (zachovají se unicode písmena a číslice, mezery a interpunkce se odstraní, maximálně 32 znaků). <n> je pořadové číslo pro daný den a dané zařízení, takže se opakované exporty ve stejný den nepřekrývají a zůstávají seřazené. Název sestavuje backupFilename() v shells/web/src/data-transfer.ts. Obsah zipu je stejný bez ohledu na název. Uvnitř:

CestaPovinnéObsah
manifest.jsonanoID formátu, verze, počty a integrita jednotlivých částí. To první, na co se čtenář podívá.
profile.jsonpokud je nastavenoUživatelův záznam me (jméno, kontakt, odkaz na fotografii, příznaky). Čte se přes host.profile.
sessions.jsonanoKaždá uložená relace: slot, ID/verze nástroje, štítek, náhled (data-URL) a kompletní vstupní data. Čte se přes host.state.
assets.jsonanoMetadata pro každý nahraný asset (obrázky, fonty, brand tokeny), každé odkazuje na svá data v assets/blobs/.
assets/blobs/<n>.<ext>u každého assetuSurová data assetu (obrázkové a fontové soubory). Uloženo nekomprimovaně (formáty jsou už zkomprimované). Přípona je jen kosmetická. Rozhodující je MIME v assets.json.
prefs.jsonanoLokální preference vlastněné uživatelem: theme, sidebarWidth a počítadlo aktivity ct-metrics.
lolly.txtanoČitelné shrnutí balíčku (počty, profil, název souboru) pro každého, kdo zip otevře bez Lolly. Znovu se generuje při každém exportu a při importu je rozpoznán, takže se nikdy nepočítá jako přeskočená část. Zapisuje se po mapě integrity, takže do ní není zahrnut.

Balíček je záměrně obyčejný zip: přežije jakýkoli přenos neporušený a prohlédnout si ho umí libovolný nástroj na rozbalování.

profile.json je nejmenší část a ta, kterou uživatel v aplikaci vidí jako první: údaje, které producent vyplní jednou, plus opt-in, který nástrojům dovolí je použít.

Formulář Profile details, ze kterého vznikne profile.json - jméno, kontakt, fotografie a opt-in vedle nichsigned by Lollyvector SVGOvěř si to sámGet the signed file18 paths~2.0k nodes41 groups30 KBFormulář Profile details, ze kterého vznikne profile.json - jméno, kontakt, fotografie a opt-in vedle nichsigned by Lollyvector SVGOvěř si to sámGet 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-…"
  }
}
PoleVýznam
formatVždy lolly-backup. Soubor bez něj je odmítnut jako "not a Lolly backup".
formatVersionRozvržení, se kterým byl balíček zapsán. Zvyšuje se při jakékoli změně sady nebo tvaru částí. Čtenáři se podle něj neřídí.
minReaderMinimální verze čtenáře potřebná k bezpečnému importu tohoto balíčku. Podle tohoto pole se čtenáři řídí.
appID produkující aplikace, pro diagnostiku.
exportedAtISO časové razítko vytvoření balíčku.
countsCo do něj zapisovatel vložil, pro zobrazení a kontrolu smysluplnosti.
integrityVolitelné. Mapuje každou část kromě manifest.json na digest ve stylu SRI sha256-<base64> jejích nekomprimovaných bajtů.

Zásady verzování (zpětná kompatibilita)

Rozdělení mezi formatVersion a minReader umožňuje, aby formát rostl, aniž by osiřely starší instalace:

Pravidlo pro autory: pokud by každý existující čtenář udělal správnou věc i tak, že tvůj přírůstek ignoruje, jde o aditivní změnu - zvyš formatVersion, minReader nech beze změny. Jinak zvyš minReader.

Integrita

Když je přítomné manifest.integrity, čtenář ověří SHA-256 každé uvedené části před tím, než cokoli zapíše. Neshoda ("failed its integrity check") nebo chybějící část ("incomplete") přeruší celý import - žádné částečné obnovení neexistuje. Tím se zachytí poškození, které může způsobit přenos souboru (zkrácený AirDrop, e-mailová brána, která přílohu překódovala, špatný sektor na USB).

Integrita je záměrně best-effort: zapisuje se jen tam, kde je dostupné Web Crypto (každý zabezpečený kontext prohlížeče a moderní Node), a ověřuje se jen tehdy, když jsou přítomné mapa i Web Crypto zároveň. Balíček bez mapy - třeba starší, z doby před integritou - se importuje beze změny. "Nelze ověřit" se nikdy nebere jako "poškozeno".

Manifest neuvádí ani sám sebe, ani znovu generovaný soubor lolly.txt README. Digesty pokrývají části, za které manifest ručí.

Sémantika importu

Import je sloučení s přepisem, nikdy nahrazení všeho:

Uložené relace se ke svým obrázkům automaticky znovu propojí: reference na assety se udržují podle ID a bridge je znovu přeloží poté, co jsou nahrané obrázky obnovené (musí tak jako tak, protože URL blob: nepřežijí obnovení stránky).

Souhrn importu hlásí { profile, sessions, userAssets, prefs, skipped, failedAssets }. failedAssets počítá nahrané assety, které se nepodařilo obnovit (například plné úložiště zařízení). To je odlišné od skipped, které počítá části od dopředu kompatibilního novějšího zapisovatele, jež tato verze nerozpoznala. UI zobrazuje skipped ("… · N novějších položek přeskočeno"), takže obnova je poctivá v tom, co nechala stranou.

Co necestuje

Ukazatel úložiště zobrazuje stejné rozdělení. Uložené relace a Moje obrázky jedou v balíčku. Cache assetů, náhledy nástrojů a offline piny pod nimi jsou vždy odvoditelné znovu, takže zůstávají mimo.

Ukazatel úložiště rozdělující data tohoto zařízení do pojmenovaných kategorií, kde jsou Uložené relace a Moje obrázky sledovány odděleně od Cache assetů, zde na čerstvé instalaci, kde je zatím každá kategorie prázdnásigned by Lollyvector SVGOvěř si to sámGet the signed file25 paths~4.8k nodes46 groups59 KBUkazatel úložiště rozdělující data tohoto zařízení do pojmenovaných kategorií, kde jsou Uložené relace a Moje obrázky sledovány odděleně od Cache assetů, zde na čerstvé instalaci, kde je zatím každá kategorie prázdnásigned by Lollyvector SVGOvěř si to sámGet the signed file25 paths~4.8k nodes46 groups59 KB

Záruka napříč shelly

data-transfer.ts čte a zapisuje výhradně přes bridge schopností (host.profile, host.state, host.assets) a sdílené preference v localStorage. Protože bridge je jediný styk, stejný modul produkuje bajtově identický balíček na každém shellu, i když se úložiště pod ním liší - IndexedDB na webu, souborový systém v Tauri. Tauri shelly tento modul používají beze změny. Liší se jen jejich implementace host.state. Headless test prochází celou zpětnou kompatibilitu (round-trip) proti in-memory bridge, a proto zastupuje všechny ostatní.

Mimo tuto záruku stojí dva shelly, z různých důvodů:

Rezervované body pro rozšíření

Obálka je záměrně navržena jako manifest plus sada pojmenovaných částí, aby na ní později mohly jet nové druhy přenosných dat bez nekompatibilní změny. Zapadnou jako aditivní části (nový formatVersion, stejný minReader) a dnešní čtenář to, co nerozpozná, přeskočí. Tyto věci jsou na roadmapě, zatím nejsou implementované. Jejich názvy jsou zde rezervované, aby formát zůstal koherentní, až přistanou.

Cokoli mimo tyto rezervované názvy a výše uvedené části je pro čtenáře neznámá část: ponechá se nedotčená a započítá se do skipped.

Reference