peach-android

@june

A free, open source, local-first password manager for Android.

Kotlin

v2.17.43 · 814 saves · 50,983 lines · updated 3 weeks ago

488 files
9cebcd3b8029
back to HEAD
app/5.6 MB · 1 month ago
drafts/221.1 KB · 4 months ago
C1/11.5 KB · 4 months ago
C7/17.6 KB · 4 months ago
MF1MF2/177.5 KB · 4 months ago
BROWSER-SPEC.mdExtracted from peach-browser source (read-only; never modified).26.8 KB · 4 months agoExportRoundTripTest.kt2.6 KB · 4 months agogen_peach_fixture.mjs1.9 KB · 4 months agoImportParsersTest.kt2.5 KB · 4 months agoImportScreen.kt───────────────────────────────────────────────────────────────────────────── ViewModel ─────────────────────────────────────────────────────────────────────────────26.0 KB · 4 months agomf1_kat_gen.mjsGenerates an MF-1 known-answer vector using the BROWSER's exact recovery algorithm (recovery-words.ts) against the REAL browser word list.4.1 KB · 4 months agoparse_android_export.mjs1011 B · 4 months agoPeachPayloadCodec.ktPeachScript binary payload (PCHS) — a byte-for-byte port of the browser's peachPayload.ts (MF-2).31.5 KB · 4 months agoPeachScript.ktPeachScript outer codec — maps each payload byte to one Private-Use-Area code point in U+E000..U+E0FF, and back.1.9 KB · 4 months agoPeachScriptExport.ktPeachScript export (MF-2) — writes the browser's PCHS binary payload (Argon2id + AES-256-GCM, zstd sections, BLAKE3 checksum, size-bucket padding, string-table entry packing) re-encoded into Private-Use-Area text.1.0 KB · 4 months agoPeachScriptImport.ktPeachScript import (MF-2) — parses the browser's PCHS binary payload back into full vault entries.2.2 KB · 4 months agoPeachScriptTest.kt9.9 KB · 4 months agoRecoveryEscrowTest.kt10.0 KB · 4 months agoRecoveryWords.kt6.0 KB · 4 months agoVaultCrypto.kt4.5 KB · 4 months agoVaultRepository.kt38.1 KB · 4 months agoVaultStore.ktOne encrypted slot at rest.7.5 KB · 4 months ago
B2-INTEGRATION.mdDraft implementation of spec B2 (lines 110–163).7.4 KB · 4 months agoC2-INTEGRATION.mdDraft implementation of spec C2 (lines 289–337).7.1 KB · 4 months ago
src/5.4 MB · 1 month ago
androidTest/28.8 KB · 1 month ago
java/28.3 KB · 1 month ago
com/28.3 KB · 1 month ago
peachpasswords/28.3 KB · 1 month ago
autofill/2.0 KB · 2 months ago
codex/3.5 KB · 3 months ago
passkeys/3.0 KB · 2 months ago
qa/13.8 KB · 1 month ago
vault/6.1 KB · 1 month ago
AndroidManifest.xml433 B · 1 month ago
debug/267 B · 3 months ago
res/267 B · 3 months ago
values/267 B · 3 months ago
main/4.6 MB · 1 month ago
java/1.8 MB · 1 month ago
com/1.8 MB · 1 month ago
peachpasswords/1.8 MB · 1 month ago
autofill/111.5 KB · 1 month ago
AssistStructureParser.ktThe autofillable fields discovered in one [AssistStructure], plus the origin Android authenticated for ranking vault entries.13.1 KB · 1 month agoAutofillEnablement.ktWhether Peach is actually the system's autofill service, and the one-time offer to make it so.2.1 KB · 3 months agoAutofillEntryPickerActivity.ktBranded bottom sheet shown when the user taps "Search Peach…"/"Unlock Peach" in the system autofill drop-down.36.3 KB · 1 month agoAutofillIntents.ktPendingIntents the autofill surfaces hand to the framework: a no-op attribution target the inline chip requires, the authentication IntentSender that opens the branded [AutofillEntryPickerActivity], and the "open new entry" launcher that the picker fires when the user taps the "+ Create new entry" affordance.7.9 KB · 2 months agoAutofillNavRepository.ktCarries a one-shot "open the new-entry editor" request from the autofill picker to the nav host.1.5 KB · 3 months agoAutofillNavViewModel.ktThin Compose-friendly wrapper around [AutofillNavRepository] so the NavHost can grab the singleton via hiltViewModel() without reaching for an EntryPoint accessor.499 B · 3 months agoAutofillOrigin.ktOrigin resolution for autofill matching.3.6 KB · 1 month agoAutofillResponseBuilder.ktTurns parsed form fields + vault entries into autofill [Dataset]s — the menu RemoteViews row, the inline keyboard chip, and the actual field values.22.8 KB · 1 month agoAutofillSave.kt3.0 KB · 1 month agoChipMonogramIcon.ktMonogram chip icons for inline autofill suggestions — the same initials and deterministic background as the vault list (titleInitials/titleBackground), rendered once per source and cached.1.7 KB · 2 months agoIdentities.ktSignup identities for the autofill picker (parity gap A4).3.6 KB · 2 months agoPasswordPolicy.ktSite password constraints detected from a password field's HTML attributes (exposed by [android.app.assist.AssistStructure.ViewNode.getHtmlInfo]).3.3 KB · 1 month agoPeachAutofillService.ktSystem autofill provider.12.1 KB · 1 month ago
codex/42.1 KB · 1 month ago
credentials/18.8 KB · 1 month ago
di/948 B · 2 months ago
feedback/3.6 KB · 3 months ago
haptics/3.0 KB · 2 months ago
license/7.2 KB · 3 months ago
passkeys/69.0 KB · 1 month ago
qs/3.1 KB · 4 months ago
shared/5.8 KB · 2 months ago
sync/298.6 KB · 1 month ago
BackgroundSyncCoordinator.ktOwns the "when do we actually start the sync service?" decision for the background-sync preference.1.5 KB · 2 months agoBackgroundSyncPreference.kt1.6 KB · 2 months agoBatteryExemption.ktAsks once to be left out of Doze / App Standby.3.8 KB · 2 months agoBootReceiver.ktRestarts the sync service after a reboot.770 B · 2 months agoCloudRelayDialer.ktOne relayed reconnect session where WE speak first — the mirror of [runCloudRelayResponderSession], and the half Android never had.4.6 KB · 2 months agoCloudRelayReconnectListener.kt32.8 KB · 1 month agoCryptoCompare.ktFixed-format protocol comparisons.539 B · 3 months agoDeviceIdentity.ktThe persisted keys keep their original names on purpose.3.3 KB · 2 months agoDeviceManifestSupport.kt0x03 adds relay routing to each introduced peer edge.11.0 KB · 2 months agoDeviceType.ktWhat kind of device a peer is, on the wire and in the paired-device store.936 B · 3 months agoForegroundSyncCoordinator.kt2.4 KB · 1 month agoLockedSyncSpoolStore.kt8.5 KB · 1 month agoNoiseKK.kt2.3 KB · 3 months agoNoiseNK.kt4.1 KB · 3 months agoPairedDevice.kt584 B · 2 months agoPairedDeviceStore.kt14.5 KB · 1 month agoPairIdentityFrames.ktThe PAIR_IDENTITY frame: who a peer claims to be, exchanged inside the encrypted session once and pinned thereafter.6.0 KB · 2 months agoPairingAuth.kt4.7 KB · 3 months agoPairingFrames.ktLength-delimited frame IO for a pairing/sync connection.7.8 KB · 1 month agoPairingInvitation.kt4.1 KB · 1 month agoPairingSession.ktThe user's SAS decision, handed to the UI and awaited by the live pairing session.721 B · 3 months agoPeachSyncService.ktKeeps this device reachable on its deterministic relay waiter edges and drives its dialer edges.12.4 KB · 1 month agoPeachWebSocket.ktA minimal RFC 6455 server endpoint — just enough of the protocol to talk to a browser extension's new WebSocket(...).7.5 KB · 3 months agoPendingVouchedDeviceStore.kt5.9 KB · 2 months agoRelayAdoptionHost.kt10.1 KB · 1 month agoRelayAdoptionReceiver.ktReceiver half of relay-first vault adoption.17.0 KB · 1 month agoRelaySettingsStore.ktSync is exactly three named choices (docs/sync-lan-retirement.md, mirroring the browser's sync-settings.ts):6.7 KB · 2 months agoRendezvous.kt6.8 KB · 2 months agoRustNoiseNative.ktThin JNI boundary over the canonical Rust snow state machine.3.4 KB · 3 months agoSASDerivation.kt543 B · 3 months agoSyncAlert.kt2.9 KB · 2 months agoSyncAlertStore.kt3.4 KB · 2 months agoSyncCoordinator.ktSync — Phase 2 manifest-diff coordinator.15.1 KB · 1 month agoSyncFrameTransport.ktE7b: split a too-large padded sync frame across multiple Noise transport messages and reassemble it on the other side.7.0 KB · 1 month agoSyncFreshStartResetter.ktClears every piece of state that can make a destroyed vault still look paired.1.9 KB · 2 months agoSyncIdentity.kt4.0 KB · 2 months agoSyncLimits.ktCloudflare Workers caps one WebSocket message at 32 MiB.2.8 KB · 1 month agoSyncMessage.ktSync wire protocol — exact port of the browser SyncMessage union (shared/sync-types.ts).6.0 KB · 1 month agoSyncNotificationPermission.ktA foreground service can keep running after Android notification permission is denied, but its status notification disappears from the drawer.1.3 KB · 2 months agoSyncOutcomeReason.ktWhy a sync attempt ended, in the same vocabulary the browser uses (src/shared/sync-outcome.ts).10.3 KB · 2 months agoSyncOutcomeStore.ktThe single place a sync attempt is allowed to end.3.1 KB · 3 months agoSyncPadding.ktE7: frame padding at the relay boundary.2.7 KB · 3 months agoSyncPeerRole.ktWho speaks first in a relay room.1.1 KB · 2 months agoSyncSession.ktTransport-neutral session consumed by the sync coordinator.439 B · 3 months agoVaultAdopt.ktVault adoption frame protocol — exact port of the browser shared/vault-adopt.ts.31.6 KB · 1 month agoVaultSyncAdapter.ktProduction [SyncVaultAdapter] backing the coordinator with the live [VaultRepository].18.3 KB · 1 month ago
ui/951.3 KB · 1 month ago
codex/44.8 KB · 2 months ago
components/81.9 KB · 1 month ago
BirdAnimation.ktThe three acts of the pairing animation, bound to the audio protocol.5.8 KB · 2 months agoCharEnterText.ktPer-character entrance: each glyph fades in and rises into place with a staggered delay.2.8 KB · 4 months agoCopyButton.ktCopy button with the two-effect copy feedback (spec §4.4): a diagonal sheen sweeps once over ~600ms and an accent drain bar fills 0→100% over 1.4s.3.6 KB · 4 months agoCopyFeedbackOverlay.kt3.2 KB · 3 months agoFaviconInitials.ktFavicons repository for this window; provided by MainActivity and the picker.4.6 KB · 2 months agoFavicons.ktU1: real site favicons, offline-first with a disk cache.7.3 KB · 1 month agoLockRuneString.kt2.4 KB · 4 months agoPairingBirds.ktThe two pairing birds, ported path-for-path from the browser extension's PairDeviceFlow.tsx (a finch and a swallow) rather than redrawn by eye.14.4 KB · 3 months agoPeachEmptyOrEndState.kt2.0 KB · 3 months agoPeachExpandableCard.kt2.7 KB · 3 months agoPeachField.kt3.7 KB · 3 months agoPeachMark.ktThe Peach brand mark — a peach fruit with a single leaf.4.0 KB · 2 months agoPeachSectionHeader.ktQuiet branded section identity used instead of the retired contained top bar.1.8 KB · 2 months agoPeachSegmentedControl.kt5.2 KB · 3 months agoPeachTopBar.kt2.7 KB · 3 months agoQaFlags.ktDebug-only, opt-in escape hatch so automated visual QA (screenshot-based Gate 2 comparisons) can capture screens that are normally FLAG_SECURE-protected.701 B · 2 months agoRuneGridBackground.kt6.4 KB · 3 months agoSecureFlagEffect.ktAcquires a reference-counted secure-window lease while this composable is in the composition — blocking screenshots, screen recording, and the recents thumbnail of screens that display secrets (MN-3: recovery words, export blob, codex generation).1.6 KB · 2 months agoSecureWindowPolicy.ktThe only owner of [WindowManager.LayoutParams.FLAG_SECURE] transitions.2.1 KB · 2 months agoSyncIndicatorDot.ktThe sync indicator light, shared by the vault list and the Sync settings card so the two can never disagree.2.9 KB · 2 months agoTOTPRing.ktA small ring that sweeps once per TOTP period and turns breach-red in the final 5 seconds.2.1 KB · 3 months ago
lock/49.2 KB · 1 month ago
onboarding/18.9 KB · 2 months ago
pairing/79.3 KB · 2 months ago
recovery/19.1 KB · 2 months ago
security/6.6 KB · 4 months ago
settings/147.1 KB · 1 month ago
sync/12.0 KB · 2 months ago
theme/19.1 KB · 2 months ago
updates/21.3 KB · 2 months ago
vault/429.3 KB · 1 month ago
AdditionalUrlsDetail.ktE3 — additional-URL rows for EntryDetailScreen.12.6 KB · 1 month agoAdditionalUrlsEditor.ktHard cap on additional URLs, matching the browser editor.4.0 KB · 2 months agoCardDetailFields.ktD2 — EntryDetail CARD display block.8.6 KB · 4 months agoCardEditFields.ktD2 — EntryEdit CARD field block.4.0 KB · 4 months agoCardFieldUtils.ktShared card formatting/detection helpers for D2 (card type fields).6.2 KB · 4 months agoCsvExport.ktPure-Kotlin CSV serialisation for the C2 Export screen (CSV sub-view).2.2 KB · 4 months agoCsvImport.ktPure-Kotlin CSV / JSON import parsing for the Import screen (spec B2).29.5 KB · 2 months agoDetailTagRow.ktInline tag row for EntryDetailScreen, mirroring the browser EntryView: chips display in place, and the "+" affordance expands a same-surface tag editor.3.1 KB · 2 months agoEditableFieldRow.ktD6 — Inline per-field editing for EntryDetailScreen.14.3 KB · 2 months agoEntryDeckChrome.kt4.8 KB · 2 months agoEntryDetailGenerator.ktD4 drafts — generator access from EntryDetailScreen.7.7 KB · 1 month agoEntryDetailScreen.kt32.5 KB · 2 months agoEntryDetailViewModel.kt14.4 KB · 2 months agoEntryEditScreen.kt25.2 KB · 1 month agoEntryEditViewModel.kt19.0 KB · 1 month agoExportScreen.kt───────────────────────────────────────────────────────────────────────────── Password strength scorer (local, dependency-free) ─────────────────────────────────────────────────────────────────────────────20.0 KB · 2 months agoIdentitySuggestDropdown.ktAnchored suggestion dropdown for identity-style fields (username/email).5.5 KB · 2 months agoImportScreen.kt───────────────────────────────────────────────────────────────────────────── ViewModel ─────────────────────────────────────────────────────────────────────────────40.1 KB · 2 months agoMultiSelectUi.ktD12 multi-select per-row checkbox (spec §9).4.2 KB · 2 months agoNoteHtml.ktNote bodies are authored in the browser's contenteditable, so a synced note arrives as HTML: the extension's sanitizer allow-list (NoteEditor.tsx) is b, strong, i, em, u, s, h2, h3, blockquote, ul, ol, li, br, hr, p — attribute-less — plus the div wrappers Chrome's contenteditable inserts for new lines.11.2 KB · 2 months agoNotesModeScreen.ktE2 — full-screen editor for NOTE-type entries.22.7 KB · 2 months agoNotesModeViewModel.ktBacks [NotesModeScreen].6.7 KB · 2 months agoPasswordHistorySection.ktShared past-password history UI, extracted from EntryEditScreen so both the editor and EntryDetailScreen render the same rows.6.5 KB · 2 months agoPeachField.ktThe Peach text field used across the entry-edit screens: a bare underline (no border box), drawn in t3 and lit to the accent while focused — matching the lock screen's credential inputs.5.4 KB · 2 months agoPeachScriptExport.ktPeachScript export (MF-2) — writes the browser's PCHS binary payload (Argon2id + AES-256-GCM, zstd sections, BLAKE3 checksum, size-bucket padding, string-table entry packing) re-encoded into Private-Use-Area text.1.4 KB · 4 months agoPeachScriptImport.ktPeachScript import (MF-2) — parses the browser's PCHS binary payload back into full vault entries.2.7 KB · 4 months agoRecoveryWordsScreen.kt12.1 KB · 3 months agoRuneResolve.ktWhich leg of the restore animation is running (browser: RestoreSymbols' animating).7.0 KB · 3 months agoTagChipEditor.ktMax tags per entry.7.5 KB · 2 months agoTagListWidgets.ktHorizontally scrollable tag filter strip for VaultListScreen, placed between the search bar and the sort bar.3.6 KB · 2 months agoTotpInlineEdit.ktE6 — TOTP double-tap to edit the 2FA secret, inline in EntryDetailScreen.15.1 KB · 2 months agoTrashScreen.kt9.4 KB · 2 months agoVaultHealthScreen.ktWarm amber used for the "reused" and "weak" advisory buckets.16.5 KB · 2 months agoVaultListScreen.kt33.8 KB · 1 month agoVaultListViewModel.kt9.7 KB · 1 month ago
PeachAppNavHost.kt19.7 KB · 2 months agoPeachNav.ktEvery navigation destination in the app.2.9 KB · 2 months ago
updates/41.2 KB · 1 month ago
vault/293.1 KB · 1 month ago
BrowserSlot.ktReads the browser extension's slot A so Android can restore a vault that was created there — a Codex printed from the extension, most importantly.8.4 KB · 2 months agoCanary.kt325 B · 4 months agoDuressConfig.ktThe action Peach takes when the duress passphrase is entered at the lock screen.3.4 KB · 4 months agoEffShortWordList.ktEFF short word list, published 2016-09-08.7.2 KB · 1 month agoJwkString.ktReads a passkey's privateKeyJwk whether it arrives as a JSON object or a string, and writes it back as an object.2.4 KB · 3 months agoLastViewedEntryStore.ktRemembers the id of the entry the user last opened so a fresh unlock can land straight back on it (matching the extension, which opens the last entry rather than the list).1.7 KB · 4 months agoPasskeyData.kt1.1 KB · 2 months agoPasswordGenerator.ktCryptographically random password generator.2.1 KB · 1 month agoPasswordHistoryItem.ktOne past password kept in [VaultEntry.passwordHistory].758 B · 4 months agoPeachPayloadCodec.ktPeachScript binary payload (PCHS) — a byte-for-byte port of the browser's peachPayload.ts (MF-2).37.2 KB · 1 month agoPeachScript.ktPeachScript outer codec — maps each payload byte to one Private-Use-Area code point in U+E000..U+E0FF, and back.1.9 KB · 4 months agoPinUnlockStore.kt17.0 KB · 1 month agoRecoveryWordList.ktRecovery word list — byte-identical to the browser's src/shared/recovery-word-list.ts: the canonical 2048-word BIP39 English list, 0-indexed, no duplicates.20.6 KB · 3 months agoRecoveryWords.kt6.3 KB · 2 months agoSavedIdentity.kt250 B · 4 months agoSyncEntrySanitizer.ktMN-3 (2026-06-09 audit, reopened 2026-08-03): content sanitization for entries arriving from a sync peer.1.9 KB · 2 months agoTOTPGenerator.ktRFC 6238 TOTP / RFC 4226 HOTP.3.8 KB · 4 months agoVaultCrypto.kt6.4 KB · 3 months agoVaultEntry.kt3.6 KB · 3 months agoVaultHealth.kt8.3 KB · 2 months agoVaultLockTimer.ktIdle auto-lock timer.1.8 KB · 4 months agoVaultRepository.ktLenient parser for the Codex vault-blob wrapper only.141.6 KB · 1 month agoVaultSettings.kt2.2 KB · 1 month agoVaultSnapshot.kt729 B · 2 months agoVaultStore.ktOne encrypted slot at rest.12.4 KB · 1 month ago
widget/2.7 KB · 4 months ago
MainActivity.ktFragmentActivity (not ComponentActivity) so androidx BiometricPrompt can attach.10.3 KB · 1 month agoPeachApplication.kt3.8 KB · 1 month agoPeachIntentRouter.ktLaunch actions the app declares to the system: the three launcher shortcuts in res/xml/shortcuts.xml and the credential-provider unlock entry point in [com.peachpasswords.passkeys.PasskeyUnlockIntent].2.2 KB · 2 months ago
jniLibs/2.1 MB · 1 month ago
arm64-v8a/504.3 KB · 1 month ago
armeabi-v7a/380.0 KB · 1 month ago
x86/635.3 KB · 1 month ago
x86_64/583.0 KB · 1 month ago
res/696.4 KB · 1 month ago
drawable/4.9 KB · 3 months ago
font/649.0 KB · 4 months ago
layout/1.7 KB · 4 months ago
mipmap-anydpi-v26/688 B · 4 months ago
raw/28.0 KB · 2 months ago
values/4.5 KB · 3 months ago
xml/7.5 KB · 1 month ago
AndroidManifest.xml8.8 KB · 1 month ago
test/837.1 KB · 1 month ago
java/834.4 KB · 1 month ago
com/834.4 KB · 1 month ago
peachpasswords/834.4 KB · 1 month ago
autofill/56.9 KB · 1 month ago
AssistStructureNullHintsTest.ktRegression pin for the 2026-08-07 Fold 7 crash loop: Facebook Messenger presented an autofillHints array containing a null entry and classify() dereferenced it, crashing the autofill service on every fill request (One UI then surfaces the repeated "app keeps stopping" dialog).1.0 KB · 2 months agoAssistStructureOtpRegexTest.ktOTP / 2FA field detection.1.9 KB · 2 months agoAutofillBrowserVisibilityTest.kt567 B · 1 month agoAutofillCardTest.kt3.6 KB · 2 months agoAutofillChipBudgetTest.ktChip-slot budget after the v2.14.8 refinement.2.1 KB · 2 months agoAutofillMatchTest.kt5.5 KB · 1 month agoAutofillNavRepositoryTest.ktAutofillNavRepository carries the one-shot "open the new-entry editor" request from the autofill picker through MainActivity to PeachAppNavHost.2.3 KB · 2 months agoAutofillNewEntryTokenTest.ktF3: the picker→MainActivity new-entry handoff is authenticated with a one-time in-memory token.1.5 KB · 2 months agoAutofillOriginReleaseTest.kt1.1 KB · 1 month agoAutofillPickerSearchTest.kt4.8 KB · 2 months agoAutofillPickerSpecSelectionTest.ktWhich inline spec hosts the "Search Peach…" chip.2.0 KB · 2 months agoAutofillPreviewLabelsTest.kt9.0 KB · 2 months agoAutofillSaveTest.kt3.6 KB · 1 month agoAutofillTwoFactorChipLabelTest.ktConfirms the keyboard-row chip carries WHAT it will fill.2.6 KB · 2 months agoIdentitiesTest.kt4.9 KB · 2 months agoOtpDatasetTest.ktE2-fix verification: the 2FA chip and the LOGIN chip are SEPARATE datasets so the user can verify the TOTP code before it lands.3.6 KB · 2 months agoOtpDigitsTest.kt1.6 KB · 2 months agoPasswordPolicyTest.kt2.9 KB · 1 month agoPeachAutofillLoggingTest.kt641 B · 1 month agoRememberOfferTest.kt1.5 KB · 2 months ago
backup/1.9 KB · 1 month ago
codex/16.3 KB · 1 month ago
credentials/5.4 KB · 1 month ago
feedback/1.7 KB · 3 months ago
license/519 B · 4 months ago
passkeys/31.5 KB · 1 month ago
qs/1.2 KB · 4 months ago
security/11.1 KB · 1 month ago
shared/3.0 KB · 4 months ago
sync/316.3 KB · 1 month ago
BackgroundSyncCoordinatorTest.ktThe v2.5.13 gate if (enabled && vault.isUnlocked.value) was wrong: the user almost always enables background sync from Settings while the vault is locked, so the service never started and the device stayed invisible to paired peers.5.7 KB · 2 months agoBackgroundSyncPreferenceTest.kt573 B · 2 months agoC7TransportTest.ktC7 transport tests.9.5 KB · 3 months agoCloudRelayDialerTest.ktPhone-to-phone: the case that had no initiator at all.11.4 KB · 2 months agoCloudRelayReconnectListenerTest.ktEnough of a vault to send SYNC_HELLO; the peer stalls before anything else.17.3 KB · 1 month agoDeviceManifestSupportTest.ktBounds tests for [verifyDeviceManifest].5.4 KB · 2 months agoForegroundSyncCoordinatorTest.kt993 B · 1 month agoLockedSyncSpoolModelTest.kt1.2 KB · 1 month agoNoiseKKTest.kt6.8 KB · 1 month agoPairedDeviceAliasTest.kt1.2 KB · 2 months agoPairedDeviceRevocationTest.kt3.5 KB · 1 month agoPairIdentityFramesTest.ktRegression coverage for M-08: the hand-rolled PAIR_IDENTITY encoder escaped ", \, and control bytes; the parser stopped at the next unescaped quote and never unescaped.3.2 KB · 2 months agoPairingAuthTest.kt3.8 KB · 3 months agoPairingInvitationTest.kt3.8 KB · 1 month agoPairingRelayLimitsTest.ktPB-26-205 (Android mirror): the pairing/adoption relay inbox is bounded before any allocate/copy of attacker-controlled frame data, with the same ceilings as the browser (src/shared/pairing-dial.ts).4.7 KB · 1 month agoPeachWebSocketTest.ktExercises the server against OkHttp's RFC 6455 client rather than a hand-rolled one.5.7 KB · 3 months agoRegistryTransactionTest.ktPure failure-injection coverage for the real SharedPreferences transaction helper.1.2 KB · 2 months agoRelayAdoptionHostTest.kt16.4 KB · 1 month agoRelayAdoptionInitiatorSourceTest.ktSource-initiator counterpart to [RelayAdoptionHostTest]: the phone dials the relay room, runs Noise as initiator, and sends the grant to the (empty) responder.19.8 KB · 1 month agoRelayAdoptionReceiverTest.ktItem 2 (REVIEW_DEFERRED_ITEMS_BRIEF.md): receiver inline-snapshot happy-path.33.4 KB · 1 month agoRelayGateTest.ktThe fail-closed relay gate, mirroring the browser's sync-settings.test.ts.3.5 KB · 3 months agoRelaySettingsPropagationTest.ktWhat a relay change does to the existing mesh, mirroring the browser's setSyncMode / setRelayUrl.3.0 KB · 2 months agoRendezvousTest.kt4.7 KB · 2 months agoSyncAlertTest.kt3.8 KB · 2 months agoSyncCoordinatorTest.ktTwo in-memory [SyncSession]s wired back to back.19.1 KB · 1 month agoSyncFrameTransportTest.ktE7b end-to-end chunking — the deliverable for the wire shape.6.6 KB · 3 months agoSyncFreshStartResetterTest.kt1.1 KB · 2 months agoSyncNotificationPersistenceTest.kt1013 B · 2 months agoSyncOutcomeTest.ktThe indicator light is the whole point of this vocabulary, so the mapping is swept exhaustively rather than sampled: a reason added later has to be given a place here or the sweep fails.11.0 KB · 2 months agoSyncPaddingTest.kt4.5 KB · 3 months agoSyncServiceStartTest.ktThe service start is the first step of every sync path, and it was the one step that could throw straight out of a button press: Android 12+ refuses a foreground service started from the background, and startForegroundService was called bare.3.4 KB · 1 month agoSyncSuiteTest.ktSync suite (brief Suite 13): length-prefixed pairing frames, SAS derivation KAT, and cross-device entry sync through the [VaultSyncAdapter] (two repositories made to share a sync root key via the Codex blob).9.4 KB · 3 months agoVaultAdoptSnapshotTest.ktInline vault snapshot protocol parity with the browser vault-adopt-snapshot.test.ts.26.7 KB · 1 month agoVaultAdoptTest.ktAdoption frame protocol parity with the browser vault-adopt.test.ts.23.4 KB · 2 months agoVaultSyncAdapterTest.kt32.5 KB · 1 month agoVaultSyncManifestEpochRaceTest.ktRegression for a stale signed manifest mutating only a prefix before relock.7.2 KB · 2 months ago
ui/95.3 KB · 1 month ago
codex/2.9 KB · 4 months ago
components/1.8 KB · 1 month ago
lock/10.0 KB · 1 month ago
onboarding/3.9 KB · 2 months ago
pairing/5.2 KB · 2 months ago
security/3.0 KB · 4 months ago
settings/5.5 KB · 1 month ago
theme/870 B · 3 months ago
vault/56.6 KB · 1 month ago
NavigationFlowTest.ktNavigation suite (brief Suite 9): route construction and the flow-decision functions that route the app — onboarding gate, list-tap, and post-unlock.5.6 KB · 2 months ago
updates/15.5 KB · 1 month ago
vault/265.4 KB · 1 month ago
AdoptDuressSlotTest.ktAdoption duress slot install tests.9.3 KB · 2 months agoBitwardenPasskeyImportTest.kt4.6 KB · 2 months agoBrowserPasskeyJwkTest.ktA passkey's privateKeyJwk is a JSON OBJECT in the browser (JsonWebKey in shared/types.ts); Android holds it as a compact string.2.9 KB · 3 months agoBrowserSlotTest.ktPins the browser→Android slot-A translation that Codex restore depends on.4.8 KB · 3 months agoCardSerializationTest.ktIn-memory [VaultStorage] for exercising last4 derivation on save (MF-3).3.4 KB · 4 months agoCodexRestoreAtomicityTest.ktC-01: a Codex restore must not touch the device's vault until the candidate has been decrypted and decoded in memory, and must roll back if any write in the commit fails.9.6 KB · 2 months agoCrossPlatformRecoveryWordsTest.ktRecovery words are only a human-readable encoding of the root key's first 16 bytes, so the two platforms MUST agree on the word list byte for byte.2.8 KB · 3 months agoCxfImportTest.ktCXF (FIDO Alliance Credential Exchange Format) passkey import.5.6 KB · 2 months agoDuressCodexRoundTripTest.ktEnd-to-end Codex round-trip tests for the duress (slot B / decoy) slot.10.7 KB · 2 months agoDuressSlotBTest.ktIn-memory [VaultStorage] including a decoy (slot B) slot, for the MF-6 duress model.13.5 KB · 2 months agoHiddenSessionStateTest.ktM-04: no operation may leave in-memory session state that disagrees with what is on disk, and the sync-key accessors must fail closed whenever the session is not a fully-unlocked real vault.12.9 KB · 2 months agoLockRaceAtomicityTest.ktH-03: lock() and requireUnlocked() must serialize with in-flight state mutations in suspend operations.7.5 KB · 2 months agoOfficialCryptoVectorsTest.kt2.8 KB · 3 months agoPasskeyConsolidationTest.kt4.7 KB · 2 months agoPasskeyEntryTest.kt1.1 KB · 4 months agoPasswordGeneratorTest.kt2.3 KB · 1 month agoPasswordRotationAtomicityTest.ktH-01: a wrapping-key rotation (changePassword / resetPasswordWithRecoveryWords) must either fully commit slot A + size-matched noise slot B + version stamp or leave the at-rest state untouched.7.8 KB · 2 months agoPeachScriptHardeningTest.ktM-02 regression tests: PeachScript parser must reject attacker-controlled lengths/counts before any unbounded allocation.7.7 KB · 2 months agoPeachScriptRoundTripTest.ktPeachScript + CSV round-trip suite (brief Suite 7): large-vault fidelity, ciphertext tamper detection, size-bucket padding, and CSV column/injection behavior.6.5 KB · 4 months agoPeachScriptTest.kt11.7 KB · 1 month agoPinUnlockStoreTest.kt1.5 KB · 1 month agoRecoveryEscrowIntegrationTest.ktIntegration coverage for the full create → confirm → seal → unlock recovery chain (brief Fix 1).4.8 KB · 4 months agoRecoveryEscrowSuiteTest.ktRecoveryEscrow suite (brief Suite 3): word validation/autocomplete, partial and wrong-word failures, missing-escrow handling, recovery-driven password reset, and the duress-mode guard that recovery escrows are never sealed for the decoy.8.2 KB · 3 months agoRecoveryEscrowTest.kt10.6 KB · 2 months agoReplaceEntriesAtomicityTest.ktM-01: import's REPLACE mode must be one all-or-nothing write.3.2 KB · 2 months agoSessionEpochRaceTest.ktDeterministic H-03 races.6.8 KB · 2 months agoSlotAUnlockTest.ktIn-memory [VaultStorage] for the non-committing dual-derivation path (MF-5).4.9 KB · 2 months agoSlotPaddingTest.ktExposes the raw stored slots so the padding lengths (MN-1) can be inspected.6.9 KB · 1 month agoSnapshotRestoreAtomicityTest.ktH-02: a snapshot restore must either fully commit slot A + slot B + version stamp or leave every byte of at-rest state (slot A, slot B, history) untouched.8.1 KB · 2 months agoSyncEntrySanitizerTest.ktMN-3: sync-peer entries are sanitized before merge — mirrors the browser's sanitizeRestoredEntry, with the Android allowance for flat passkey fields.3.5 KB · 2 months agoTOTPGeneratorTest.kt1.3 KB · 4 months agoVaultCryptoKdfTest.ktMF-4: the Argon2id KDF must hash the password's explicit UTF-8 bytes (matching the browser's TextEncoder().encode), not its UTF-16 code units.1.9 KB · 4 months agoVaultCryptoTest.ktVaultCrypto suite (brief Suite 2): Argon2id key derivation, AES-256-GCM round-trips, AAD enforcement, and KDF parameters.9.1 KB · 3 months agoVaultHealthAdvancedTest.kt5.5 KB · 2 months agoVaultHealthTest.ktVaultHealth suite (brief Suite 8): the pure [VaultHealth.buildReport] scoring — breach / reused / weak / aged / sensitivity detection, section counts, and the sensitivity-weighted vault score.7.5 KB · 4 months agoVaultLockTimerTest.ktIn-memory [VaultStorage] so the timer can drive a real repository off-device.3.9 KB · 4 months agoVaultRepositoryExtraTest.ktSecond VaultRepository suite (brief Suite 1 expansion).17.4 KB · 2 months agoVaultRepositoryTest.ktIn-memory [VaultStorage] so the repository can be exercised without Android.25.6 KB · 1 month agoVaultSettingsDefaultsTest.ktGate for the new-install default.2.3 KB · 1 month ago
widget/761 B · 4 months ago
CrossPlatformKATTest.ktMN-4: cross-platform known-answer tests.8.8 KB · 2 months agoMainActivityTest.kt1.4 KB · 1 month agoPeachIntentRouterTest.kt1.5 KB · 2 months ago
resources/2.6 KB · 1 month ago
fixtures/2.6 KB · 1 month ago
golden/2.6 KB · 1 month ago
build.gradle8.8 KB · 1 month agoproguard-rules.pro329 B · 1 month ago
gradle/73.7 KB · 2 months ago
releases/9.7 KB · 1 month ago
scripts/17.3 KB · 1 month ago
tasks/17.8 KB · 1 month ago
.gitignore99 B · 1 month agobuild.gradle980 B · 1 month agogradle.properties222 B · 4 months agogradlew734 B · 4 months agokepr.build521 B · 2 months agoREADME.mdA free, open source, local-first password manager for Android.2.4 KB · 2 months agosettings.gradle396 B · 4 months agoVERSION7 B · 1 month ago
dfb3e513e48eroute the entry-deck Notes action to the notes table of contents instead of a notes-filtered vault list3 months agodf43a3a2a1bdadd Kepr update check, checksum-verified APK download, install prompt, what's-new screen and Settings About row3 months agob3f592370e5adispatch relay traffic on the sync listener and add the Settings relay toggle, default on3 months agob6208af4fe5eadd RELAY_ frame format and the phone-side relay hub that pairs two links and forwards verbatim3 months ago423c314f718aremove chirp audio pairing, its screen and the mic permission, keeping the transport interface and sync layer3 months ago0e74837151f3add codeless reconnect listener on a fixed port for known peers, advertise it in PAIR_IDENTITY, host it from the sync service3 months agod9f3f7e7ee34add password reveal, move generate into the focused field, render entry chrome actions on every entry, unify top-bar icons to one outlined family, add autofill settings row3 months ago45ee189c2e7eunlock inline in the autofill sheet with biometrics, offer to enable Peach as the autofill service3 months ago8ee5d862e957re-pin golden vector to the browser's 4-byte token, enforce exact token size on encode, note VPNs on the pairing screen3 months ago792a4039d36cexpire the pairing code after five minutes, prefer wlan for the advertised address, offer battery exemption after pairing3 months agoa4e36e3eaef3shorten pairing code to four groups with a 4-byte token3 months ago894f871df762add WebSocket pairing listener, Crockford pairing code, and SAS-gated code pairing screen3 months ago578a68466d1ctranslate browser-shaped slot A on Codex restore, wrap restore-option pills so labels survive narrow widths3 months ago639970cb1815replace hand-drawn pairing birds with the extension's finch and swallow, render SAS inline instead of over them3 months ago8dffe25307efrestore onboarding after vault destroy, add rune glows to panic step 3, add lock FAB above the + FAB3 months ago099f17d7211cstop a real vault's import from hanging the app. Three things were wrong at once on the confirm step:3 months ago3573fda2b97bremove the title-only top bar from the recovery-words screen. It carried no back action and no actions at all — just the words 'recovery words' in a full-width bar above a card whose own headline already says what the screen is, so it was pure vertical cost on a screen that wants the room for a 12-word grid plus three inputs.3 months agof78005e12eb1fix a regression I introduced earlier today: adding the CodexJson parser for the Codex blob fix inserted it BETWEEN the @Singleton annotation and 'class VaultRepository', so the annotation landed on the property and the repository stopped being a singleton. Every injection point then got its own vault — createVault unlocked one instance while the screen observed a different, still-locked one 30ms later (proved by logging System.identityHashCode: 100965910 vs 135655535 in the same process).3 months ago896672fa08f1merge the recovery-words display and confirmation into a single screen (June's call): the 12 words, copy/save actions, and the three position inputs now sit together, so the words can be read straight off the list while typing instead of being hidden behind a second step. Drops the Phase enum, the 5-second countdown, and the separate 'I've saved my recovery words' step.3 months agoc7836f5947eemake Codex and PeachScript import actually work on a real browser-generated vault — three separate bugs, all invisible to the small Android-generated fixtures that previously passed.3 months ago8984cc3fac9ddrop the heart/health icon from the vault list action cluster — it has no counterpart in the browser extension's list chrome. Vault Health itself is untouched and still reachable at Settings > Vault > Advanced Vault Health, so nothing is orphaned; only the list-level shortcut and its onHealth plumbing are gone. Cluster now reads Notes / Select / settings / trash, verified live.3 months agoca118f1d3bc7add a settings cog to the vault list's action cluster, beside the trash icon. With an empty vault the list is the deck root and there is no entry-detail top bar, which is where settings/lock live — so a vault with zero entries had no route to settings at all. Verified on a freshly created empty vault: the cluster now reads Notes / health / Select / settings / trash. Also wire release signing: no signingConfig existed, so assembleRelease produced an unsigned, uninstallable APK. Keystore lives at ~/.peach-release/peach-release.jks with its password in local.properties, which .kohignore already excludes, so the key and password never enter koh history. Release installs as com.peachpasswords, separate from the debug build's com.peachpasswords.debug, so a real vault stays isolated from test data.3 months ago98ecce847507scale the whole UI up on wide screens instead of capping or splitting it (June's pick after the 480dp cap and the two-pane both got rejected): a WideScreenScale wrapper at the app root overrides LocalDensity by width/411dp, clamped to 1.35x, so every dp and sp grows together and the same single-column layout reads as a bigger screen rather than a stretched phone. One wrapper, no per-screen breakpoints to keep in sync, and an exact no-op at or below 411dp so phones are pixel-identical — verified by shooting the vault list at both 686dp and phone width. Ceiling: a uniform scale is not real adaptive layout; a screen that ever wants a genuinely different wide arrangement will need its own breakpoint.3 months agoc8422d123645back out the two-pane list-detail deck — June's call, it looked awful. Kept the harmless modifier params on VaultListScreen/EntryDetailScreen (idiomatic Compose, no behaviour change) and deleted VaultDeck.kt; the EntryDetail route renders EntryDetailScreen directly again, exactly as before. Foldable width remains an open question: the blanket 480dp cap wasted the margins and the two-pane was wrong, so the right answer is neither and needs June's steer before a third attempt.3 months ago7daa1324b93drevert the blanket content-width cap I put in ShellBackground: at 686dp (a foldable's inner screen) it forced every screen into a 480dp column and left ~200dp of dead margin either side, which is worse than the full-bleed it replaced. The cap belongs only on the hero/form screens it was asked for (Lock, Onboarding) — lists and detail views should use a foldable's real width — so CONTENT_MAX_WIDTH now lives as a shared constant applied at those two call sites instead of wrapping every screen.3 months agoc072a6b4976efour onboarding fixes from live review: (1) rune background was frozen solid — it was driven by animateFloat/infiniteRepeatable, which the system animator_duration_scale can zero out, so the ambient field stopped dead wherever that setting is turned down; moved it to the frame clock like the browser's rAF loop and gave each row its own drift speed (8/11/6, RuneBackground.tsx SPEEDS) so the field shears horizontally instead of sliding as one block, verified moving with animator scale still at 0. (2) onboarding cards were vertically centred, leaving dead space above and below on a tall phone — card now sits high with the nav pinned to the bottom, and the card's type/padding scaled up (body 13 to 16sp, vertical padding 28 to 44dp) since it was sized for a 520px browser popup and read as a small box adrift on a 570dp screen; tried the browser's literal flex-1 full-height card first, it looked wrong, reverted to content height. (3) restore chooser was missing Codex — added a third From Peach Codex option handing off to the existing CodexRestoreScreen, which already works pre-vault, and a completed Codex restore now lands in the vault instead of popping back to the chooser underneath it. (4) onboarding's wordmark had lost its peach mark; extracted the mark-plus-text lockup into PeachWordmark and used it on both Lock and Onboarding, which is where the two copies had drifted apart.3 months ago270e5244bf8fport RestoreSymbols' chaos-snap-bloom sequence to the PeachScript import (new RuneResolve.kt, wired into ImportScreen's Working and Done states): glyphs drift while the backup decrypts, snap into the 8x6 grid over 400ms once it lands, then dissolve as the peach mark blooms over 900ms before the result count shows. Source read correction: the browser's symbols restore tab is PeachScript (the rune glyphs), NOT a recovery-words restore as ONBOARDING_ADDENDUM_2 guessed, so Android's existing PeachScript/CSV/Codex tabs already cover all three browser tabs and only this animation was missing. Caught a hang in live testing where SNAP never advanced because onFinished only fired for BLOOM; now every timed phase reports completion. Live-verified end to end on a real .peach restore into a fresh install: chaos frame, grid-snap frame, and settling on 6 entries imported.3 months ago789289291437add the four create-vault pieces missing vs Lock.tsx: blocker message on the submit button (reuses the existing createValidationError, suppressed while the field is empty) so a disabled button explains itself instead of silently doing nothing; show/hide reveal toggle via a new masked param on UnderlineField; static At-least-12-characters hint that the strength bar replaces once typing starts; and back-to-onboarding by keeping Onboarding on the nav backstack (system back gesture, no custom button) with the four post-vault escape points switched from popUpTo(Lock) to the popUpTo(0) pattern already used by the panic route, so a returning user with no Onboarding entry still clears correctly. Live-verified all three blocker states, reveal toggle, hint-to-strength swap, back-to-card-3, and full create to recovery-words to vault-list with the pre-vault stack cleared.3 months ago7e62540bd7b5fix onboarding's 3-card intro against the real browser source (ONBOARDING_ADDENDUM.md), correcting a prior pass's guesses: (1) moved the warning from card 3 to card 2 where it actually belongs, card 3 has none in source; (2) added card 3's missing restore-from-backup choice row, wired to the existing Import screen (I already have Peach/adopt intentionally not shown yet, its real semantics aren't confirmed on the Android side per addendum §4/task #36); (3) fixed the rune background from a guessed two-layer 8.5%/13.5% parallax to the real single-layer 0.07 opacity; (4) fixed card transition timing to run translateX+alpha in parallel (was sequential, doubling the exit duration) with the real 120ms ease-in exit, 60ms hold, 200ms ease-out-expo enter, matching CARD_EXIT_MS/CARD_ENTER_GAP_MS exactly; (5) made the whole card tappable to advance, not just the next button; (6) fixed nav button labels/glyphs to the real '← back'/'next →'/'create vault' (was 'back'/'next'/'Get started', lowercase to match the app's own established convention verified against LockScreen's sibling button); (7) fixed a real state-loss bug found during live verification — going to restore-from-backup and back reset onboarding to card 1 because used plain remember instead of rememberSaveable, which doesn't survive the Compose Navigation back-stack entry recreation that a real pushed route (unlike the browser's in-place view swap) causes. Updated OnboardingTest.kt to match. Live-verified every fix on-device: rune background visibly quieter, card-2 warning/card-3-no-warning, whole-card tap-advance, restore-from-backup reaching Import and returning to the correct card, create vault reaching the real create-vault screen.3 months agod8c36c86dde0wide-screen/foldable audit (task 27): found LockScreen and OnboardingScreen's centered glass-panel content stretching edge-to-edge on tablet/foldable widths instead of staying a comfortable card width, confirmed live at an override 1200x1600 wm size — the root Column used only fillMaxSize with no width cap. Fixed both by capping the content Column at widthIn(max = 480.dp), centered in the remaining space via Box alignment; modifier order matters here (widthIn must precede fillMaxWidth in the chain, since fillMaxWidth first would lock min=max to the full available width before the cap could apply). Live-verified at the wide override across all 3 onboarding cards plus the create-vault/lock screen: content now caps and centers correctly instead of stretching full-bleed. Scope note: this fixes the two worst-offending 'hero card' screens: the many other top-bar+scrollable-form screens (Settings, Import, Export, EntryDetail, etc.) share the same unconstrained-fillMaxSize root pattern and would need the same treatment for full tablet/foldable readiness, but that's a much larger sweep across ~15+ files left for a dedicated follow-up rather than folded into this pass.3 months ago6708bbf7f7acrewrite ProCelebration.kt and the settings-deck Pro icon-tap replay to match the browser's actual celebration effects (ProCelebration.tsx + popup.css), replacing two Android-invented effects that didn't exist in the source: full-screen overlay now uses two corner accent blooms + a glow pulse behind PeachMark + staggered wordmark/thankyou fade-in-from-below (was a single centered flat circle + a continuously orbiting 12-dot sparkle ring with no such browser equivalent), and the Pro-icon celebration replay now plays the exact 8-point radial spark burst (alternating sparkle/dot glyphs, individually staggered, matching browser's spark-x/spark-y/spark-delay values) plus a 'thank you ✦' text flash (was a physical shake/bob with no browser equivalent); also fixed the replay's hold duration from 900ms to 3200ms to match browser's PRO_CELEBRATION_THANK_YOU_MS. Live-verified: activated the real test license key, watched the full-screen celebration play through cleanly (no crash), then tapped the Pro card icon and captured the spark glyphs + thank-you text mid-animation via uiautomator dump3 months ago0afcf4f6c6b4fix both Gate 1 findings from the 2026-07-23 material-3 audit of the six shared primitives: bump PeachSegmentedControl's touch target from 34dp to MD3's 48dp minimum; route PeachTopBar/PeachField/PeachExpandableCard/PeachSegmentedControl through MaterialTheme.colorScheme for every role PeachTheme already maps 1:1 to the same peachColors value (surface, onSurface, surfaceVariant, outline, onPrimary), leaving genuinely custom tones (T1/T2/T4, SurfaceElevated) on peachColors since MD3 has no equivalent role for them3 months agoaa9cb4d3508cmirror deck-root EntryDetailScreen top bar to the browser's persistent peach-chrome header: leading PeachMark + peach wordmark title (was a lock icon + entry/domain title), actions reordered to Notes, Settings, New entry, Delete, Lock trailing-last (was Lock leading, Add/Settings/Delete trailing); add PeachNav.VaultNotes route (VaultListScreen with startNoteOnly) as the nearest Android equivalent to the browser's dedicated secure-notes overlay for the new Notes action3 months ago501a671f57b5add Amazon passkey-only entry to seedDemo() for import/export round-trip coverage; fix pre-vault PeachScript/CSV restore silently reporting 0 entries imported by having confirmImport create the vault (with a new master password collected in the preview step) before adding entries when unlocked3 months agocc9b66d963a4fix the second, independent bug blocking Codex restore: a malformed regex in VaultRepository.restoreFromCodex - the pattern's trailing wrapper-object close-brace was unescaped (\s*}\s*$ instead of \s*\}\s*$), which Android's on-device regex compiler rejects as a syntax error while the host JVM's regex engine silently tolerates it. This meant restoreFromCodex has likely never worked on a real device regardless of decode success - confirmed via a temporary debug log showing UnlockResult.Error with the exact 'Syntax error in regexp pattern' exception, and confirmed the existing VaultRepositoryExtraTest covering this path passes on the host JVM (explaining why it was never caught) despite failing identically every time on-device. Escaped the brace. Full end-to-end live verification: generated a fresh Codex PDF from a 5-entry vault (Pro-gated feature, activated with the real license key), saved it, navigated to Restore from Codex, imported the exact same file - 76/76 codes decoded (building on the fork's earlier vector-rendering fix), entered the master password, tapped restore, relaunched the app fresh, unlocked, and confirmed all 5 original entries present by name (Recovery Notes, Fastmail, Old Bank, Google with TOTP, GitHub). Codex generate+restore is now fully confirmed working, closing out the last unverified vault import/export format.3 months agoc6e41d31ec0aquiet the entry-deck root's top bar to match the browser's minimal persistent header - removed the colored favicon-initials chip (the one loud, saturated element in an otherwise neutral bar, and redundant with the entry's own hero section shown just below it), and unified lock/add/settings icon tint from T0 (full white) to T1 (quiet), matching the delete icon's existing default-state tint so the whole action row reads as one consistent, muted set instead of three bright icons plus one quiet one3 months ago73d0f6503c8afix critical data-loss bug: SAF file pickers silently wiped the vault mid-export/import - ProcessLifecycleOwner.onStop() called vault.lock() (zeroing keys, clearing entryList) whenever the WHOLE PROCESS backgrounds, which fires not just on genuine user backgrounding but also whenever a system Activity (SAF save/open dialog, share sheet) takes foreground as an expected, momentary part of an in-app flow. Result: CSV export always produced a 35-byte header-only file with zero entry rows, silently discarding all vault data, and the app dropped to the lock screen right after - confirmed via temporary logcat instrumentation showing entries.size=0 at buildCsv() time despite 5 real entries existing seconds earlier. Added VaultRepository.expectTransientBackground()/consumeTransientBackgroundSuppression() (a single-use flag) and wired it into PeachApplication's onStop to skip the lock when set. Applied at all 6 external-activity launch sites found across the app: CSV export, PeachScript export, CSV/JSON import picker, recovery-words save-as-text, Codex PDF save, Codex PDF share, and all 3 Codex PDF-restore picker launches. Live-verified the fix end to end: re-ran the exact same CSV export flow, confirmed via logcat entries.size=4 (real count) and isUnlocked=true at export time (previously 0/would-have-locked), pulled the resulting file and confirmed real entry rows (GitHub/Google/Old Bank/Fastmail with real usernames, passwords, urls) instead of just the header, and confirmed the app no longer drops to the lock screen after export.3 months agob2f98db39dabfix task 29: expose username and email as separate fields on entry detail - VaultEntry already had both as distinct optional fields (username, email), but EntryDetailScreen only ever rendered whichever was present and silently dropped the row entirely for a blank one, with no way to add the missing field from the detail screen at all - a real gap vs. the browser, which shows a '+ add username'/'+ add email' link for the missing field. Added per-field show/hide state seeded from whether the entry already has a value, with '+ add username'/'+ add email' links (reusing the existing '+ add another url' link pattern) that reveal an EditableFieldRow with the matching placeholder when tapped. Live-verified on the GitHub demo entry (username only): '+ add email' link appears, tapping it reveals an EMAIL row with 'add email' placeholder ready to edit.3 months ago1476a6674ce6fix task 22: tiny inline save/cancel buttons and password field icon inconsistency - SaveCancelRow rendered '✓ save' / '✗' as 10sp text labels with a few dp of padding, well under the 48dp touch-target minimum and visually inconsistent with every icon button elsewhere on the screen; replaced with two 36dp rounded-square icon buttons (Check/Close) matching CopyButton's exact shape, fill, and size. WrenchButton (password generate) used a bare icon on a plain CircleShape clip with no background fill or press feedback, breaking consistency with the copy button sitting directly next to it; rebuilt to match CopyButton's 36dp/6dp-rounded/filled-background convention. Live-verified all four action buttons (save, cancel, copy, generate) now render at matching sizes with correct content-desc.3 months agob06edcaca0e7begin task 21 motion pass: animate vault list reflow and filter pill selection - LazyColumn entry rows had no animateItem() modifier, so sort changes, deletes, and new entries snapped straight to their new position; added Modifier.animateItem() per row. PeachFilterPills switched between two entirely different composables (bare Text vs Surface-wrapped Text) on selection change with no transition at all - unified into one always-mounted Text with animateColorAsState on background/content color so switching segments now crossfades instead of hard-snapping. Live-verified both: A-Z sort reorders the list and reassigns the accent pill correctly.3 months ago2f7b3c14b0ecrecord handoff summary of this continuation's work in continuity - license activation second bug found and fixed, C1 and C2 fully completed with real bugs found and fixed along the way, launcher icon and peach brand mark fixes, Pro card button clipping fixed, new queue items opened3 months ago6adf086a89eafix Peach Pro card CTA button clipping in the settings deck preview - the Pro card is the tallest in the deck (6 features + price + button + license-key section) and was the only one where the shared expandedH preview budget clipped tight, leaving the Get Peach Pro button flush against the fanned tab beneath it with no visible margin. Added an optional per-row verticalPadding param to the shared RowLine helper (default unchanged at 9dp, so no other card's spacing shifted), used 6dp for Pro's 6 feature rows specifically, and increased the trailing spacer after the button from a first attempt at 28dp (still let the LICENSE KEY label peek through, per live feedback) to 44dp - confirmed clean on a freshly created non-Pro vault with real margin between the button and the tab below and no license-key label bleed-through.3 months ago8ec8a51c5f29eliminate the real remaining settings-card gesture flicker and fix launcher icon safe-zone/background - root cause (found by a dedicated investigation pass) was two independent gesture recognizers on the same focused card fighting over one touch stream: the outer tab-level detectDragGestures was still attached to the active card too, keyed on deckOpen/isActive, which the nested-scroll actions mutate mid-drag - the instant collapse fired, that pointerInput's key changed, cancelling and restarting the coroutine with the finger still down, letting it independently resolve the same physical gesture a second time. Fixed by restricting the outer detector to non-active tabs only (the active card's own nested scroll connection now owns 100% of its gesture) and moving both actions to resolve once on release (onPreFling) instead of continuously mid-drag, matching the app's existing resolveStackDrag on-release convention. Also restricted the expand trigger to upward drags only (previously any direction) after live testing showed repeated downward 'scroll to top' attempts right after a collapse would immediately re-satisfy an any-direction check on the now-unfocused preview and flicker back open. Separately: the launcher adaptive-icon background went through two more corrections after the first transparent attempt rendered as an empty black void on this launcher instead of blending with wallpaper (adaptive-icon backgrounds are expected to be opaque) - now filled with the app's own root canvas color (PeachColors.Bg, #0C0A06) instead of the original literal cream or a naive transparent; and the foreground/monochrome peach mark's safe-zone scale was corrected from an initial 0.8 (based on overall bbox, still let the leaf tip clip on circular masks) to 0.6 after computing the leaf's true radial distance from center (~126 of 240 viewport units, not just its bbox extent). All live-verified on-device: full expand/collapse/re-expand cycle clean with no flicker, repeated downward drag after collapse no longer reopens, launcher icon shows the complete un-cropped peach on a color-filled background in the app drawer dock.3 months ago55352aec7f22fix settings card two-way scroll gesture thrashing and bare launcher icon - expanding the nested scroll connection to also handle collapsed-card-scroll-expands (per direct spec: any scroll on a collapsed card expands it) caused a real regression: collapsing a card flips focused=false mid-drag, which for the same still-moving finger immediately satisfied the expand branch, thrashing collapse/expand back and forth every ~15ms (confirmed via temporary logcat instrumentation). Fixed with a latch that allows only one action per physical touch, unlatching on onPreFling (finger lift) rather than on state change; also moved focused/active off the remember() key list and onto rememberUpdatedState so the connection object (and its latch) survives the very recomposition its own actions trigger. Separately, ic_launcher_background.xml was a solid cream rectangle (#FFF4E9D2) that adaptive-icon masking renders as a visible colored circle behind the peach mark on the home screen and app drawer - made transparent for a bare-icon look, confirmed on-device in the app drawer dock.3 months agoa4ab61925a3efix settings card collapse gesture and vault list peach mark - C2's drag-to-collapse never fired because the focused card's own verticalScroll consumed all drag touches before the outer raw detectDragGestures on the card container ever saw them; replaced with a NestedScrollConnection on the scrollable body that watches for leftover downward drag once scrollState is already at 0, accumulates past a 60dp threshold, then hands off to the deck's collapse callback - same physical metaphor as a bottom sheet; also added trailing bottom spacer inside each card's scrollable body so bottom-of-card content (Pro card's CTA button) doesn't sit flush against the fanned tab stacked beneath it; and added the missing peach brand mark icon (PeachMark) next to the vault list's top bar wordmark, matching the browser header - live-verified card focus/collapse cycle and the peach icon on-device3 months ago560cbfdb55f0add horizontal swipe between deck entries and vertical slide-down-to-collapse on the vault list search bar, completing the entry-deck/vault-list symbiotic relationship - swipe left/right on EntryDetailScreen resolves via vm.adjacentDestination on drag end (120px threshold, mirrors the existing tap-arrow logic); VaultListScreen gains an optional onBack wired only when it was pushed on top of an entry (previousBackStackEntry != null), with a drag-down gesture on its search bar popping back to that exact entry, symmetric with the existing slide-up-to-open gesture; live-verified all four gestures on-device with a fresh seeded test vault3 months ago6e842eac315efix license verifySignature to use Bouncy Castle Ed25519 instead of java.security KeyFactory/Signature - the JCA 'Ed25519' algorithm name routes to AndroidKeyStore's provider on-device, which only accepts KeyGenParameterSpec-generated keys and throws InvalidKeySpecException on any imported public key, silently swallowed to false; confirmed root cause via instrumented on-device test capturing the real exception, confirmed fix with the real test key validating true on-device3 months agoaea3a3106d8erecord comprehensive handoff summary of this entire corrections pass in continuity - what's fixed/verified, what's partially done, what's not started, and the operating lesson about not declaring confidence prematurely3 months ago9037428d5317fix real license activation bug: SettingsCardBodies.kt's license key input forced .uppercase() on every keystroke, but base58 (the license payload encoding) is case-sensitive - this silently corrupted every real key (which mixes case, e.g. '6dC8sBJ5...') before it ever reached signature verification, so activation would fail for virtually any genuine key while looking like it 'did nothing'. Removed the uppercase transform. Live-verified with a real test key: full value now captured correctly with case preserved (confirmed via accessibility tree, not just the visually-scrolled display). Activation still reported 'invalid' for this specific test key - could not independently confirm whether that's the key's own provenance or a remaining issue, but the confirmed uppercase-corruption bug is real and fixed regardless3 months ago502ba3b1ec00fix the real C2 dead-space root cause: settingsDeckHeight() capped the whole deck at a fixed 462dp ported verbatim from the browser's small popup (StackDeck.tsx), and separately EXPANDED_H (258dp) capped the deckOpen picker view's active-card preview height the same way - together stranding roughly a third of the screen as dead space and hiding most of each card's content (Pro card's full 6-item feature list + price + CTA button were invisible below the fold). Made both dynamic: settingsDeckHeight now fills available height up to a much larger bound, and expandedH is computed so the active preview + all 6 fanned tabs together exactly fill the deck height, floored at the original browser-derived minimum. Live-verified: Pro card now shows its entire content (Peach Sync/Codex/Passkeys/Vault Health/Canary/Duress list, price, Get Peach Pro button) that was previously cut off. Also converted the deck's drag-to-focus/collapse motion from a tween-styled-as-spring to real spring() physics (matching PeachExpandableCard), and removed the invented 'end of card' marker from every settings card per the same no-invented-end-markers pattern as C7 and vault list's 'all caught up'. Updated SettingsStackTest's height assertions to match the new intended behavior3 months ago

← newerolder →

details

Peach for Android

A free, open source, local-first password manager for Android.

No accounts. No subscription. Your passwords stay on the device, encrypted with AES-256-GCM and protected by Argon2id key derivation. Sync, backup, and autofill happen without trusting any cloud in the middle.

peachpasswords.com


Features

  • Zero-knowledge vault — AES-256-GCM encryption, Argon2id KDF, keys never leave your device
  • End-to-end encrypted sync — pairs with your other Peach devices over a Noise channel; the relay only forwards ciphertext it cannot read
  • Inline autofill — fills directly in apps, no copy-paste detour
  • Passkeys — WebAuthn credentials alongside your passwords
  • Quick Settings tile — copy a credential from anywhere with a single tap
  • Biometric unlock — hardware-backed AndroidKeyStore escrow, invalidated on enrollment change
  • Codex — prints your encrypted vault as Aztec codes on paper. Physical offline backup

Open Source

Peach is free and open source under the GPL v3 license. Both the browser extension and the Android app.

The source is hosted on Kepr — Asha Software's own version control platform.


Security

Peach has undergone two adversarial analysis sessions against this codebase. The most recent findings have been resolved.

Cryptographic primitives:

  • Key derivation: Argon2id (m=64MiB, t=3, p=4)
  • Encryption: AES-256-GCM with fresh random nonces
  • Sync handshake: Noise NK / Noise KK (25519, ChaChaPoly, BLAKE2s)
  • Backup codec: GF(2⁸) Reed-Solomon with zstd compression
  • BLAKE3 checksums throughout

The canonical Noise core lives in a shared Rust crate with the browser extension — Android drives it via JNI. See docs/CRYPTOGRAPHIC-TEST-VECTORS.md for the byte-level vectors that pin each primitive.


Building

./gradlew assembleRelease

Outputs to app/build/outputs/apk/release/. The shared Noise core is built from ../peach-browser/crypto-core.


License

GPL v3 — see LICENSE.


Peach Pro

Pro features (end-to-end encrypted sync, Codex, Canary) are available for $39 one-time at peachpasswords.com. Purchasing Pro supports continued development.


Built by Asha Software · [email protected]