Skip to content

v1.2.0 — OFF cache + body-cap streaming + R8 minify

Choose a tag to compare

@DocGerd DocGerd released this 28 May 11:19
· 266 commits to develop since this release
Immutable release. Only release title and notes can be modified.
b3d4ef0

[1.2.0] — 2026-05-28

Added

  • Offline cache for OFF lookups of non-pantry barcodes. Re-scanning a
    product that was previewed (but not added) now resolves locally —
    no network call, no 4-host fallback walk. 30-day TTL; cache row is
    deleted when the barcode is committed to the pantry. (#48)

Changed

  • Release builds now use R8 minify + shrinkResources. APK size
    reduced from 40,523,977 bytes (~40.5 MB) at v1.1.0 to 24,140,473
    bytes (~24.1 MB) at v1.2.0 — a 40.4% reduction. (SR-9, refs #36)

Security

  • Replace header-only OFF response body cap with streamed enforcement.
    The 256 KB cap now fires on chunked responses regardless of
    Content-Length advertisement, closing the gap left by the v1.1.0
    hotfix. (#52)
  • R8 strips unused code from the release artifact, reducing attack
    surface. Belt-and-braces -keep rules in app/proguard-rules.pro
    preempt the "first-time R8 enable strips reflection target"
    symptom for kotlinx.serialization @serializable types
    (OffProduct, OffApiEnvelope) and Room entities/DAOs (Product,
    OffLookupCacheEntry, ProductDao, OffLookupCacheDao, plus
    AppDatabase and Converters defensively). (SR-9, refs #36)

Tests / quality

  • 194 → 218 JVM unit tests.
  • RNG screenshot harness added (#74 / SR-74) using Robolectric
    Native Graphics + golden-PNG diff. Covers icon variants, theme,
    font-scale, and Coil image rendering — retires UAT §0 rows 2-4,
    §2 rows 1, 2, and 4, §11 last row (greyed-row 45% opacity check),
    and v1.2 §11 Coil row.
  • Scan-flow Compose UI tests (#75 / SR-75) cover OFF-hit, OFF-miss
    timeout fallback, in-inventory remove, and not-in-inventory +
    switch-to-Add — retires UAT §7 (8 of 9), §8 (5 of 6), §11 (5), §12 (2).
  • Search UI test (#76 / SR-76) — retires UAT §9 (5 rows).
  • Camera permission deep-link + onResume tests (#77 / SR-77) —
    retires UAT §4 (5 of 6), §5 (5 of 7), §6 (3 of 8).
  • Rotation + error-tone tests + detekt rule (#78 / SR-78) — config-change
    • error tone; the ErrorToneRule extracted to a standalone
      :detekt-rules Gradle module with a proof test. Retires UAT §14
      (configuration change row) and §15 (error tone).
  • CI emulator job (#79 / SR-79) on
    reactivecircus/android-emulator-runner@v2.37.0, API 35, PR-gating
    connectedDebugAndroidTest runs. ~5-8 min added per PR.
  • R8 static-inspection script (#80 / SR-80) verifies @Serializable +
    @Entity classes survive minification in the release APK.
  • MIGRATION_1_2 emulator-drive runbook (#81 / SR-81) — script + docs
    for on-device migration smoke; retires UAT v1.2 §1 upgrade-install row.
  • OFF resilience tests (#82 / SR-82) — fallback-chain matrix +
    cache offline replay; retires UAT v1.2 §3-5 (3) + §12 (1).
  • androidTest permission-revoke fix (SR-117 / PR #118) — adds
    CameraPermissionGate.isCameraGranted test seam so revoking a held
    runtime permission no longer kills the shared instrumentation
    process.
  • Room schema baseline committed under app/schemas/ (#57 / SR-17),
    unlocking MigrationTestHelper-based migration tests against the
    v1 → v2 schema delta.
  • UAT checklist umbrella closed (#73) — every retired row annotated
    with [automated by SR-N]; new "Stays human-only" appendix
    enumerates the irreducibly-physical items + the v1.2 OFF CDN chunked
    encoding rule.
  • CLAUDE.md lessons fold (#119) — 6 new entries in "Things that
    have bitten past sessions" covering revoke-of-held-permission,
    custom AndroidJUnitRunner.newApplication, detekt custom rules in
    standalone module, post-tag lockfile untrack, on-device CI catches
    what static review can't, GitFlow ruleset constraints.

Install (sideload)

  1. Download app-release.apk from this release.
  2. Enable "Install unknown apps" for your browser or file manager (Android: Settings → Apps → Special access).
  3. Open the downloaded APK. The installer will request permission to install; the app updates over v1.0.x / v1.1.x in place (no data loss).

Verify the APK

SHA-256  8be3e781c4837dc433fc6b11b70baa02916e44d9ac4533df4712c2286c8ad366  app-release.apk
size     24,271,545 bytes (~24.27 MB)

Signing certificate (lifetime identity for all v1.x updates):

Subject:    CN=Patrick Kuhn, OU=DocGerdSoft, O=DocGerdSoft, L=Schwetzingen, ST=BW, C=DE
SHA-256:    ec9a4bb80ccbe56b3aeccf73eb220418be87ac10b1128bdd868b3d0cd87cb3d9
SHA-1:      fbd758914b3abeb71321c03b429716dae9e212cc

If you have v1.0.x or v1.1.x installed, the signing cert matches and Android will accept the upgrade-install.

Source

Built reproducibly from tag v1.2.0 at commit b3d4ef02e6bcbb8516c765cd197834244e2500d5.