AppStateBackup

class AppStateBackup(passkeyManager: PasskeyManager, storage: BackupStorage)

Coordinates PRF-encrypted backup and restore of app-specific state (e.g. Kicks's MatchStore witnesses + commitments, BBoard drafts, future game/agent state).

Why "AppState" and not "Sigil": the wallet seed and the sigil DID both derive from the user's passkey via PRF (see WalletSeedSource and SigilIdentityProvider). Neither needs to travel through a Block Store blob to survive a new device — the passkey carries them. What can't be re-derived from the passkey is per-app state that's accumulated mid-session: witness keys paired to a deployed contract, draft data, in-flight game moves. That's what this class persists.

Flow:

  1. Authenticate passkey with BACKUP_SALT → 32-byte PRF output.

  2. HKDF(PRF output) → AES-256-GCM key.

  3. Encrypt appMetadata → versioned blob.

  4. Store blob in BackupStorage (Block Store by default).

Restore (new device or sign-in flow):

  1. Passkey syncs via Google Password Manager.

  2. Authenticate with the same salt → same PRF output → same AES key.

  3. Decrypt blob → RestoredAppState.appMetadata handed to the host.

Security: intermediate key material (PRF output, AES key, plaintext) is wiped in finally blocks immediately after use. Google sees only an opaque encrypted blob.

Versioning: the blob's leading byte is the schema version. v2 is the post-PRF format (this class); v1 blobs from before the AppStateBackup extraction are silently rejected as "no backup" — the seed and sigil fields they carried are redundant now, and the appMetadata they carried isn't decryptable under the v2 schema.

Constructors

Link copied to clipboard
constructor(passkeyManager: PasskeyManager, storage: BackupStorage)

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
suspend fun backup(activity: Activity, appMetadata: ByteArray? = null)

Encrypts appMetadata and writes the blob to storage.

Link copied to clipboard
suspend fun deleteBackup()

Delete the backup.

Link copied to clipboard
suspend fun hasBackup(): Boolean

Whether a backup exists in storage.

Link copied to clipboard

Whether the storage backend is available.

Link copied to clipboard
suspend fun restore(activity: Activity): RestoredAppState

Reads + decrypts the app-state blob from storage.