trackslash

Description

Split from VAULT-51 (#648), which added the duress slots and "make duress database" to the encrypted store. This is the per-vault settings part of the design (docs/on-device-encryption.md, "Everything else for VAULT-23").

Why: each vault, real or duress, needs its own backup password and its record, backup events, and auto-backup configuration and retention. Otherwise a duress vault would show, use, overwrite or clean up the real vault's backups (MANIFESTO.md C10), and the Backups page would show the real vault's last backup.

The change:

  • The payload: add vault.settings to the payload, always encoded so every vault's payload has the same shape. It holds:
    • the backup password (derived key) and its date or record;
    • the last backup event;
    • the auto-backup configuration.
  • Routing: route BackupPasswordStore, BackupEventLogger and the auto-backup configuration by the store session:
    • plain mode keeps today's keychain and UserDefaults;
    • an unlocked encrypted vault uses its payload;
    • locked has none.
    • Services reload on unlock and clear on lock.
  • Auto-backup isolation: each vault records the auto-backup files it wrote, cleans up only those, and never overwrites another's.
  • Conversion: when converting plain to encrypted (VAULT-47's converter), move the plain settings into the real vault's payload, then delete them from the keychain and UserDefaults.
  • Erase: erasing (VAULT-52) needs nothing extra for payload settings, because they go with the file.

Rules: no telemetry or log about which vault is open (C3), and nothing in a payload may reveal that another vault exists.

Tests:

  • Routing in each mode.
  • Isolation of auto-backup between two vaults, including cleanup.
  • Migration of the settings at conversion.
  • Payload shape equality.

Linked issues

0

GitHub

0

No branches or pull requests linked.

Comments

1
Bradley

Done in https://github.com/badbundle/vault-app/pull/651.

What each vault keeps: every encrypted vault, real or duress, keeps its own settings in its payload (vault.settings):

  • the backup password,
  • the last backup event,
  • the auto-backup configuration and the files it wrote,
  • the PDF backup's hint.

Every key is always written, so all payloads have the same shape. A new duress vault starts with none set, and the default hint.

Routing: OpenVaultBackupSettings routes the backup password store, the event logger, auto-backup and the PDF hint by session.

  • Plain mode uses the keychain and UserDefaults, as before.
  • An unlocked vault uses its payload.
  • A locked app has none.
  • They reload on every switch or lock, including #650's lock().
  • Saves only land in the vault they were read from; plain-store writes go through the same check.
  • An export or backup records its event in the vault that was open when it started.

Auto-backup isolation (C10):

  • A vault never overwrites a file; a clash gets -2, -3.
  • A vault only cleans up files its own auto-backup wrote, and only forgets names it deleted or confirmed gone. iCloud placeholders count as present.
  • On a vault change, the old destination is cleared, and the new one is set up once any running backup has finished.

Conversion: the plain settings move into the real vault, then are deleted from the device.

Plain-mode change: cleanup now only deletes files auto-backup recorded. An existing configuration is seeded once from the folder with exactly what the old cleanup would have deleted, so upgrading users' old auto-backups keep being cleaned up.

Tests:

  • Routing in each mode.
  • A composed suite with the real session, settings, data model and auto-backup service, covering the window where the vault has switched but the settings haven't reloaded.
  • Two-vault isolation, including cleanup and name clashes.
  • The seed, the conversion move, and payload shape.
  • iCloud never-overwrite and placeholder handling.

Review: a security review found no path where one vault touches another's backups. It raised five should-fixes: the shared PDF hint, forgetting files after a missed listing, the upgrade seed, plain-mode writes racing a switch, and tests. All were fixed and re-reviewed.

Remaining nits (the safe direction):

  • If no folder was set up at upgrade, the seed runs when one is first chosen.
  • iCloud-only placeholder backups aren't seeded, so they're never cleaned up automatically.