Lolly
Spustit aplikaci

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 moje data zapíše jeden zip, Import data ho zase načte signed by Lollyvector SVG9 paths~4.9k nodes11 groups56 KBOvěř si to sámStáhni podepsaný souborDvě tlačítka, která přesunou celou instalaci: Exportovat moje data zapíše jeden zip, Import data ho zase načte signed by Lollyvector SVG9 paths~4.9k nodes11 groups56 KBOvěř si to sámStáhni podepsaný soubor

Tato stránka je specifikace formátu. Návod pro koncového uživatele najdeš v Najdi a obnov svou práci → Přenes svou práci do jiného 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 z katalogu. 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); nástroje, které si uživatel vytvořil sám, cestují uvnitř profile.json. Import nikdy nenainstaluje ani neaktualizuje nástroj z katalogu.

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 nastavenoCelý uživatelův záznam me: jméno, kontakt, odkaz na fotografii a příznaky, plus složky, Koš, návrhy projektů, uživatelské šablony a uživatelem vytvořené nástroje, oblíbené, skryté nástroje, volba jazyka a emoji. Č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, loga, uložené kopie stažení), 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.
assets/blobs/<n>.c2papokud je přítomnéExtrahované Content Credentials jako přesné binární bajty, na které odkazuje _credentialFile v záznamu assetu. Nejde o podepisovací klíče zařízení.
design-systems.jsonpokud je přítomnéDesign systémy vytvořené nebo přidané na této instalaci, jako { active, records }. Při importu se sloučí podle ID; aktivní volba balíčku se použije, jen když cíl nemá vlastní design systém.
file-history.jsonvolitelnéVerzované snímky assetů, hlášení terminálových souborových operací a kompletní dávkové manifesty. Část historie má vlastní verzi; poskytuje ji interní záložní adaptér fileHistory daného shellu.
revision-history.jsonvolitelné, ruční zálohyStabilní ID výtvorů, zachované checkpointy, náhledy a průběžné návrhy pro obnovu. Poskytuje host.state.history.backup tam, kde je podporováno.
file-history/versions/u každého snímkuPředchozí data assetu a extrahované credentials, bez ohledu na to, jestli aktuální asset ještě existuje.
file-history/results/u každé dokončené operacePřesná výstupní data. Žádný originální soubor vybraný ke konverzi se neuchovává ani nezahrnuje.
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ář s podrobnostmi profilu, který se stává souborem profile.json: jméno, kontaktní údaje a profilová fotka signed by Lollyvector SVG15 paths~1.2k nodes30 groups1 image40 KBOvěř si to sámStáhni podepsaný soubor

manifest.json

