Self-review of the last four commits against the codebase's own error-handling
conventions. Two real defects found, both in GoogleProfileMerger, both mine:
1. Its writes could crash sign-in. The class doc said "best-effort by design",
but createUser/updateDisplayName/updatePhotoUrl were unwrapped, and merge()
runs inside the view model's onSuccess block in viewModelScope — a throw
there is an unhandled coroutine exception, after authentication has already
succeeded. The words claimed a contract the code didn't deliver. merge() now
never throws: the seed runs under runCatching and failures are recorded.
(The pre-rework copies had the same unwrapped createUser, so this is older
than my refactor — but I rewrote the class and kept the hole, and the doc
claiming best-effort made it worse than inherited.)
2. It was the only file in domain/ using android.util.Log. The house pattern
for use cases is an injected CrashReporter (DailyQuestionResolver is the
model): recordException for failures, log() for breadcrumbs. Swapped over;
a swallowed failure now actually surfaces in Crashlytics instead of dying
in logcat on a device we'll never see.
Also aligned: the two Kotlin assert() calls in RecoveryPhraseNormalizationTest
were the only ones in the suite and silently depend on the JVM -ea flag — now
assertNotEquals like everything else; RecoveryScreen's OutlinedButton is
imported rather than fully qualified (the file's lone qualified call was the
anomaly, not the rule).
GoogleProfileMergerTest pins the contract: a failed read writes nothing and is
recorded (C-AUTH-001's conflation), a failed write is recorded not thrown, a
stub is not seeded over, a complete profile is untouched, and only blank fields
are filled. Mutation-checked by removing the runCatching — and that check also
caught a bug in the test itself: the "complete profile" fixture had defaulted
photoUrl to "", so the merger legitimately tried to fill it and the strict
mock's throw was swallowed by the very runCatching under test — a test passing
for the wrong reason. Fixture fixed; the mutation now kills exactly the one
test that asserts the contract.
Hilt graph validated via assembleDebug; full unit suite green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>