Current release target: Keysoft 3.0.2, Android versionCode 126 through EAS remote auto-increment. iOS remains a cloud-simulator compatibility target and is not an App Store release target.
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.bunx expo export --platform ios --output-dir C:\tmp\keysoft-ios-exportpasses.- Architecture and i18n regression tests are included in the passing test run.
- Android permissions match
app.config.jsand native Android configuration. - The generated release build uses
proguard-android-optimize.txt,minifyEnabled true,shrinkResources true, andandroid.r8.optimizedResourceShrinking=true. - The generated release build still includes the Argon2 keep rules required by native password login.
- 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. - The in-app and public Mikesoft Keysoft policies show the same fixed effective date, dedicated
keysoft@mikesoft.itcontact, implemented permissions/features, Android release status, and iOS simulator-only boundary. - The visible compact Settings layout exposes shared Mikesoft Support, Privacy Policy, Open source and legal, and GitHub Sponsors; an entry present only in the hidden legacy layout does not satisfy this check.
- Launcher, Android adaptive, splash, web favicon, and onboarding all use the original Keysoft shield-and-eye artwork; no obsolete alternate logo is packaged.
- Verify Settings > Open source and legal while offline: it identifies Keysoft as Apache-2.0 and displays the complete bundled license. Confirm source, notices, and trademark links.
- Validate password login, iPad split view, Dynamic Type, VoiceOver, backup import/export, and auto-lock in the iOS cloud simulator. Face ID and other hardware-backed behavior remain outside simulator coverage.
- 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 3.0.2 release, app.config.js uses version: "3.0.2", android.versionCode: 126, and an iOS simulator baseline of ios.buildNumber: "1". The Android EAS production profile uses the remote version source. Its baseline is set to 125 before the production workflow so autoIncrement produces store build 126. The aligned local value remains visible through expo-constants but does not control EAS production builds. Because EAS Update uses the appVersion runtime policy, 3.0.2 has a distinct native runtime.
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 Android workflow runs for a matching version tag or manual dispatch. It uploads the project to Expo and therefore requires explicit approval before it is run.
Run the local JavaScript bundle check before using EAS:
bunx expo export --platform ios --output-dir C:\tmp\keysoft-ios-exportFor browser-based simulator validation without paid Apple enrollment, follow iOS Testing Without Apple Hardware. After explicit approval for the external upload, create the simulator artifact with:
bun run build:ios:simulatorThe artifact can then be tested in Appetize. App Store signing, submission metadata, and publication are intentionally outside the release workflow.
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.
expo-build-properties enables release minification and resource shrinking. plugins/withAndroidReleaseOptimization.js then selects proguard-android-optimize.txt and enables the optimized resource shrinker available in AGP 8.12. Do not force AGP 9 independently of Expo and React Native; upgrade it only through a supported Expo SDK toolchain.
The Google Play edge-to-edge and bitmap recommendations are dependency-level static findings in the current React Native/Fresco/Glide binary. Keysoft already avoids status/navigation bar color setters on Android 15+, uses safe-area layouts, and does not download profile images from the network. Reassess these findings after supported Expo/React Native upgrades, but do not fork native dependencies or add another image loader solely to hide a scanner recommendation.
For release validation, generate Android native files in a temporary copy and confirm:
android/app/build.gradleselectsproguard-android-optimize.txt.- Release minification and resource shrinking are enabled.
android/gradle.propertiescontainsandroid.r8.optimizedResourceShrinking=trueonce.android/app/proguard-rules.proretains the Argon2 package rules.- The EAS build produces
mapping.txtand completes native PIN login in an internal-test installation.
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 history, alerts, destructive confirmations, loading dialogs, bottom sheets, and toasts. Confirm a dialog opened from a sheet appears above the interface and that canceling restores the expected workflow.
- Confirm loading and confirmation dialog dimming extends beneath the Android navigation bar with no undimmed strip at the bottom of the screen.
- Pick a profile photo, save it, reload the app, lock/log out, and confirm the same avatar is visible on unlock, vault, and settings screens. Canceling profile edits must keep the previously saved image.
- Verify automatic light/dark appearance and responsive layout at compact-phone, tall-phone, landscape/tablet, and narrow split-view sizes without clipped content or full-height compact dialogs.
- Open Vault Health at compact widths and with long translations; confirm the percentage remains inside the summary card and weak, reused, and expired findings match the stored credentials.
- Confirm the original Keysoft shield appears without distortion on onboarding, launcher/adaptive icon, splash, and favicon.
- 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.
- Enable reduced motion and confirm transitions remain usable without relying on animation to convey state.
For significant changes, update:
README.mdCHANGELOG.md- Relevant files under
docs/ AGENTS.mdwhen contributor workflow, release, security, or tooling rules change.