3.2 KiB
Android one-time passwords
Issue #107 connects the TOTP destination to the storage-owned discovery catalog. Opening the list reads cached metadata without decrypting entries. Select a row, then Unlock to display its issuer, account, grouped code, countdown and progress. Refresh TOTP catalog reuses unchanged ciphertext while locked and authenticates for new or changed entries; discovery, progress and cached search implement #110.
The normal entry viewer and TOTP detail use the same code component and native viewer controller. Decryption, creation and editing reconcile the catalog in Rust. Only nonsecret row identities and revisions are restored after recreation. OTP parameters, codes and authentication secrets are never persisted by Kotlin.
Rust computes SHA1/SHA256/SHA512 codes, six/eight digits, custom periods, absolute validity boundaries, grouping and countdown. The composed code component owns a STARTED-lifecycle coroutine that submits OS clock facts without touching the authentication lease. Scrolling it out or leaving stops decryption/countdown ticks; an expiry-only native window check still erases held codes when hidden. Rust validates each returned window before publication, including delayed results and backward clock changes. Lock, background, expiry, entry changes and stale revisions remove codes and cancel presentation. Explicit copies use the existing sensitive clipboard adapter and Rust timeout/ownership checks.
HOTP in the normal entry viewer requires Generate next HOTP code and a separate counter confirmation. The existing pass-otp core increments and atomically commits the encrypted counter before returning its code. Refresh and Copy use that same committed counter without incrementing. Stale documents, open editors, failed Git commits and overflow cannot consume a counter. The TOTP discovery catalog remains specific to time-based entries. Android exposes no Watch sharing controls.
Validation
Rust tests cover RFC 6238 algorithm vectors, six/eight digits, 30/60-second boundaries, cache agreement, polling without lease renewal, malformed URI diagnostics, stale revision revocation, HOTP confirmation, copy/refresh stability, commit rollback and counter overflow. Android's NativeOtpPresentationTest uses real encrypted stores with fake wall/lease clocks to verify catalog-only reads, boundary transitions, tick lease expiry, clipboard handoff expiry, queued user actions overtaking read-only observations, both HOTP generations and background revocation. TotpScreenTest covers explicit unlock, grouped code/countdown/copy, lock cleanup, HOTP confirm/cancel, tick cancellation on leaving and 300% text without clipped digits. Computer use inspects the same Compose components on an ARM64 emulator using disposable presentation fixtures.
All emulator installs preserve the retained app container. Production Keystore and biometric enrollment are unchanged by this story; the native controller tests provide deterministic OS capability callbacks. Supported release ABIs remain arm64-v8a and armeabi-v7a; physical devices and x86_64 are outside this milestone.