Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,50 @@ final class PersistedLocalVaultStoreTests {
#expect(result.errors == [])
}

@Test
func retrieveMatchingQuery_keepsOnlyPassphraseItemsHiddenWhenMatcherNil() async throws {
let digester = SearchPassphraseDigester(key: .zero())
// The hidden item's title matches the text query, so the text
// predicate alone would leak it if searchableLevel were
// mishandled. This is the state after a keychain key-load failure
// leaves the matcher nil — hidden items must fail closed.
let hiddenID = try await sut.insert(item: anySecureNote(title: "aaa").wrapInAnyVaultItem(
searchableLevel: .onlyPassphrase,
searchPassphrase: digester.makeDigest(phrase: "aaa"),
).makeWritable())
let controlID = try await sut.insert(
item: anySecureNote(title: "aaa").wrapInAnyVaultItem(searchableLevel: .full).makeWritable(),
)

let query = VaultStoreQuery(filterText: "aaa")
let explicitNil = try await sut.retrieve(query: query, searchPassphraseMatcher: nil)
let convenience = try await sut.retrieve(query: query)

#expect(explicitNil.items.map(\.metadata.id) == [controlID])
#expect(convenience.items.map(\.metadata.id) == [controlID])
#expect(explicitNil.items.map(\.metadata.id).contains(hiddenID) == false)
#expect(explicitNil.errors == [])
}

@Test
func retrieveMatchingQuery_keepsOnlyPassphraseItemsHiddenForWrongPhrase() async throws {
let digester = SearchPassphraseDigester(key: .zero())
let hiddenID = try await sut.insert(item: anySecureNote(title: "bbb").wrapInAnyVaultItem(
searchableLevel: .onlyPassphrase,
searchPassphrase: digester.makeDigest(phrase: "secret phrase"),
).makeWritable())
let controlID = try await sut.insert(
item: anySecureNote(title: "bbb").wrapInAnyVaultItem(searchableLevel: .full).makeWritable(),
)

let query = VaultStoreQuery(filterText: "bbb")
let result = try await sut.retrieve(query: query, searchPassphraseMatcher: digester)

#expect(result.items.map(\.metadata.id) == [controlID])
#expect(result.items.map(\.metadata.id).contains(hiddenID) == false)
#expect(result.errors == [])
}

@Test
func retrieveMatchingQuery_returnsCorruptedItemsAsErrors() async throws {
let codes: [VaultItem.Write] = [
Expand Down