Implement Android TOTP list and large-code detail presentation #107

Closed
opened 2026-08-17 19:15:15 +00:00 by hugo · 1 comment
Owner

Goal

Provide complete pass-otp viewing and copy behavior in the TOTP destination and normal entry viewer.

Scope

  • List storage-identified TOTP entries from the discovery catalog and open a native detail screen with issuer/account, large grouped code, countdown/progress, copy action, lock/error state, and refresh.
  • Request decryption only when a code/detail is opened and calculate every TOTP/HOTP value and validity window in crates/storage.
  • Update visible countdown/code from storage-owned results using a lifecycle-scoped coroutine; ticks, recomposition, and animations must not extend the authentication lease.
  • Show the same TOTP component at the top of an OTP-bearing normal entry and let storage update the catalog after an entry is decrypted/created/edited.
  • Support TOTP algorithms/digits/periods and HOTP behavior exactly as the shared core allows; counter-changing HOTP operations must use storage-owned atomic semantics and explicit confirmation.
  • Copy only the current storage-returned code through the secure clipboard adapter and clear it according to storage timeout/race rules.
  • Immediately remove codes on background, expiry, manual lock, entry change, or stale revision.
  • Do not implement Apple Watch sharing, snapshot, selection, or synchronization.

Acceptance criteria

  • RFC/upstream pass-otp fixtures display the exact code and transition at boundary times using fake clocks.
  • Code/countdown updates do not renew the lease and stop when not visible.
  • TOTP-bearing entry views and the TOTP destination agree and keep the cache current.
  • Copy is explicit, sensitive-marked, timed, and race-safe.
  • Kotlin never parses otpauth://, calculates OTP, mutates HOTP counters, or persists secret parameters.

Depends on TOTP discovery, the structured viewer, biometric authentication, and lifecycle security. Part of #87.

Android support update (2026-10-08)

User-directed scope: Android release and CI targets are arm64-v8a and armeabi-v7a. x86_64 Android is excluded for now. Validation for every Android milestone issue uses emulator devices only; physical-device testing and physical-device checklists are excluded. Record the limits of available ARM emulator/API images without claiming physical-device coverage.

## Goal Provide complete pass-otp viewing and copy behavior in the TOTP destination and normal entry viewer. ## Scope - List storage-identified TOTP entries from the discovery catalog and open a native detail screen with issuer/account, large grouped code, countdown/progress, copy action, lock/error state, and refresh. - Request decryption only when a code/detail is opened and calculate every TOTP/HOTP value and validity window in `crates/storage`. - Update visible countdown/code from storage-owned results using a lifecycle-scoped coroutine; ticks, recomposition, and animations must not extend the authentication lease. - Show the same TOTP component at the top of an OTP-bearing normal entry and let storage update the catalog after an entry is decrypted/created/edited. - Support TOTP algorithms/digits/periods and HOTP behavior exactly as the shared core allows; counter-changing HOTP operations must use storage-owned atomic semantics and explicit confirmation. - Copy only the current storage-returned code through the secure clipboard adapter and clear it according to storage timeout/race rules. - Immediately remove codes on background, expiry, manual lock, entry change, or stale revision. - Do not implement Apple Watch sharing, snapshot, selection, or synchronization. ## Acceptance criteria - RFC/upstream pass-otp fixtures display the exact code and transition at boundary times using fake clocks. - Code/countdown updates do not renew the lease and stop when not visible. - TOTP-bearing entry views and the TOTP destination agree and keep the cache current. - Copy is explicit, sensitive-marked, timed, and race-safe. - Kotlin never parses `otpauth://`, calculates OTP, mutates HOTP counters, or persists secret parameters. Depends on TOTP discovery, the structured viewer, biometric authentication, and lifecycle security. Part of #87. ## Android support update (2026-10-08) User-directed scope: Android release and CI targets are **arm64-v8a** and **armeabi-v7a**. x86_64 Android is excluded for now. Validation for every Android milestone issue uses emulator devices only; physical-device testing and physical-device checklists are excluded. Record the limits of available ARM emulator/API images without claiming physical-device coverage.
hugo added this to the 06 - Implement an Android version of the software milestone 2026-08-17 19:15:15 +00:00
hugo added the enhancement label 2026-08-17 19:15:15 +00:00
hugo added the critical label 2026-10-11 13:37:49 +00:00
Author
Owner

