med-det-samme/docs/backup-verification.md
Ole-Morten Duesund dae09ff9fb Record backup verification: Google new-device demo + test coverage
Documents how each backup path has actually been exercised — Google
Auto Backup verified on emulator (status card, blob round-trip via local
transport, restore card by screenshot; decrypt+import by instrumented
test since ADB can't tap the Compose dialog reliably), file import/
export verified earlier, S3 still pending a live bucket. Captures the
scrypt wf=15 rationale and the safe real-hardware test protocol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:49:54 +02:00

2.6 KiB

Backup — verification record

How the three backup mechanisms have actually been exercised, so a future reader knows what's proven vs. assumed. Re-verify after touching BackupManager, AgeBackupCrypto, or the manifest backup rules.

Google Auto Backup (new-device restore) — emulator demo, 2026-06-11

Run on a throwaway API-35 AVD with the local backup transport (bmgr transport com.android.localtransport/.LocalTransport), which is deterministic and stands in for the Google transport.

Verified by screenshot:

  • Settings status card reads "Google-sikkerhetskopi aktiv (kryptert)" (not the red "ikke satt opp") with a passphrase set and no S3.
  • bmgr backupnowpm clear (simulated new device) → bmgr restore: the age blob files/gbackup/latest.json.age returns and the DB is empty.
  • The Today screen then shows the "Kryptert sikkerhetskopi funnet" card with a passphrase prompt.

Verified by instrumented test (CloudBackupRoundTripTest, green on emulator) — this covers the final decrypt+import step, which ADB/uiautomator can't tap reliably (the Compose dialog reports a phantom node and touch isn't delivered to the button behind the soft keyboard — a harness quirk, not an app bug):

  • writeThenRestoreOnEmptyDb: blob written → empty DB → pendingCloudRestore fires → import(blob, passphrase) brings the exact data back.
  • wrongPassphraseFailsAndKeepsDbEmpty: wrong passphrase throws, DB stays empty.
  • noPassphraseRemovesBlob: clearing the passphrase deletes the blob.
  • testBackupWithOnlyPassphraseSucceeds / …NothingConfiguredThrows: the passphrase-only "Test backup" path succeeds instead of erroring.

Not yet done on real hardware: the true new-device round-trip via the Google transport (uninstall + reinstall). Safe protocol when attempted — file-export first as a safety net, then bmgr backupnow → uninstall → reinstall.

Note: scrypt work factor is 15, not age's desktop default 18 — 18 needs a 256 MiB working set and OOM-crashes inside a normal Android heap. 15 = 32 MiB; largeHeap covers decrypting foreign files made at 18.

S3 / Garage — not yet verified end to end

The SigV4 signer is unit-tested against AWS's published example, and listAllKeys/parseListKeys are unit-tested, but no real PUT/GET against a live Garage bucket has run yet (no bucket available). Pending: configure credentials, "Test backup nå", then confirm the object and age -d it.

File export/import — verified

Exercised on-device in earlier sessions: encrypted export → import round-trip, and v1→v2 backup-format conversion (BackupSerializerTest).