/sync
) is unidirectional, with a mobile client providing an update when new files are included in the backup. The client only fetches remote updates in certain scenarios (see below).
The contains the encoded for World App plus a set of raw files. The source of truth is the BackupFormat
structure in Bedrock. The files back up all required self-custodial information that a user holds in their World App. In particular, today this is the user’s World ID s (or PCPs).
One of the challenges the system faces is that because the backup is end-to-end encrypted, the Backup Service cannot enforce any type of rules that prevent accidental data loss. For example, consider Client M in which the User gets their passport verified and hence obtains a PCP. If the user is also authenticated on Client N, and a backup sync is triggered from Client N, the PCP would be removed from the backup because Client N does not have it.
Backup State Management
The backup system uses a manifest-based approach to prevent accidental data loss during syncs. Each backup contains a manifest that describes its contents and enforces proper versioning.The Manifest
Each backup ships with a manifest that describes the backup’s contents. The manifest serves as a versioned ledger, ensuring clients always begin from the current state () and apply incremental updates to produce the next state ().blake3
hash of the manifest file (raw bytes).
Responsibilities
- Client: Bears sole responsibility for performing backup updates based on the current state. Must verify it’s operating on the latest manifest before making changes.
- Server: Maintains a pointer to the current state hash. Validates state transitions during updates but cannot inspect encrypted contents.
ManifestManager API (Client-Side)
TheManifestManager
provides controlled access to backup modifications. Before any operation, it fetches the remote state hash to ensure consistency:
- If the local manifest is missing → prompts user to authenticate and download the remote state
- If
remote_manifest_hash == local_manifest_hash
→ proceeds with updates - If hashes differ → prompts user to authenticate and download the remote state
Available Methods
store_file(designator, filePath)
- Adds a new file to the backup. Verifies path uniqueness, computes checksum, triggers pack & upload.list_files(designator)
- Returns all entries for the given designator.replace_all_files_for_designator(designator, newFilePath)
- Replaces all existing entries for a designator with a new file.remove_file(filePath)
- Removes a file entry from the manifest.
Pack & Upload Process
When building and uploading a new backup version:- Validate local manifest - Error if missing; prompt to download remote.
- Build unsealed backup - Collect all files from the manifest. Verify checksums match for every file.
- Submit sealed backup - Include updated manifest inside. Report current and new manifest hashes to backend.
- Backend validation - Verifies current hash matches recorded state before accepting update.
Download & Unpack Process
When downloading and unpacking a remote backup:- Decrypt sealed backup - Extract and replace local manifest unconditionally.
- Unpack files - Write each file to its declared
filePath
. Replace existing files (log errors for checksum mismatches).
Startup Verification
On app startup, the client fetches the remote state checksum. If it differs from the local manifest, the user is prompted to authenticate and download the remote backup.Additional Safety Measures
- Backend short-lived locks - Prevents narrow race windows during updates, only one update at a time. Authoritative enforcement remains via manifest hash validation.
- Hard links (Android Only) - Hard links are created under
/backup/files/{checksum}
to guard against accidental deletion of source files. Links are removed on file removal.