Trasferimento dati - il bundle lolly-backup

Tutto ciò che un utente Lolly accumula vive sul suo dispositivo - nessun account, nessun cloud. Il bundle di trasferimento dati è come quel valore si sposta: esportalo su un'installazione, porta il file con qualsiasi mezzo (USB, AirDrop, email a te stesso, una condivisione di rete) e importalo su un'altra. Il file è il trasporto. La destinazione può essere offline o online. Non fa differenza, perché nulla parla mai con un server.

I due pulsanti che spostano un'intera installazione: Esporta i miei dati scrive uno zip, Importa dati lo rileggesigned by Lollyvector SVGVerifica tu stessoGet the signed file12 paths~5.1k nodes12 groups60 KBI due pulsanti che spostano un'intera installazione: Esporta i miei dati scrive uno zip, Importa dati lo rileggesigned by Lollyvector SVGVerifica tu stessoGet the signed file12 paths~5.1k nodes12 groups60 KB

Questa pagina è la specifica del formato. Per la guida passo passo pensata per l'utente finale vedi Usare Lolly → Passare a un altro dispositivo. L'implementazione è in shells/web/src/data-transfer.ts, e tests/data-transfer.test.ts fissa il contratto di andata e ritorno.

Ambito. Un bundle trasporta dati utente, non strumenti. Strumenti e asset di catalogo sono sincronizzati separatamente e si presume siano già presenti sulla destinazione (nel peggiore dei casi in una versione più recente). L'importazione non installa né aggiorna mai uno strumento.

Obiettivi

La busta

Un bundle è un semplice .zip. Il download prende il nome della persona a cui appartiene - LollyTools-<First>-<Last>-<YYYY-MM-DD>-<n>.zip (ad esempio LollyTools-Ada-Lovelace-2026-06-26-1.zip) - così una cartella Download piena di backup resta leggibile. Le parti nome e cognome provengono dal profilo e vengono omesse se non impostate. Senza profilo si ottiene LollyTools-2026-06-26-1.zip, e con il solo nome si ottiene LollyTools-Ada-2026-06-26-1.zip. Ogni parte viene sanificata in un token sicuro per i nomi file (lettere/cifre Unicode mantenute, spazi/punteggiatura rimossi, limite di 32 caratteri). <n> è una sequenza giornaliera per dispositivo, così esportazioni ripetute nello stesso giorno non collidono e restano in ordine. backupFilename() in shells/web/src/data-transfer.ts costruisce il nome. Il contenuto dello zip è identico indipendentemente dal nome. All'interno:

PercorsoObbligatorioContenuto
manifest.jsonId del formato, versioni, conteggi e integrità per parte. La prima cosa che un lettore controlla.
profile.jsonquando impostatoIl record me dell'utente (nome, contatto, riferimento alla foto, flag). Letto tramite host.profile.
sessions.jsonOgni sessione salvata: slot, id/versione dello strumento, etichetta, miniatura (data-URL) e dati di input completi. Letto tramite host.state.
assets.jsonMetadati per ogni asset caricato (immagini, font, token di brand), ciascuno che punta ai suoi byte sotto assets/blobs/.
assets/blobs/<n>.<ext>per assetI byte grezzi dell'asset (file immagine e font). Memorizzati non compressi (formati già compressi). L'estensione è cosmetica. Il MIME in assets.json è quello autorevole.
prefs.jsonPreferenze locali di proprietà dell'utente: theme, sidebarWidth e il conteggio attività ct-metrics.
lolly.txtUn riepilogo leggibile del bundle (conteggi, profilo, nome file) per chiunque apra lo zip senza Lolly. Rigenerato a ogni esportazione e riconosciuto all'importazione, quindi non conta mai come parte saltata. È scritto dopo la mappa di integrità, quindi ne resta fuori.

Il bundle è di proposito un semplice zip: sopravvive intatto a qualsiasi trasporto, e qualsiasi strumento di estrazione può ispezionarlo.

profile.json è la parte più piccola e la prima che un lettore vede nell'app: i dati che un produttore compila una volta, più l'opt-in che permette agli strumenti di usarli.

Il modulo dei dettagli del profilo che diventa profile.json - nome, contatto, foto e l'opt-in accantosigned by Lollyvector SVGVerifica tu stessoGet the signed file18 paths~2.0k nodes41 groups30 KBIl modulo dei dettagli del profilo che diventa profile.json - nome, contatto, foto e l'opt-in accantosigned by Lollyvector SVGVerifica tu stessoGet 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-…"
  }
}
CampoSignificato
formatSempre lolly-backup. Un file senza questo campo viene rifiutato come "non un backup Lolly".
formatVersionIl layout con cui questo bundle è stato scritto. Incrementato a ogni modifica dell'insieme o della forma delle parti. I lettori non si basano su questo campo.
minReaderLa versione minima del lettore richiesta per importare questo bundle in sicurezza. È il campo su cui i lettori si basano.
appId dell'app che ha prodotto il bundle, per la diagnostica.
exportedAtTimestamp ISO di creazione del bundle.
countsCosa lo scrittore ha inserito, per la visualizzazione e il controllo di coerenza.
integrityOpzionale. Mappa ogni parte tranne manifest.json a un digest in stile SRI sha256-<base64> dei suoi byte non compressi.

