Eight modules each had a copy of the same configuration-context harness (ScreenSnapshots/Snapshots); M12f had to fix
the same capture bug in two of them. :core:design's test fixtures (src/testFixtures, package
se.hagstedt.kvitt.design.testing) now hold Variant, TestClock, TestEnvironment, ScreenSnapshots with its three
capture modes (Root; Screen, with the hand-advanced frame clock; ScreenWhenIdle), MainDispatcherRule and withMain.
Test fixtures rather than a :core:testing module: :core:design's own tests can use them without a dependency on
itself, no module is added to the §6.2 graph, and lint treats them as test sources. The architecture check rejects
test fixtures outside test configurations. Modules keep only their own frame (analytics household, settle size and
inline overlays, settings avatar pictures). Every golden is unchanged.
kvitt.android.screenshots applies Roborazzi with outputDir src/test/screenshots and adds the screenshot test
libraries; the feature plugin applies it and adds the test fixtures, so the seven feature build scripts lose their
copied blocks. Removed: roborazzi-junit-rule and roborazzi-compose (never imported), the explicit
lifecycle-viewmodel-compose (feature plugin, :app) and hilt-lifecycle-viewmodel-compose in :app (both still arrive
through the features; release and debug runtime classpaths are identical), and the unused catalog entries
androidx-hilt-navigation-compose and androidx-lifecycle-viewmodel-compose. @Before/@After setMain pairs in nine test
classes use MainDispatcherRule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
- AppViewModel.onLink drops an invite link while paired (AC-2.6, D-084), so it never prefills S-1 later.
- PushTokens: a failed E-17 PUT (network, 429, 5xx) is kept by PushTokenRetry and sent again after each successful
sync until accepted; a newer FID replaces it (AC-13.7).
- Notifications are VISIBILITY_PRIVATE with a generic public version (notif_generic_title, notif_generic_body):
no description, amount, account or name on a secure lock screen (security review L-7).
- androidResources.localeFilters en, sv (SPEC G-8, AC-19.1).
- Tests: AppViewModelTest (links while paired and unpaired, AC-2.9 permission after the first finished successful
sync), PushTokenRetryTest, NotificationPrivacyTest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
NavHost enter, exit, pop and size transitions are None, so pushed screens,
tab switches, editors and the session gate change at once instead of the
default 700 ms cross-fade. NavTransitionsTest asserts the values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
isMinifyEnabled and isShrinkResources on the release build type with
proguard-android-optimize.txt and an app proguard-rules.pro that adds no rules:
the libraries' consumer rules cover kotlinx.serialization, Room 3, Hilt, Ktor,
WorkManager (worker class names kept) and Firebase. Debug is unchanged.
Signed release APK 43 356 272 -> 11 019 453 bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
AboutScreen loses onOpenLicences, AboutActions its onOpenLicences, the
:app call site its no-op lambda. settings_about_licences was unused in
every module afterwards and is dropped from both strings.xml files and
docs/ux/strings.csv. The 24 S-22 goldens are re-recorded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
Drop the en_dark variant from every screenshot helper and render every
golden at mdpi (Robolectric qualifier w411dp-h<height>dp-mdpi instead of
xhdpi/xxhdpi), so a 411 x 891 dp screen is 411 x 891 px. All goldens
deleted and re-recorded; 1143 -> 865 PNGs. README describes the layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
Server: E-3 invite_kind; E-12 link ?from=<admin name>, E-4 passes it into kvitt://invite;
X-Kvitt-App-Version-Name stored in devices.app_version_name (migration 0003, schema 3);
OpenAPI and examples follow. Phone: :core:model, :core:fakes, :data, features and :app
updated together; goldens re-recorded for S-20 (version name) and new S-1/S-22 states.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
:app binds every :core:model interface to :data in debug and release (AppDataModule, D-085); the
debug fakes module is gone. NavHost over all feature screens with the session gate (S-1, S-2, S-18),
bottom destinations from each screen's own bar, result snackbars, deep links (kvitt://invite and the
/i/<CODE> landing link) and notification taps. :adapter:fcm maps payload v1 to PushEvent and registers
by Firebase Installation ID (firebase-messaging 26, D-087). Push work runs in WorkManager: expedited
sync waited up to 20 s, then the notification from local data or the generic text. WorkManager uses
KvittWorkerFactory, Coil uses :data's ImageLoader, SyncTriggers on start and foreground, update check
in release only. Network security configs (debug cleartext, D-086; pinned-root variant), release
signing from local.properties, notification permission after the first sync.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
AppBuildInfo from BuildConfig for both variants (buildConfig enabled); the
release source set includes DataBindingsModule (D-041), so features'
@HiltViewModels resolve in release as they do against the debug fakes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
Features' @HiltViewModel classes need bindings in :app's graph; until M8 binds :data, debug builds bind
FakeRepositories(FakeScenarios.empty). Debug source set only; M8 deletes the file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
Gradle project in android/ with every module of SPEC §6.2 (build-logic convention plugins, version catalog,
architecture check in check), :core:model types and repository interfaces of §14.2.4 and §14.5, :domain
implementing §14.5.2 and §14.5.4 (125 vector cases), scenario-driven fakes with the empty scenario, Room 3
entities and KvittDatabase v1 with exported schema, :app shell with Hilt, en/sv strings with MissingTranslation
as a lint error, Roborazzi goldens of the empty screen in light and dark.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>