Install dependencies:
bun installStart Expo for Expo Go:
bun run startOpen on Android with Expo Go:
bun run androidUse a tunnel when LAN discovery is not reliable:
bun run start:tunnelRun web:
bun run webRun all checks:
bun run typecheck
bun run lint
bun run test
bunx expo-doctorBefore requesting an EAS preview build, also validate the Android bundle export:
bunx expo export --platform android --output-dir C:\tmp\keysoft-android-exportRun only tests:
bun run testRun a focused test file:
bun run test -- src/__tests__/services/CryptoService.test.ts- Use TypeScript strict mode.
- Prefer interfaces for structured data.
- Use functional components and hooks.
- Prefer named exports for services and helpers.
- Keep user-visible strings in the localization dictionaries.
- Do not add fallback UI strings such as
t('key') || 'Fallback'. - Keep business logic in
src/services. - Keep complex screen orchestration in
src/hooks. - Keep feature-specific hooks in lowercase subdirectories, such as
src/hooks/settings. - Keep UI in
src/screensandsrc/components.
All user-visible strings must use t('key').
When adding a new key:
- Add it to the Italian dictionary.
- Add it to the English dictionary.
- Use named parameters for dynamic values.
Example:
t('notification_backup_reminder_body', { daysAgo });The i18n regression test in src/__tests__/i18n verifies:
- Italian and English dictionaries contain the same keys.
- Translation keys are not duplicated.
- Statically referenced
t('key')andthis.t('key')calls exist in both dictionaries. - Interpolation placeholders such as
{count}and{daysAgo}match across languages. - Known user-facing fallback strings do not return as hardcoded UI text.
Names that are not localization content, such as route names, icon names, brand names, email addresses, URLs, and technical labels like AES-256, can remain literal.
Use src/utils/cryptoRandom.ts for randomness.
Do not:
- Persist the encryption key.
- Store plaintext password or note data.
- Log secrets.
- Use
Math.random. - Accept imported backup objects without validation.
| Test type | Location |
|---|---|
| Service unit tests | src/__tests__/services |
| Context tests | src/__tests__/contexts |
| Hook tests | src/__tests__/hooks |
| Integration tests | src/__tests__/integration |
| Architecture tests | src/__tests__/architecture |
| Internationalization tests | src/__tests__/i18n |
| Performance tests | src/__tests__/performance |
| Compatibility tests | src/__tests__/compatibility |
Use Expo tooling for SDK-aligned native dependencies:
bunx expo install --fixThen verify:
bun install
bunx expo-doctorIf expo-doctor reports duplicate native modules after a valid dependency update, regenerate node_modules and reinstall from the lockfile.
Day-to-day development uses Expo Go. Do not use local Gradle builds as the default workflow.
Build artifacts are produced on expo.dev through EAS:
bun run build:android:preview
bun run build:android:productionThe repository is also linked to EAS Build, and the EAS Workflow .eas/workflows/build-android-production.yml can build the Android production app-bundle from GitHub. It is triggered only by a version tag push (v*) or manual dispatch to limit build-credit usage; it does not run on every push. iOS is excluded while paused.
Expo Go cannot load custom native modules. Keysoft therefore uses the PBKDF2 KDF fallback in Expo Go and keeps Argon2 for EAS/native builds where react-native-argon2 is available.
Use Expo Go for development and smoke testing only. Create release-test vaults in an EAS/native build when validating Argon2 behavior. Vault metadata that requires Argon2 (memory > 0) must fail with the native-KDF diagnostic if the native module is unavailable; do not reintroduce PBKDF2 fallback for that path.
The withArgon2ProGuard config plugin patches the native Argon2 dependency during prebuild and appends ProGuard keep rules for release builds, including com.poowf.argon2 for react-native-argon2 v4. When changing the Argon2 dependency or EAS prebuild behavior, verify that the generated Android project still contains those keep rules.
When changing authentication, biometric unlock, KDF behavior, or PIN-change flows, run the focused regression suite before the full checks:
bun run test -- src/__tests__/services/AuthService.test.ts src/__tests__/services/StorageService.test.ts src/__tests__/services/CryptoService.test.ts src/__tests__/integration/Authentication.test.tsx src/__tests__/hooks/usePinManagement.test.tsx src/__tests__/contexts/AuthContext.test.tsx src/__tests__/config/Argon2ProGuard.test.ts --runInBandEAS build commands upload the project to expo.dev. Run them only after the release checks pass and the upload has been explicitly approved.
- Icon-only controls must have
accessibilityRole,accessibilityLabel, and a stable hit area. - Interactive targets should be at least 44x44 points.
- Custom modals and bottom sheets must expose modal semantics and keep decorative backdrops inaccessible.
- Category filters and segmented choices should expose selected state.
- User-visible notification content must use localization keys in both Italian and English.
- Do not commit local secrets.
- Do not commit generated temporary extraction folders.
- Keep unrelated worktree changes separate.
- Run
git diff --checkbefore handing off changes.