Politica di versione (compatibilità in avanti)

La separazione tra formatVersion e minReader è ciò che permette al formato di crescere senza abbandonare le installazioni più vecchie:

Regola pratica per gli autori: se ogni lettore esistente si comporterebbe comunque correttamente ignorando la tua aggiunta, è additiva - incrementa formatVersion, lascia minReader. Altrimenti alza minReader.

Integrità

Quando manifest.integrity è presente, un lettore verifica lo SHA-256 di ogni parte elencata prima di scrivere qualsiasi cosa. Una mancata corrispondenza ("non ha superato il controllo di integrità") o una parte mancante ("incompleto") interrompe l'intera importazione - non esiste un ripristino parziale. Questo intercetta la corruzione che un trasporto di file può introdurre (un AirDrop troncato, un gateway email che ha ricodificato l'allegato, un settore USB difettoso).

L'integrità è best-effort per progettazione: viene scritta solo dove Web Crypto è disponibile (ogni contesto browser sicuro e Node moderno), e verificata solo quando sia la mappa sia Web Crypto sono presenti. Un bundle senza la mappa - per esempio uno precedente all'esistenza dell'integrità - viene importato senza modifiche. "Impossibile verificare" non viene mai trattato come "corrotto".

Il manifest non elenca né se stesso né il README lolly.txt rigenerato. I digest coprono le parti di cui il manifest si fa garante.

Semantica di importazione

L'importazione è unione con sovrascrittura, mai sostituzione totale:

Le sessioni salvate si ricollegano automaticamente alle proprie immagini: i riferimenti agli asset sono mantenuti tramite id, e il bridge li ririsolve dopo che le immagini caricate sono state ripristinate (deve farlo comunque, perché gli URL blob: non sopravvivono a un ricaricamento).

Il riepilogo dell'importazione riporta { profile, sessions, userAssets, prefs, skipped, failedAssets }. failedAssets conta gli asset caricati che non è stato possibile ripristinare (per esempio archiviazione del dispositivo piena). È distinto da skipped, che conta le parti provenienti da uno scrittore più recente e compatibile in avanti che questa build non ha riconosciuto. L'interfaccia mostra skipped ("… · N elementi più recenti saltati"), così il ripristino è onesto su cosa ha lasciato indietro.

Cosa non viaggia

Il misuratore di archiviazione elenca la stessa suddivisione. Le sessioni salvate e Le mie immagini viaggiano in un bundle. La cache degli asset, le anteprime degli strumenti e i pin offline sotto di esse sono tutti riderivabili, quindi restano indietro.

Il misuratore di archiviazione che suddivide i dati di questo dispositivo in categorie con nome, con Sessioni salvate e Le mie immagini tracciate separatamente dalla Cache asset, qui su un'installazione appena fatta dove ogni categoria è ancora vuotasigned by Lollyvector SVGVerifica tu stessoGet the signed file25 paths~4.8k nodes46 groups59 KBIl misuratore di archiviazione che suddivide i dati di questo dispositivo in categorie con nome, con Sessioni salvate e Le mie immagini tracciate separatamente dalla Cache asset, qui su un'installazione appena fatta dove ogni categoria è ancora vuotasigned by Lollyvector SVGVerifica tu stessoGet the signed file25 paths~4.8k nodes46 groups59 KB

Garanzia tra shell

data-transfer.ts legge e scrive esclusivamente attraverso il capability bridge (host.profile, host.state, host.assets) e le preferenze condivise in localStorage. Poiché il bridge è l'unico punto di contatto, lo stesso modulo produce un bundle identico byte per byte su ogni shell, anche se lo storage sottostante differisce - IndexedDB sul web, il filesystem su Tauri. Le shell Tauri riusano questo modulo senza modifiche. Solo la loro implementazione di host.state differisce. Il test headless esegue il round-trip completo su un bridge in memoria, per questo vale come rappresentante di tutte.

Due shell restano fuori da questa garanzia, per motivi diversi:

Punti di estensione riservati

L'involucro è un manifest più un insieme di parti nominate, per design, così che nuovi tipi di dati portabili possano appoggiarsi su di esso in futuro senza una modifica incompatibile. Si inseriscono come parti additive (nuovo formatVersion, stesso minReader), e il lettore odierno salta ciò che non riconosce. Sono nella roadmap, non ancora implementati. I nomi sono riservati qui affinché il formato resti coerente quando verranno introdotti.

Qualsiasi cosa al di fuori di questi nomi riservati e delle parti sopra elencate è, per un lettore, una parte sconosciuta: lasciata intatta e conteggiata in skipped.

Riferimento