Commit: 6a864a8, pushed to main.

Implemented Android TOTP list/detail and shared OTP presentation in Rust and Kotlin.

  • The TOTP destination reads storage's cached catalog without decrypting entries; explicit row selection and Unlock open its detail. It presents issuer/account, large grouped code, countdown/progress, refresh, secure copy, lock/error states and compact/expanded layouts. The same component appears above fields in the normal entry viewer. Decrypt/create/edit reconcile the Rust catalog.
  • Rust owns algorithm/digits/period parsing, HMAC codes, grouping, countdown, absolute window validation and document revision checks. The rendered component owns its STARTED-lifecycle coroutine; scrolling it out or leaving stops decryption/countdown ticks without touching the lease or showing authentication busy UI. A cheap expiry-only Rust window check still erases hidden codes. Expired or delayed windows are masked before publication; background, expiry, lock, entry changes and stale revisions revoke presentation.
  • HOTP uses the existing pass-otp atomic counter/Git transaction after a separate counter confirmation. Only a committed code is shown. Refresh/copy retain that counter; declined confirmation, stale ciphertext, open editors, commit failure and overflow cannot consume a counter.
  • Explicit copies use the existing sensitive clipboard adapter and Rust timeout/ownership cleanup. A fresh Rust window check immediately before the OS write also rejects a code that expired during the native-to-clipboard handoff. Only nonsecret row identity/revision is saved for recreation. Android adds no Watch controls.

Validation:

  • Required cargo fmt/check (warnings denied), workspace clippy (warnings denied), and cargo test --workspace passed with Rust 1.97.1. The workspace socket/SSH tests required normal local process access.
  • Android androidVerification and release lint passed: JVM tests, architecture/ktlint/Lint gates, both ARM ABI builds, APK/AAB native/16 KB audits, dependency inventory. Final APK manifest/backup exclusions, release symbols and CycloneDX/license audits passed.
  • Rust RFC 6238 SHA1/SHA256/SHA512 fixtures at exact boundary times, six/eight digits and custom periods passed. Tests prove no lease renewal, cache agreement, malformed OTP diagnostics, stale revision revocation, HOTP confirmation/copy/refresh, rollback and overflow.
  • Real encrypted Kotlin/Rust controller fixtures passed on API 26 ARM64 and strict API 37 ARM64 with 16384-byte pages and compatibility mode disabled. They cover cached navigation without unlock, fake wall/lease clock boundaries, clipboard expiry at the handoff, read-only observations overtaken by user actions without revoking their lease, HOTP generations and lifecycle cleanup. Full native controller/editor/settings regression suite passed on strict 16 KB ARM64.
  • Final app regression suite reported OK (38 tests) on API 37 ARM64; opt-in interactive/strong-biometry tests remain skipped unless explicitly enabled. OTP UI tests prove unlock/copy/refresh/lock and HOTP confirm/cancel; a 300% text test verifies no digit clipping, and a component-disposal test verifies tick cancellation.
  • Computer use validated the actual Compose catalog/detail, locked state, large grouped code/countdown, explicit copy/lock cleanup, HOTP counter confirmation and resulting code, plus scrolling to actions at 300% text size using disposable presentation fixtures. Retained simulator app data and enrollment were preserved with install -r. Deterministic native tests use OS capability callbacks; no claim of new real-Keystore biometric coverage. Physical devices and x86_64 are excluded by milestone scope.

