Implement Android TOTP cached discovery and search (#110)
This commit is contained in:
1 parent
0c8366d34f
commit
f4a6edbc68
18 files changed
+1070
-165
No files matched your search
+4
-3
@@ -3,9 +3,10 @@
|
||||
Issue [#107](https://git.rfc1437.de/hugo/IronStorage/issues/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 is an
|
||||
explicit authenticated discovery action; the progress/search workflow belongs
|
||||
to [#110](https://git.rfc1437.de/hugo/IronStorage/issues/110).
|
||||
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](totp-discovery.md) implement
|
||||
[#110](https://git.rfc1437.de/hugo/IronStorage/issues/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
|
||||
|
||||
@@ -30,7 +30,7 @@ Every issue linked here belongs to milestone 23.
|
||||
| Password length/generation and replacement | generate; mobile_entry::MobileEntryDraft::generate_password | Generator controls call Rust | #103; Rust validation and unbiased generated value; no Kotlin generator |
|
||||
| OTP URI input, camera/image import, review before Save (OtpImportViewController; TOTP Add action) | mobile_entry::MobileEntryDraft::add_otp_image; document/otp/presentation | CameraX frames or Android photo picker bytes; Rust decode and field construction | #103/#106/#107; URI/image/scan parity, invalid/oversized input, cancel; no payload parsing in Kotlin |
|
||||
| Move/copy/delete entries and folders, destination browse, overwrite and dirty-editor handling (PasswordMutationCoordinator) | mobile_mutation::MobileMutationService/Plan/Request; mutation | Compose dialogs/destination picker | #108; revisions, destination conflicts, recipient reencryption and rollback |
|
||||
| TOTP discovery catalog, incremental progress, warm cache, refresh, cancel/resume, cached search (TotpListViewController) | mobile_totp discovery/catalog/operation; mobile_authentication cached/search APIs | Compose list/progress/search; private no-backup catalog | #90/#110; cold/warm/change/add/remove/corrupt/wrong-store/concurrent-change tests |
|
||||
| TOTP discovery catalog, incremental progress, warm cache, refresh, cancel/resume, cached search (TotpListViewController) | mobile_totp discovery/catalog/operation; mobile_authentication cached/search APIs | Compose list/progress/search; private no-backup catalog | #90/#110; [discovery behavior and evidence](totp-discovery.md), cold/warm/change/add/remove/corrupt/wrong-store/concurrent-change tests |
|
||||
| TOTP rows, large detail code, countdown/expiry, copying (TotpDetailViewController, TotpCodeView) | mobile_totp::MobileOtpCodePresentation; otp; mobile_authentication::{presented_otp_code,copy_presented_otp_code,advance_presented_hotp} | Compose code/detail; OS clock facts, Rust timing | #107/#100; [OTP behavior and evidence](otp.md), RFC vectors, boundary countdown, stale callback/relock and clipboard |
|
||||
| Repository/server identity, local-only/add-remote Settings, token replace/remove (PreferencesViewController, TokenUpdateViewController) | mobile_authentication::MobilePreferences; mobile_onboarding::replace_configured_application_token; config/secret_store | Compose Settings/facade | #104/#95; no token display; protected replacement/removal and offline operation |
|
||||
| Key identity/fingerprint, GPG recovery import and public/private QR export (KeyImportScannerViewController, KeyExportListViewController, KeyQrExportViewController) | mobile_key_transfer::{MobileKeyTransferService,MobileKeyTransferImport}; crypto/presentation | CameraX Preview/ImageAnalysis; animated Rust-provided matrices | #106/#104; multi-frame order/duplicates/interruption, bounded frames, private export authorization and camera denial |
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user