Grapevine_Disease_Detection/VinEye
Yanis 26d0f39986 feat(mobile): backend sync auth + ban handling + scan push
Wires the React Native app to the vineye-admin backend so user accounts
and scans flow into the admin panel, and so a ban applied via the panel
takes effect on the device on the next app boot (or sooner on any
authenticated request).

Core
- Install expo-secure-store for storing the better-auth session token.
  Falls back to AsyncStorage on web/Expo Go where SecureStore is unavailable.
- New tokenStorage service with saveToken/getToken/removeToken and a
  stable per-install getDeviceId() (used to derive the deterministic
  password the backend signs sign-up/sign-in with).
- Extend the API client with apiPost(), automatic Bearer header attach,
  and a tiny pub/sub (authEvents) that emits 'unauthorized' on 401 and
  'banned' on 403 with banned: true. Handlers are global so any request
  can trigger logout or open the BannedModal.

Auth
- New services/api/auth.ts: syncUser (POST /auth/sync), fetchMe (GET
  /auth/me), signOutServer (POST /auth/sign-out, best-effort).
- types/auth.User now carries optional banned/bannedReason/role/xp/level
  hydrated from the backend.
- AuthContext.login is now async vs the backend; the server-side id
  replaces any locally-generated UUID so mobile and admin agree on the
  same User row. Hydration is optimistic from AsyncStorage (never blocks
  the splash on the network) and a background fetchMe picks up server
  ban changes. logout/resetAccount best-effort revoke the server session.
- AuthChoiceScreen surfaces sign-up failures through a toast instead of
  silently dropping the user into the app with no account.

Ban UX
- BannedModal: non-dismissible Tailwind modal with the bannedReason
  interpolated and a CTA that calls resetAccount. Mounted globally in
  RootNavigator and toggled by isBanned from AuthContext.
- Banned state is persisted alongside the User in AsyncStorage so the
  modal stays visible across restarts even when /auth/me is unreachable.

Scan sync
- New services/api/scans.pushScan() that maps the mobile ScanRecord to
  the backend body: confidence /100 (0-100 → 0-1 backend), diseaseSlug
  passthrough (server resolves to diseaseId), latitude/longitude direct,
  imageUrl always null (V1 keeps photos local-only), customName dropped
  (no column server-side, stays in AsyncStorage).
- useHistory.addScan now fires pushScan after the local save and ignores
  failures so the app stays usable offline.

i18n
- New keys auth.errors.network/signupFailed and auth.banned.{title,
  description,descriptionNoReason,cta}. The fr/en files also include
  scanner gallery placeholder keys from an adjacent feature WIP — not
  part of this commit's scope but bundled here to avoid splitting a
  small JSON.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 12:11:11 +02:00
..
.claude chore(ml,android): retire react-native-fast-tflite + nitro, mock JS only 2026-04-30 21:14:38 +02:00
assets feat(mobile): UI overhaul + ML pipeline + Android build fixes 2026-04-30 21:00:03 +02:00
plugins chore(android): propagate CMake fix to native subprojects 2026-05-01 11:30:55 +02:00
src feat(mobile): backend sync auth + ban handling + scan push 2026-05-01 12:11:11 +02:00
.gitignore add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
.npmrc chore(deps,infra): pnpm hoisted mode + dependency cleanup for Map rebuild 2026-04-30 12:31:39 +02:00
app.json feat(scanner,ml): real TFLite inference + preload + flip camera + analyzing skeleton 2026-05-01 11:31:17 +02:00
App.tsx feat(auth): onboarding flow + local auth (no backend) 2026-05-01 09:33:27 +02:00
babel.config.js add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
CLAUDE.md chore(android): propagate CMake fix to native subprojects 2026-05-01 11:30:55 +02:00
components.json add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
global.css add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
index.ts add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
metro.config.js feat(mobile): UI overhaul + ML pipeline + Android build fixes 2026-04-30 21:00:03 +02:00
nativewind-env.d.ts add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
package.json feat(mobile): backend sync auth + ban handling + scan push 2026-05-01 12:11:11 +02:00
pnpm-lock.yaml feat(mobile): backend sync auth + ban handling + scan push 2026-05-01 12:11:11 +02:00
tailwind.config.js add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00
tsconfig.json add VinEye frontend app + fix hardcoded paths + gitignore 2026-04-02 10:30:05 +02:00