{
  "format": "lolly-backup",
  "formatVersion": 3,
  "minReader": 1,
  "app": "lolly",
  "exportedAt": "2026-06-22T09:30:00.000Z",
  "counts": { "profile": true, "sessions": 2, "userAssets": 4, "prefs": 3, "assetVersions": 1, "fileOperations": 1 },
  "integrity": {
    "profile.json": "sha256-…",
    "sessions.json": "sha256-…",
    "assets.json": "sha256-…",
    "assets/blobs/0.bin": "sha256-…",
    "file-history.json": "sha256-…",
    "file-history/versions/0.bin": "sha256-…",
    "file-history/results/0.bin": "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í, 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.

Když je přítomná historie souborů, souhrn nese navíc assetVersions, fileOperations a failedHistory. Vyčerpání úložiště nebo konflikty neměnných ID mohou způsobit částečnou obnovu; UI řekne uživateli, aby si ponechal zdrojovou zálohu. Cloudová synchronizace neposune svou aplikovanou revizi po částečné nebo nepodporované obnově, takže snímek zůstává dostupný pro opakovaný pokus. Obnova není jedna transakce napříč všemi úložišti profilu/relace/assetu/historie.

Historie výtvorů (v3)

Ruční zálohy z webového hostitele schopného historie obsahují revision-history.json s vlastním schématem { version: 1, documents, revisions, recoveries }. Nese zachovaná ID, kanonické snímky vstupů, verzová razítka, rastrové náhledy a samostatné návrhy editoru. Adaptér historie zachytí aktuální relace a jejich hlavy v jedné čtecí transakci; sessions.json používá stejné aktuální snímky pro starší čtenáře.

Obnova před potvrzením archivu v jedné transakci kontroluje SHA-256 a počty bajtů payloadu, unikátní identity, vztahy dokument/hlava, původ, časová razítka, typy náhledů a limity. Zkompaktované odkazy na rodiče mohou chybět. Existující aktuální práce se nikdy tiše nenahradí: když je výtvor na obou stranách, strana, která se nezachová jako aktuální, se stane chráněným návrhem. Limit přenosu archivu 384 MiB se kontroluje explicitně a limity úložiště se vynucují bez zkracování zachovaných checkpointů. Celá záloha stále používá in-memory implementaci ZIP a není to streamovaný archiv.

Souhrn přidává revisions a recoveryDrafts, které počítají jen to, co tento import přidal, a added, kept, replaced, copies a hidden pro to, jak se každý výtvor sloučil. Shell bez této schopnosti obnoví běžné relace a část historie nahlásí jako přeskočenou. Historie nativního souborového systému zůstává nepodporovaná, dokud její adaptér nedodá trvalé transakce historie. Stav P2P hosta nemá trvalou historii ani archiv pro obnovu.

Osobní synchronizace snímků výslovně vylučuje historii výtvorů. Aplikace snímku na lokální dokument nesoucí historii zachová jeho předchozí pracovní stav jako samostatný návrh pro obnovu a zneplatní zapisovací token každého otevřeného editoru. Jeho neměnné checkpointy zůstávají na zařízení. Tohle chrání lokální historii během nahrazení snímkem; neslučuje souběžné historie z různých zařízení.

Historické reference na assety se zachovávají, zatímco vykreslování pořád řeší assety přes existující knihovnu cíle. Tenhle archiv zatím nezaručuje přesná stará data assetu ani staré rendery nástroje. Data verze assetu a výsledku souboru nadále cestují přes svou existující samostatnou část zálohy.

Uložené verze a výsledky souborů (v2)

Volitelná část historie obsahuje { version: 2, assetVersions: [...], operations: [...], batches: [...] }; čtenáři akceptují i starší tvar history-v1 bez batchů. Každý snímek identifikuje stabilní ID assetu a přesnou verzi, čas uložení, délku v bajtech a hex SHA-256, plus záznam assetu, jehož _file a volitelný _credentialFile ukazují na binární části. Operace nesou původní fakta o souboru, požadavek, hlášení, časová razítka a volitelný výsledek _file; názvy úložných backendů, OPFS handly a exekuční leasy necestují. Starší čtenáři jen s history-v1 odmítnou novou verzi historie ještě před importem, místo aby tiše zahodili členství v batchi.

Dávkové manifesty zaznamenávají každý vybraný zdroj před zpracováním, včetně souborů nikdy nepřečtených, zrušených členů, selhání rezervace místa pro výsledek a přerušené práce. Každý člen má stabilní ID operace, referenci/fakta zdroje, požadovaný název výstupu a terminálové hlášení. Nepřečtený zdroj má deklarovaná fakta, ne vymyšlený digest. Import validuje identitu člena a konzistenci s neseným hlášením operace. Dávková hlášení zůstávají dostupná, i když byly jednotlivé výsledky výslovně odstraněny, ale potvrzenka neznamená, že jeho výstupní data jsou stále uložená.

Starší čtenáři pořád akceptují obálku v2 (minReader: 1) a obnoví známé části, přičemž nepodporované části historie počítají jako přeskočené. Plná obnova historie vyžaduje shell s adaptérem fileHistory; je to interní šev shellu, ne nová schopnost HostV1 viditelná pro nástroje. Skutečnou obnovu mezi dvěma zařízeními pokrývá lokální Chromium gate; akceptace obnovy na nainstalovaném Tauri/iOS/Androidu zůstává samostatná.

Co necestuje

Ukazatel úložiště zobrazuje stejné rozdělení. Uložené relace, Moje obrázky a Výsledky a verze souborů 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 SVG37 paths~4.9k nodes85 groups65 KBOvěř si to sámStáhni podepsaný souborUkazatel ú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 SVG37 paths~4.9k nodes85 groups65 KBOvěř si to sámStáhni podepsaný soubor

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. Stejný modul čte a zapisuje společnou obálku na webu i v Tauri, přes IndexedDB nebo souborové úložiště. Volitelné části historie se objeví jen tam, kde je dostupný odpovídající adaptér; nepodporovaná část se při importu nahlásí jako přeskočená. Headless sada zkouší společné části proti in-memory bridge, zatímco transakce historie mají i testy ve skutečném prohlížeči.

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čí. Zatím nejsou postavené. 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