cap sync registers @capacitor/preferences for the bundled Capacitor app target. Document the web-SSR vs bundled-app-SPA dual build in reference/recipes.md (BUILD_TARGET/CAP_BUNDLED switch, the app-only fetch interceptor + useAuthSession, the app-auth middleware/endpoints, and the ops gotchas).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add bundled-app deploy & CORS notes (reference/app-spa-deploy.md)
Tailored to the current nginx: the /api Nuxt path needs NO nginx change (location / forwards OPTIONS + headers to Nitro; the app-auth middleware emits CORS + answers preflight). The one required change is Strapi's CORS allow-list (https://localhost) for /media-api uploads. Includes verify curls and the APK ship steps.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump app to 1.0.2 (code 3) for the bundled-SPA release
First release of the bundled (CAP_BUNDLED) app — versionName must increase above the deployed 1.0.1 for the in-app updater to offer it. version.json updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix in-app updater: offer update when installed version can't be read
useAppUpdate fell into `updateAvailable = false` whenever getAppVersion() returned null (older APK without the AppUpdate plugin, or the plugin rejected) — so those devices saw "no update" forever, contradicting the code comment's stated intent. Offer the update in that case instead, and fetch the version manifest with cache: 'no-store'.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unifies the release cycle into one script: bump version (build.gradle + version.json) → npm run build:app → npm run cap:sync:app → gradle assembleDebug → stage into android/update-files/ → hand off to the existing scripts/upload-mobile-update.sh. Auto-bumps the patch (or takes an explicit versionName), with --no-upload to build/stage only. Docs updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hide "Mobile worker" toggle in the native app (always-on there)
In the bundled Capacitor app every user is a mobile worker, so force the flag on (mobileWorker: isNativeApp) and hide the selectable chip. Web sign-in is unchanged. The server enforceMobileWorkerGate stays authoritative.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add biometric login for the native Android app (Phase 1)
Fingerprint/Face login via @capgo/capacitor-native-biometric. After a normal password login the app stores a biometric-bound snapshot (refresh token + context, never the password) in the Android Keystore (getSecureCredentials); on the next visit "Login with fingerprint" unlocks it, mints a fresh access token via the existing /api/app-auth/token-refresh, and signs in — no new server route. App-only: all logic is gated by isNativePlatform and the plugins are dynamically imported, so the web sign-in/build is unchanged (verified). Adds USE_BIOMETRIC/USE_FINGERPRINT to the manifest.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>