feat(mobile): identité user-first — login/password, SecureStore, scoping par compte

- api: DeviceRegistration device-only, login/changePassword/resolveUser, interception 401 (purge) exonérée sur le login ; type User aligné sur le fil (is_admin)
- SecureStore (expo-secure-store v57) : token + profil, jamais en SQLite ; miroir active_user_id
- AuthContext : statut loading/signedOut/signedIn, bootstrap register→restore, signIn/signOut, garde-fou switch de compte
- app/login.tsx + gate de routes dans _layout (Redirect signedOut) ; i18n fr/en
- DB v5 : user_id sur pending_operations + resource_permissions (UNIQUE par user), repos scopés (user_id IS ? OR IS NULL)
- syncOutbox : delta permissions par compte (Map), outbox poussée du compte actif uniquement
- tests: register/login/401/resolve/changePassword, scoping outbox+permissions, migrations v5 ; e2e live revert register→login admin
This commit is contained in:
m
2026-09-10 21:34:34 +02:00
parent c2c7dddba6
commit 0536fca6c3
25 changed files with 663 additions and 49 deletions
+7 -1
View File
@@ -1,6 +1,6 @@
export const DATABASE_NAME = 'dot.db';
export const DATABASE_VERSION = 4;
export const DATABASE_VERSION = 5;
export const PREFERENCES_KEY = 'user_preferences';
@@ -8,6 +8,12 @@ export const DEVICE_USER_ID_KEY = 'device_user_id';
export const AUTH_TOKEN_KEY = 'auth_token';
// Miroir non-sensible du compte connecté (voir services/secureStore.ts) : le
// token lui-même reste en SecureStore ; seul l'id du compte actif est répété en
// SQLite pour permettre aux repositories de scoper leurs lectures/écritures
// sans avoir à importer expo-secure-store (tests Node inclus).
export const ACTIVE_USER_ID_KEY = 'active_user_id';
export const FOLDER_COLUMNS = [
'resource_id',
'uri',