Why
The storage and crypto layer is well tested piece by piece. The slot file, the encrypted store, duress slots, the attempt counter and Argon2 all have suites that use real crypto on temporary directories. What's thin is everything that joins those pieces together:
- The composition root has no tests. No test references
VaultiOS/VaultRoot.swift, so nothing covers the observers it registers, launch recovery or the erase path it wires up.
- Lock and unlock are mostly tested against a fake. Most of that behaviour runs against
FakeAppLockPasswordService. EncryptedVaultPasswordServiceTests (11 tests) is the only suite that runs over the real services.
- Formats are pinned field by field, with no whole-file fixtures. No fixture from a shipped build exists. A change made on both the write side and the read side passes every round trip, and then can't open the vaults and backups people already have.
- Restore has one round-trip suite.
BackupRoundTripTests has 4 tests, with a random key and an in-memory store. The repo has no backups from older builds.
- There are no UI tests.
VaultApp.xcodeproj has no UI test target.
Plan
Sub-issues, one PR each:
- VAULT-84: App Lock: the lock paths through the real services.
- VAULT-85: Unlock: real passwords, erasing and launch recovery.
- VAULT-86: Encryption: golden fixtures from shipped builds.
- VAULT-87: Restore: a corpus of old backups, and end-to-end restores.
- VAULT-88: UI tests: a UI test target and launch tests.
- VAULT-89: UI tests: launch locked, unlock, lock again.
VAULT-84 to VAULT-88 don't depend on each other. VAULT-89 needs VAULT-88.
Ground rules for all of them:
- Go through the real services, real crypto and real files wherever that's practical. Keep the cheap Argon2 parameters the tests use today, unless a ticket says otherwise.
- Where code needs a seam before it can be tested (for example the static lets in
VaultRoot), add the smallest one that works. Don't restructure.
- If a test finds a bug, fix it in the same PR when it's small. Otherwise file a follow-up.
- Anything security-relevant follows VAULT-82's disclosure rule: neutral titles and no exploitable detail in public until the fix has shipped.
- Keep
make validate fast. One deliberately slow test, such as unlocking with the production Argon2 parameters, is fine.
Done when
- Every sub-issue is done, and
make validate runs the new tests, UI tests included.
- The "Test strategy" section of
docs/on-device-encryption.md matches what's actually tested.
- VAULT-82's list of guarantees can point at these tests.
Related: VAULT-82 (security review), VAULT-26 (on-device encryption design), VAULT-61 (no passcode means "Passcode Required").