Reviewed the final changes against every #107 acceptance criterion. See docs/android/otp.md for behavior and evidence. Completion is recorded in the single commit referenced below.

Commit: [6a864a8](https://git.rfc1437.de/hugo/IronStorage/commit/6a864a8d7fe3bcba2d9930ba98a94e2e0fb63c0e), pushed to main. Implemented Android TOTP list/detail and shared OTP presentation in Rust and Kotlin. - The TOTP destination reads storage's cached catalog without decrypting entries; explicit row selection and Unlock open its detail. It presents issuer/account, large grouped code, countdown/progress, refresh, secure copy, lock/error states and compact/expanded layouts. The same component appears above fields in the normal entry viewer. Decrypt/create/edit reconcile the Rust catalog. - Rust owns algorithm/digits/period parsing, HMAC codes, grouping, countdown, absolute window validation and document revision checks. The rendered component owns its STARTED-lifecycle coroutine; scrolling it out or leaving stops decryption/countdown ticks without touching the lease or showing authentication busy UI. A cheap expiry-only Rust window check still erases hidden codes. Expired or delayed windows are masked before publication; background, expiry, lock, entry changes and stale revisions revoke presentation. - HOTP uses the existing pass-otp atomic counter/Git transaction after a separate counter confirmation. Only a committed code is shown. Refresh/copy retain that counter; declined confirmation, stale ciphertext, open editors, commit failure and overflow cannot consume a counter. - Explicit copies use the existing sensitive clipboard adapter and Rust timeout/ownership cleanup. A fresh Rust window check immediately before the OS write also rejects a code that expired during the native-to-clipboard handoff. Only nonsecret row identity/revision is saved for recreation. Android adds no Watch controls. Validation: - Required cargo fmt/check (warnings denied), workspace clippy (warnings denied), and cargo test --workspace passed with Rust 1.97.1. The workspace socket/SSH tests required normal local process access. - Android androidVerification and release lint passed: JVM tests, architecture/ktlint/Lint gates, both ARM ABI builds, APK/AAB native/16 KB audits, dependency inventory. Final APK manifest/backup exclusions, release symbols and CycloneDX/license audits passed. - Rust RFC 6238 SHA1/SHA256/SHA512 fixtures at exact boundary times, six/eight digits and custom periods passed. Tests prove no lease renewal, cache agreement, malformed OTP diagnostics, stale revision revocation, HOTP confirmation/copy/refresh, rollback and overflow. - Real encrypted Kotlin/Rust controller fixtures passed on API 26 ARM64 and strict API 37 ARM64 with 16384-byte pages and compatibility mode disabled. They cover cached navigation without unlock, fake wall/lease clock boundaries, clipboard expiry at the handoff, read-only observations overtaken by user actions without revoking their lease, HOTP generations and lifecycle cleanup. Full native controller/editor/settings regression suite passed on strict 16 KB ARM64. - Final app regression suite reported OK (38 tests) on API 37 ARM64; opt-in interactive/strong-biometry tests remain skipped unless explicitly enabled. OTP UI tests prove unlock/copy/refresh/lock and HOTP confirm/cancel; a 300% text test verifies no digit clipping, and a component-disposal test verifies tick cancellation. - Computer use validated the actual Compose catalog/detail, locked state, large grouped code/countdown, explicit copy/lock cleanup, HOTP counter confirmation and resulting code, plus scrolling to actions at 300% text size using disposable presentation fixtures. Retained simulator app data and enrollment were preserved with install -r. Deterministic native tests use OS capability callbacks; no claim of new real-Keystore biometric coverage. Physical devices and x86_64 are excluded by milestone scope. Reviewed the final changes against every #107 acceptance criterion. See docs/android/otp.md for behavior and evidence. Completion is recorded in the single commit referenced below.
hugo closed this issue 2026-10-12 09:43:44 +00:00
Sign in to join this conversation.