Files
IronStorage/docs/android/totp-discovery.md
T
hugo f4a6edbc68
Android ARM verification / rust (push) Failing after 49m58s
Android ARM verification / android (push) Failing after 8s
Dependency security audit / rustsec (push) Failing after 22s
Implement Android TOTP cached discovery and search (#110)
2026-10-12 20:38:33 +02:00

3.8 KiB

Android TOTP discovery

The TOTP destination opens the storage-owned non-secret catalog while locked. Rows are canonical entry identities and paths. Rust hashes current ciphertext before returning a row, and Kotlin never parses entries or OTP URIs. Searching uses the cancellable cached navigation API, debounces input, cancels the preceding Rust operation, and publishes only the latest query's result.

Explicit refresh and pull-to-refresh use one serialized Rust discovery operation. An unchanged usable catalog refreshes while locked without requesting a passphrase or decrypting an entry. New or changed ciphertext requires authentication; an existing valid lease is reused. Only changed records are decrypted. The UI polls Rust's typed preparing, inspecting, saving, complete and cancelled phases and shows total, inspected, cache hits, matches and unavailable counts. Progress is determinate once the total is known. Cancellation and loss of foreground ownership cancel native work and leave completed checkpoints available for the next refresh. A pass that observes a changed repository never reports a complete result. Deleted records are pruned only after a stable complete pass. Cache recovery/write notices are presented separately from authentication/operation failures.

The existing catalog is totp-catalog.toml beside the private configuration in Android's noBackupFilesDir/ironstorage, preserved by normal install-over updates. The versioned store identity prevents another repository from using it. Each record contains only canonical entry path, SHA-256 ciphertext hash, and is_totp. Passwords, OTP URI/secret, issuer/account, codes, passphrases and keys are absent. The file uses private permissions and atomic writes and is excluded from backup and device transfer. Android bindings are built without the Watch feature, so there are no Watch selection/status fields or controls.

Verification covers real encrypted cold/warm scans, locked zero-decrypt refresh, changed/add/remove records, cancellation/resume without early deletion pruning, concurrent ciphertext changes, damaged/wrong-store catalogs, relocation/update retention, and storage-owned search across 1,000 cached entries. Android native instrumentation additionally exercises latest-query-wins, recovery, typed progress and reconstruction of the Rust/private-session owner while retaining the catalog. Compose tests cover the displayed phase/counts, query control, determinate progress and cancellation/resume message. Discovery remains busy through the subsequent row reload, so observers cannot see an idle state with the old catalog rows.

On 2026-10-12 the required Rust gates passed, including 519 workspace tests. Android verification passed for debug/release, both ARM ABIs, Lint, KtLint, manifest/backup rules, native alignment/debug symbols and dependency/license/SBOM audits. Full app, core and bridge instrumentation plus five cold starts passed on API 26 ARM64/4 KB, API 37 ARM64/4 KB and API 37 ARM64/strict 16 KB.

Computer use verified locked catalog opening, explicit warm refresh with all records reported as cache hits, typed counts/determinate completion, a nonmatching query, and catalog retention after install-over/process recreation. The retained public fixture on the strict 16 KB emulator also displayed its TOTP row in portrait and adaptive landscape; warm refresh reported four inspected records, four cache hits, one match and zero unavailable records without authentication. Authenticated cold/recovery/cancellation paths use real encrypted public fixtures in native instrumentation. The opt-in retained fixture helper checks its exact public key fingerprint and reuses an existing current TOTP record without replacing it. No emulator data or enrollment was reset. ARMv7 is package-audited; its runtime and physical devices are outside the available emulator evidence.