Current release target: Keysoft 2.2, Android versionCode 120.
Before preparing a release:
bun run typecheckpasses.bun run lintpasses.bun run testpasses.bunx expo-doctorpasses.bunx expo export --platform android --output-dir C:\tmp\keysoft-android-exportpasses.- Architecture and i18n regression tests are included in the passing test run.
- Android permissions match
app.config.jsand native Android configuration. - No local secrets, keystores, certificates, or environment files are staged or tracked.
- Public repository checklist has been reviewed when preparing public GitHub visibility.
- Backup import/export still works with encrypted payloads.
- Biometric login behavior is verified on a physical Android device when possible.
- Privacy text discloses that
INTERNETis used for Expo/EAS updates only, not vault sync. - Pre-build security/UI review is current and all blocking findings are remediated or explicitly accepted.
Application version data is maintained in:
package.jsonapp.config.js- Android native configuration where applicable
For the 2.2 Android production release, app.config.js uses version: "2.2" and android.versionCode: 120.
When changing Android permissions or update behavior, keep app.config.js, EAS profiles, and generated native configuration in sync.
Development uses Expo Go:
bun run androidExpo health check:
bunx expo-doctorBuild artifacts are created on expo.dev through EAS, not through local Gradle:
bun run build:android:preview
bun run build:android:productionThese commands upload the project to expo.dev. Do not start them until the release checklist is complete and the upload has been explicitly approved.
The repository is linked to EAS Build. The EAS Workflow .eas/workflows/build-android-production.yml builds the Android production app-bundle and runs only on a version tag push (v*) or manual dispatch, to keep build-credit usage low. Trigger a release build by pushing the matching tag (for example git tag v2.2 && git push origin v2.2) or by running the workflow from the Expo dashboard. iOS is excluded while paused, so the missing-iOS-credentials warning does not apply; build Android only.
Google Play submission is currently performed manually (upload the app-bundle in the Play Console). To automate it later, configure a Google service-account key in eas.json (submit.production) and run:
bun run submit:android:productionRelease validation for the KDF path must be performed on an EAS/native build. Expo Go uses the PBKDF2 fallback because it cannot load the Argon2 native module.
Before approving a release build that touches KDF or native dependency configuration, confirm the generated Android project includes the Argon2 ProGuard keep rules inserted by plugins/withArgon2ProGuard.js, especially com.poowf.argon2 for react-native-argon2 v4.
Allowed/expected:
INTERNETfor Expo/EAS update delivery only.CAMERAfor camera-based features.POST_NOTIFICATIONSfor Android 13+ local notifications.
Blocked:
READ_MEDIA_IMAGESREAD_MEDIA_VIDEOREAD_MEDIA_AUDIO
Prefer Android Photo Picker or explicit user-selected file access instead of broad media permissions.
Encrypted backups use KS1-PW1. Release testing should cover:
- Export encrypted backup.
- Import encrypted backup with the correct password.
- Reject encrypted backup with the wrong password.
- Reject malformed JSON backup.
- Reject backup objects with invalid password or note shape.
Before release, confirm these invariants:
saveBiometricKeyandgetBiometricKeyare used only for SecureStore-backed biometric unlock and never logged.- Argon2 vault metadata (
memory > 0) fails with an explicit native-KDF error if the native module is unavailable. - Argon2 timeout surfaces as a KDF timeout diagnostic, not as a generic invalid PIN.
- PIN setup and PIN change reuse the key derived while creating the master-key verifier instead of running an extra KDF pass for the same new PIN.
- No
Math.randomusage exists undersrc. - Backup export does not call
Crypto.encrypt(jsonData, exportPassword). - Backup import does not decrypt with
Crypto.decrypt(parsedData.data, importPassword). - Plaintext legacy arrays are re-encrypted when loaded with an active key.
Suggested command:
rg "Math\.random|Crypto\.encrypt\(jsonData|Crypto\.decrypt\(parsedData\.data" srcThe command should return no matches.
Before release, manually smoke test on Expo Go and on the EAS preview build:
- Unlock, auto-lock, logout, cold-start biometric unlock, biometric invalidation fallback, and PIN change after biometrics are enabled.
- Create, edit, delete, search, and copy password records.
- Create, edit, delete, and search secure notes.
- Open and dismiss notification, alert, and bottom-sheet modals.
- Navigate icon-only controls with TalkBack where possible.
- Confirm touch targets remain comfortable on smaller Android screens.
- Switch Italian/English/system language and confirm core notification, alert, and settings labels remain localized.
For significant changes, update:
README.mdCHANGELOG.md- Relevant files under
docs/ AGENTS.mdwhen contributor workflow, release, security, or tooling rules change.