Skip to content

Extract the autofill credential resolver and cover its gating - #570

Merged
bradleymackey merged 1 commit into
mainfrom
fix/autofill-resolver-tests
Sep 15, 2026
Merged

bradleymackey merged 1 commit into
mainfrom
fix/autofill-resolver-tests

Conversation

@bradleymackey

Copy link
Copy Markdown
Member

Problem

VaultCredentialProviderViewController (the autofill extension's entry point) had zero tests. Its most security-relevant decision — provideCredentialWithoutUserInteraction deciding whether an item can be served to the QuickType bar without any user interaction — lived inline in the UIKit view controller, untestable: the auth gate via requiresAuthenticationToCopy, the HOTP refusal (counter must not increment without UI), and an untestable direct Date() for TOTP rendering. VaultAutofillViewModel was also untested.

Fix / refactor

  • New AutofillOTPCredentialResolver: the body of provideOTPCredential moved verbatim into a small @MainActor struct with an Outcome enum (code / userInteractionRequired / notFound / failure), injected with a retrieval closure, the copy-action handler, and an EpochClock (replacing the raw Date()).
  • The VC becomes a thin Outcome → extensionContext switch. The refusal paths map to exactly the same indistinct ASExtensionErrors as before — no new error taxonomy leaking item properties.
  • Behavior change: none intended; TOTP rendering now uses VaultRoot.clock instead of Date() (same wall clock in production).

Tests

AutofillOTPCredentialResolverTests:

  • nil / malformed / unknown record identifiers and non-OTP items → .notFound
  • auth-gated item → .userInteractionRequired (the C4-relevant gate, now pinned)
  • HOTP item → .userInteractionRequired
  • TOTP item → code rendered for the injected clock's epoch (deterministic, compared against TOTPAuthCode.renderCode directly)
  • retrieval error → .failure

VaultAutofillViewModelTests: feature routing, dismiss publisher, blank-string filtering on textToInsertPublisher, cancel-reason forwarding.

VaultiOSAutofillTests goes from 2 tests to 15.

Also fixed en route: the VaultiOSAutofillTests scheme had no TestPlanReference (unlike the other test schemes), so running it standalone ignored TestPlans/Individual/VaultiOSAutofillTests.xctestplan and the snapshot locale guard fataled on non-en_US hosts. The scheme now references its plan, matching VaultiOSTests.

Local verification: VaultiOSAutofillTests scheme green on iPhone 18 Pro Max / iOS 27.0.

⚠️ Automatic CI is still disabled (#548), so this is local verification only.

🤖 Generated with Claude Code

The QuickType no-interaction path had zero tests despite carrying the
auth gate and the HOTP refusal. Move the logic verbatim into an
injectable AutofillOTPCredentialResolver (clock replaces raw Date()),
reduce the view controller to an Outcome switch with the same
indistinct ASExtensionErrors, and cover resolver and view model. Also
wire the missing TestPlanReference into the VaultiOSAutofillTests
scheme so its locale-pinned snapshots run correctly standalone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bradleymackey
bradleymackey merged commit 2135c91 into main Sep 15, 2026
@bradleymackey
bradleymackey deleted the fix/autofill-resolver-tests branch September 15, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant