@buivietphi/skill-mobile-mt 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  # Prompt Engineering — Intelligent Prompt Generation
2
2
 
3
- > Learned from Anthropic, Cline, Roo Code, and Claude Code.
3
+ > Learned from Anthropic, Cursor, Lovable, Manus, Windsurf, Kiro, Claude Code, and top 50k+ star repos.
4
4
  > How to generate prompts that AI agents execute correctly.
5
5
 
6
6
  ---
@@ -64,40 +64,138 @@
64
64
  ```xml
65
65
  <think>
66
66
  BUG: [description]
67
- FILE: [path]
67
+ ERROR MESSAGE: [paste exact error]
68
+
69
+ ⛔ STOP — CLASSIFY + SEARCH PROJECT FIRST (before ANY analysis):
70
+
71
+ <error_classification>
72
+ TYPE: [RUNTIME CRASH / BUILD ERROR / TYPE MISMATCH / NETWORK ERROR /
73
+ RENDER ERROR / NAVIGATION ERROR / PERFORMANCE / STATE ERROR /
74
+ NATIVE ERROR / MEMORY ERROR / INVESTIGATION]
75
+
76
+ SEARCH STRATEGY based on type:
77
+ → RUNTIME/STATE/RENDER/NAVIGATION → Search src/ FIRST → then trace outward
78
+ → BUILD/NATIVE → Search config files FIRST (tsconfig/gradle/Pod/pubspec)
79
+ → NETWORK/API → Search API service files → then .env → then interceptors
80
+ → INVESTIGATION → Search by feature name → read → report (don't fix yet)
81
+
82
+ If complex bug → Read shared/debugging-intelligence.md for pattern match
83
+ </error_classification>
84
+
85
+ <project_search>
86
+ STEP 1: Extract keywords from error:
87
+ → File/path in stack trace: [extract]
88
+ → Function/class/component name: [extract]
89
+ → Module/package name: [extract]
90
+ → Line number: [extract if available]
91
+ → Error code / HTTP status: [extract if available]
92
+
93
+ STEP 2: Filter noise from log (if user pasted log):
94
+ → SKIP: node_modules/*, React internals, engine frames
95
+ → FOCUS: lines with src/ paths, "Error:", "Caused by:", YOUR component names
96
+
97
+ STEP 3: Search project source code (MANDATORY):
98
+ → Grep "[keyword]" src/ ← ALWAYS start here (unless BUILD error)
99
+ → Grep "[function_name]" src/ ← find the actual function
100
+ → Glob "**/*[ComponentName]*" ← find the actual file
101
+ → Results: [list files found]
102
+
103
+ STEP 4: Read matched files (TOP 3-5):
104
+ → Read [file1] — [what I found: actual code, types, imports]
105
+ → Read [file2] — [what I found: related logic, callers]
106
+ → Read [file3] — [what I found: state/store connected to this]
107
+
108
+ ⛔ If I skipped Step 1-4 → GO BACK AND DO THEM NOW
109
+ ⛔ If I found 0 results in src/ → widen: lib/ → app/ → project root
110
+ </project_search>
68
111
 
69
112
  <source_verification>
70
- ⚠️ BEFORE analyzing verify I have real data:
71
- - [ ] Read the actual file (not guessing from error message)
72
- - [ ] Verified function/class names exist (grep)
113
+ ⚠️ Verify I have REAL project data (not assumptions):
114
+ - [ ] Classified error type and picked correct search strategy
115
+ - [ ] Filtered noise from log (if applicable)
116
+ - [ ] Searched src/ with Grep for error keywords → found files
117
+ - [ ] Read the actual file(s) where bug occurs
118
+ - [ ] Verified function/class names exist in project (grep result)
73
119
  - [ ] Checked package versions in package.json/pubspec.yaml
74
120
  - [ ] Identified data types from actual code (not assumed)
121
+ - [ ] Traced the call chain: who calls this → what it returns
75
122
  </source_verification>
76
123
 
77
- <context_needed>
78
- - Read [file] to understand current implementation
79
- - Grep for similar patterns: grep "[pattern]" src/
80
- - Check imports and dependencies
81
- </context_needed>
82
-
83
- <root_cause>
84
- [Analyze AFTER loading context - don't guess]
85
- - What code is executed?
86
- - What values are passed?
87
- - What conditions are checked?
88
- SOURCE: [file:line where the bug is cite exact location]
89
- </root_cause>
124
+ <root_cause_tracing>
125
+ NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
126
+
127
+ STEP 1 IMMEDIATE CAUSE (what throws):
128
+ - Error type: [from classification above]
129
+ - Crash/error at: [file:line from project search]
130
+ - What code does at that line: [describe from reading]
131
+ - What value is wrong: [actual vs expected]
132
+
133
+ STEP 2 TRACE BACKWARD (what called this):
134
+ - Who calls this function? → [grep callers in src/]
135
+ - What data does caller pass? [trace data origin]
136
+ - Go up one level: who calls the caller? → [trace further]
137
+
138
+ STEP 3 — ROOT CAUSE (where chain breaks):
139
+ - Root cause at: [file:line — where correct data becomes incorrect]
140
+ - WHY it fails: [based on actual code read, NOT guess]
141
+ - Does this match a known pattern? → [check debugging-intelligence.md if loaded]
142
+ - Does root cause explain ALL symptoms? YES/NO
143
+ → If NO → theory is wrong → re-trace from Step 2
144
+ </root_cause_tracing>
145
+
146
+ <working_example>
147
+ Search for similar working code in SAME project:
148
+ → Grep for similar pattern that works: [search term]
149
+ → Found working example at: [file:line] (or "none found")
150
+ → Differences between broken vs working:
151
+ 1. [difference]
152
+ 2. [difference]
153
+ → The fix should align broken code with working pattern
154
+ </working_example>
155
+
156
+ <hypothesis>
157
+ ⛔ 1 HYPOTHESIS → 1 MINIMAL CHANGE → VERIFY
158
+
159
+ HYPOTHESIS: [specific theory based on root cause]
160
+ CHANGE: [smallest possible change to test this — 1 change only]
161
+ EXPECTED RESULT: [what should happen if hypothesis is correct]
162
+
163
+ ⛔ If this fails → REVERT → form NEW hypothesis (never stack fixes)
164
+ ⛔ If 3 hypotheses fail → STOP → question architecture
165
+ </hypothesis>
90
166
 
91
167
  <fix>
92
- [Specific change with code snippet]
168
+ [Specific change with code snippet — before → after]
93
169
 
94
170
  WHY IT WORKS:
95
- [Explain the fix based on root cause]
171
+ [Explain based on root cause tracing — not guess]
96
172
  SOURCE: [where this fix pattern comes from — project code / skill file / official docs]
173
+
174
+ DEFENSE IN DEPTH (make bug structurally impossible):
175
+ - Layer 1 (input): [validation added]
176
+ - Layer 2 (state): [guard added]
177
+ - Layer 3 (render): [null check / fallback added]
97
178
  </fix>
98
179
 
180
+ <verification>
181
+ ⛔ NO COMPLETION CLAIMS WITHOUT EVIDENCE
182
+
183
+ 🚩 Anti-rationalization check:
184
+ - Am I saying "should work now" without running it? → RUN IT
185
+ - Am I "confident" without evidence? → PROVE IT
186
+ - Am I stacking 3+ changes? → REVERT. 1 change only.
187
+
188
+ Evidence:
189
+ - [ ] Fix addresses root cause (not just symptoms)
190
+ - [ ] All symptoms explained by this root cause
191
+ - [ ] Working example pattern followed (if found)
192
+ - [ ] Defense-in-depth added at [N] layers
193
+ - [ ] Side effects checked (grep for other callers)
194
+ - [ ] Both platforms considered (iOS + Android)
195
+ </verification>
196
+
99
197
  <side_effects>
100
- - Files that import this: [list after grep]
198
+ - Files that import this: [list from grep results]
101
199
  - Tests affected: [list]
102
200
  - Platform-specific: iOS [impact] / Android [impact]
103
201
  </side_effects>
@@ -116,6 +214,64 @@ FILE: [path]
116
214
  </think>
117
215
  ```
118
216
 
217
+ ### Diagnostic Scan (user unsure / vague / "check this for me")
218
+
219
+ ```xml
220
+ <think>
221
+ USER SAID: [what user described or asked — could be vague]
222
+ AREA: [extract: screen name / feature name / module name / file name]
223
+
224
+ <area_identification>
225
+ What did user mention or show?
226
+ → Screen/feature name: [extract from user's words]
227
+ → File pasted/referenced: [if any]
228
+ → Behavior described: [if any]
229
+ → If unclear → I should ask: "Which screen or feature should I check?"
230
+ </area_identification>
231
+
232
+ <project_search>
233
+ Search broadly for this area:
234
+ → Grep "[feature]" src/ → found: [list files]
235
+ → Glob "**/*[ScreenName]*" → found: [list files]
236
+ → Also search: related hooks, services, stores, utils
237
+ → Total files to scan: [N files]
238
+ </project_search>
239
+
240
+ <diagnostic_scan>
241
+ For EACH file, run the checklist:
242
+
243
+ FILE: [file1:path]
244
+ □ Crash risks: [findings or "clean"]
245
+ □ Memory leaks: [findings or "clean"]
246
+ □ Race conditions: [findings or "clean"]
247
+ □ Security: [findings or "clean"]
248
+ □ Performance: [findings or "clean"]
249
+ □ UX/states: [findings or "clean"]
250
+ □ Data flow: [trace API → state → render — any break?]
251
+ □ Edge cases: [empty data? error response? offline? slow?]
252
+
253
+ FILE: [file2:path]
254
+ □ ... (repeat for each file)
255
+ </diagnostic_scan>
256
+
257
+ <report>
258
+ Scanned: [N files] in [area name]
259
+
260
+ 🔴 Issues found:
261
+ 1. [SEVERITY] [file:line] — [description]
262
+ 2. [SEVERITY] [file:line] — [description]
263
+
264
+ 🟡 Suspicious (might be intentional):
265
+ 1. [file:line] — [what looks off and why]
266
+
267
+ ✅ Looks good:
268
+ - [aspect that's well-implemented]
269
+
270
+ Recommendation: [what to fix first / what to investigate deeper]
271
+ </report>
272
+ </think>
273
+ ```
274
+
119
275
  **Example:**
120
276
  ```xml
121
277
  <think>
@@ -652,6 +808,101 @@ Faster than reading documentation.
652
808
 
653
809
  ---
654
810
 
811
+ ## Advanced Patterns (from top AI tools)
812
+
813
+ ### Verification-First Pattern (Anthropic #1 recommendation)
814
+
815
+ ```
816
+ ALWAYS provide verification criteria BEFORE implementation:
817
+
818
+ <good-example>
819
+ "Add pagination to ProductList. Verify: loads 20 items, next page
820
+ on scroll to bottom, shows loading spinner during fetch, handles
821
+ empty last page. Run: jest --testPathPattern=ProductList"
822
+ </good-example>
823
+
824
+ <bad-example>
825
+ "Add pagination to ProductList"
826
+ (no way to verify success)
827
+ </bad-example>
828
+
829
+ The single highest-leverage thing: include tests or expected outputs
830
+ so the agent can check itself.
831
+ ```
832
+
833
+ ### Investigate-Before-Answer Pattern (used by Cursor, Lovable)
834
+
835
+ ```
836
+ NEVER speculate about code you have not opened:
837
+
838
+ STEP 1: User mentions file → Read it
839
+ STEP 2: Understand the actual code → then answer
840
+ STEP 3: If referencing a function → Grep to verify it exists
841
+
842
+ ⛔ "The error is probably because..." (guessing)
843
+ ✅ Read file → find line → "Line 42 accesses product.images[0]
844
+ without null check. The API sometimes returns empty array."
845
+ ```
846
+
847
+ ### Assumption-Driven Progress (from Cursor — for non-blocking work)
848
+
849
+ ```
850
+ When NOT blocked but details are unclear:
851
+
852
+ ✅ State assumption clearly → proceed → let user correct
853
+ "Assuming REST API (matching product feature pattern). Creating
854
+ authService with axios. If this should use Firebase, let me know."
855
+
856
+ ⛔ Ask permission for every small decision
857
+ "Should I use axios or fetch? Should the file be named authService
858
+ or AuthService? Should I put it in services/ or api/?"
859
+ ```
860
+
861
+ ### Negative Space Pattern (used by ALL top tools)
862
+
863
+ ```
864
+ Explicitly state what NOT to do — prevents drift:
865
+
866
+ ⛔ NEVER add new packages without checking existing deps first
867
+ ⛔ NEVER create utils/ or helpers/ for one-time operations
868
+ ⛔ NEVER add error handling for scenarios that can't happen
869
+ ⛔ NEVER refactor surrounding code when fixing a bug
870
+ ⛔ NEVER add comments to code that is self-explanatory
871
+ ```
872
+
873
+ ### Batched Operations (from Lovable — reduces tool call waste)
874
+
875
+ ```
876
+ COMBINE operations that can run together:
877
+
878
+ <good-example>
879
+ Read 3 files in ONE message (parallel):
880
+ Read src/features/product/ProductScreen.tsx
881
+ Read src/features/product/productService.ts
882
+ Read src/features/product/product.types.ts
883
+ </good-example>
884
+
885
+ <bad-example>
886
+ Read file 1 → wait → Read file 2 → wait → Read file 3
887
+ (3 round-trips instead of 1)
888
+ </bad-example>
889
+ ```
890
+
891
+ ### Error Recovery with Escalation (from Cursor, Claude Code)
892
+
893
+ ```
894
+ ATTEMPT 1: Auto-fix (missing imports, type errors, lint)
895
+ ATTEMPT 2: Read related files, check dependencies
896
+ ATTEMPT 3: Try alternative approach
897
+ ATTEMPT 4: STOP → present options to user
898
+
899
+ ⛔ NEVER: loop on same error 5+ times
900
+ ⛔ NEVER: suppress errors to make tests pass
901
+ ✅ If corrected twice on same issue → /clear and restart with better prompt
902
+ ```
903
+
904
+ ---
905
+
655
906
  ## Quick Reference
656
907
 
657
908
  ### Good Prompt Checklist
@@ -0,0 +1,312 @@
1
+ # Mobile Storage Patterns
2
+
3
+ > On-device storage — when to use what, how to implement correctly.
4
+ > Covers: AsyncStorage, MMKV, SecureStore/Keychain, SQLite, WatermelonDB, Realm, SharedPreferences.
5
+
6
+ ---
7
+
8
+ ## Decision Matrix — Pick Storage Type First
9
+
10
+ ```
11
+ WHAT ARE YOU STORING? → STORAGE TO USE
12
+ ────────────────────────────────────────────────────────────────────
13
+ Auth tokens / secrets → SecureStore (RN) / Keychain (iOS)
14
+ EncryptedSharedPreferences (Android)
15
+ flutter_secure_storage (Flutter)
16
+
17
+ App preferences / settings → MMKV (RN, fast KV)
18
+ (theme, language, onboarding) SharedPreferences (Android native)
19
+ UserDefaults (iOS native)
20
+ shared_preferences (Flutter)
21
+
22
+ Simple key-value cache → MMKV (RN) / MMKV (Flutter)
23
+ (session data, small objects)
24
+
25
+ Structured relational data → SQLite (via expo-sqlite / sqflite)
26
+ (offline CRUD, complex queries) WatermelonDB (RN, reactive queries)
27
+ drift (Flutter, type-safe)
28
+
29
+ Large offline datasets → WatermelonDB (RN)
30
+ (sync with server, observables) drift (Flutter)
31
+ Room (Android native)
32
+ CoreData / SwiftData (iOS native)
33
+ Realm (cross-platform)
34
+
35
+ Files / images / documents → FileSystem (expo-file-system / path_provider)
36
+ AsyncStorage ❌ (NOT for binary data)
37
+
38
+ ⛔ RULE: AsyncStorage is deprecated for RN. Use MMKV instead.
39
+ ⛔ RULE: NEVER store tokens in AsyncStorage / SharedPreferences / UserDefaults.
40
+ ```
41
+
42
+ ---
43
+
44
+ ## React Native
45
+
46
+ ### 1. Secure Storage (Tokens, Credentials)
47
+
48
+ ```typescript
49
+ // expo-secure-store (Expo) / react-native-keychain (bare RN)
50
+ import * as SecureStore from 'expo-secure-store';
51
+
52
+ // Store
53
+ await SecureStore.setItemAsync('accessToken', token);
54
+
55
+ // Read
56
+ const token = await SecureStore.getItemAsync('accessToken');
57
+
58
+ // Delete (on logout — ALWAYS do this)
59
+ await SecureStore.deleteItemAsync('accessToken');
60
+ await SecureStore.deleteItemAsync('refreshToken');
61
+
62
+ // RULE: On logout, delete ALL secure store keys
63
+ async function logout() {
64
+ await Promise.all([
65
+ SecureStore.deleteItemAsync('accessToken'),
66
+ SecureStore.deleteItemAsync('refreshToken'),
67
+ SecureStore.deleteItemAsync('userId'),
68
+ ]);
69
+ }
70
+ ```
71
+
72
+ ### 2. MMKV (Preferences + KV Cache) — 60x faster than AsyncStorage
73
+
74
+ ```typescript
75
+ // react-native-mmkv
76
+ import { MMKV } from 'react-native-mmkv';
77
+
78
+ // Create instance (one per app, or per domain)
79
+ export const storage = new MMKV();
80
+
81
+ // Typed wrapper (recommended)
82
+ export const Storage = {
83
+ getString: (key: string) => storage.getString(key),
84
+ setString: (key: string, value: string) => storage.set(key, value),
85
+ getBoolean: (key: string) => storage.getBoolean(key) ?? false,
86
+ setBoolean: (key: string, value: boolean) => storage.set(key, value),
87
+ getObject: <T>(key: string): T | null => {
88
+ const raw = storage.getString(key);
89
+ return raw ? JSON.parse(raw) : null;
90
+ },
91
+ setObject: <T>(key: string, value: T) => storage.set(key, JSON.stringify(value)),
92
+ delete: (key: string) => storage.delete(key),
93
+ clear: () => storage.clearAll(),
94
+ };
95
+
96
+ // With Zustand persist (recommended combo)
97
+ import { create } from 'zustand';
98
+ import { persist, createJSONStorage } from 'zustand/middleware';
99
+
100
+ const mmkvStorage = {
101
+ getItem: (name: string) => storage.getString(name) ?? null,
102
+ setItem: (name: string, value: string) => storage.set(name, value),
103
+ removeItem: (name: string) => storage.delete(name),
104
+ };
105
+
106
+ export const useSettingsStore = create(
107
+ persist(
108
+ (set) => ({
109
+ theme: 'light',
110
+ language: 'en',
111
+ setTheme: (theme: string) => set({ theme }),
112
+ setLanguage: (lang: string) => set({ language: lang }),
113
+ }),
114
+ { name: 'settings', storage: createJSONStorage(() => mmkvStorage) }
115
+ )
116
+ );
117
+ ```
118
+
119
+ ### 3. SQLite / WatermelonDB (Structured Offline Data)
120
+
121
+ ```typescript
122
+ // expo-sqlite (simple queries)
123
+ import * as SQLite from 'expo-sqlite';
124
+
125
+ const db = SQLite.openDatabaseSync('app.db');
126
+
127
+ // Init schema
128
+ db.execSync(`
129
+ CREATE TABLE IF NOT EXISTS tasks (
130
+ id TEXT PRIMARY KEY,
131
+ title TEXT NOT NULL,
132
+ completed INTEGER NOT NULL DEFAULT 0,
133
+ created_at INTEGER NOT NULL
134
+ )
135
+ `);
136
+
137
+ // Query
138
+ const tasks = db.getAllSync<Task>('SELECT * FROM tasks WHERE completed = ?', [0]);
139
+
140
+ // Insert
141
+ db.runSync('INSERT INTO tasks (id, title, completed, created_at) VALUES (?, ?, ?, ?)',
142
+ [uuid(), 'Buy milk', 0, Date.now()]);
143
+ ```
144
+
145
+ ```typescript
146
+ // WatermelonDB (reactive queries, sync-ready)
147
+ // Best for: large datasets, reactive UI, server sync
148
+ import { Database } from '@nozbe/watermelondb';
149
+ import SQLiteAdapter from '@nozbe/watermelondb/adapters/sqlite';
150
+
151
+ const adapter = new SQLiteAdapter({ schema, migrations });
152
+ const database = new Database({ adapter, modelClasses: [Post, Comment] });
153
+
154
+ // Observe (reactive — auto re-renders on change)
155
+ const posts = database.get('posts').query().observe();
156
+ ```
157
+
158
+ ### 4. Avoid AsyncStorage (Legacy)
159
+
160
+ ```typescript
161
+ // ❌ DEPRECATED — avoid in new projects
162
+ import AsyncStorage from '@react-native-async-storage/async-storage';
163
+
164
+ // ✅ Migrate to MMKV:
165
+ // Before: await AsyncStorage.setItem('theme', 'dark');
166
+ // After: storage.set('theme', 'dark');
167
+
168
+ // ✅ Migrate to expo-secure-store for tokens:
169
+ // Before: await AsyncStorage.setItem('token', jwt);
170
+ // After: await SecureStore.setItemAsync('token', jwt);
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Flutter
176
+
177
+ ### 1. Secure Storage (Tokens)
178
+
179
+ ```dart
180
+ // flutter_secure_storage
181
+ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
182
+
183
+ final _secureStorage = FlutterSecureStorage(
184
+ aOptions: AndroidOptions(encryptedSharedPreferences: true),
185
+ iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
186
+ );
187
+
188
+ // Store
189
+ await _secureStorage.write(key: 'accessToken', value: token);
190
+
191
+ // Read
192
+ final token = await _secureStorage.read(key: 'accessToken');
193
+
194
+ // Delete on logout
195
+ await _secureStorage.deleteAll();
196
+ ```
197
+
198
+ ### 2. SharedPreferences / Hive (KV Storage)
199
+
200
+ ```dart
201
+ // shared_preferences (simple, built-in)
202
+ final prefs = await SharedPreferences.getInstance();
203
+ await prefs.setString('language', 'en');
204
+ final lang = prefs.getString('language') ?? 'en';
205
+
206
+ // Hive (faster, type-safe, no codegen)
207
+ import 'package:hive_flutter/hive_flutter.dart';
208
+
209
+ await Hive.initFlutter();
210
+ final box = await Hive.openBox('settings');
211
+ box.put('theme', 'dark');
212
+ final theme = box.get('theme', defaultValue: 'light');
213
+ ```
214
+
215
+ ### 3. Drift (SQLite, type-safe)
216
+
217
+ ```dart
218
+ // drift — type-safe SQLite with code generation
219
+ @DriftDatabase(tables: [Tasks])
220
+ class AppDatabase extends _$AppDatabase {
221
+ AppDatabase() : super(_openConnection());
222
+
223
+ Stream<List<Task>> watchIncompleteTasks() =>
224
+ (select(tasks)..where((t) => t.completed.not())).watch();
225
+
226
+ Future insertTask(TasksCompanion task) => into(tasks).insert(task);
227
+ }
228
+ ```
229
+
230
+ ---
231
+
232
+ ## iOS Native (Swift)
233
+
234
+ ```swift
235
+ // UserDefaults — preferences ONLY (not tokens)
236
+ UserDefaults.standard.set("en", forKey: "language")
237
+ let lang = UserDefaults.standard.string(forKey: "language") ?? "en"
238
+
239
+ // Keychain — tokens and secrets
240
+ import Security
241
+
242
+ func saveToKeychain(key: String, value: String) {
243
+ let data = value.data(using: .utf8)!
244
+ let query: [String: Any] = [
245
+ kSecClass as String: kSecClassGenericPassword,
246
+ kSecAttrAccount as String: key,
247
+ kSecValueData as String: data,
248
+ kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
249
+ ]
250
+ SecItemDelete(query as CFDictionary)
251
+ SecItemAdd(query as CFDictionary, nil)
252
+ }
253
+
254
+ // SwiftData / CoreData — structured offline data
255
+ @Model class Task {
256
+ var id: UUID
257
+ var title: String
258
+ var completed: Bool
259
+ init(title: String) { self.id = UUID(); self.title = title; self.completed = false }
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Android Native (Kotlin)
266
+
267
+ ```kotlin
268
+ // EncryptedSharedPreferences — tokens and secrets
269
+ val masterKey = MasterKey.Builder(context)
270
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build()
271
+ val encryptedPrefs = EncryptedSharedPreferences.create(
272
+ context, "secure_prefs", masterKey,
273
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
274
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
275
+ )
276
+ encryptedPrefs.edit().putString("accessToken", token).apply()
277
+
278
+ // DataStore — preferences (replaces SharedPreferences)
279
+ val Context.dataStore by preferencesDataStore(name = "settings")
280
+ val LANGUAGE_KEY = stringPreferencesKey("language")
281
+
282
+ suspend fun saveLanguage(context: Context, lang: String) {
283
+ context.dataStore.edit { it[LANGUAGE_KEY] = lang }
284
+ }
285
+
286
+ val languageFlow = context.dataStore.data.map { it[LANGUAGE_KEY] ?: "en" }
287
+
288
+ // Room — structured offline data
289
+ @Entity data class Task(@PrimaryKey val id: String, val title: String, val completed: Boolean)
290
+ @Dao interface TaskDao {
291
+ @Query("SELECT * FROM task WHERE completed = 0") fun getActive(): Flow<List<Task>>
292
+ @Insert suspend fun insert(task: Task)
293
+ }
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Security Checklist
299
+
300
+ ```
301
+ ✅ Tokens → SecureStore / Keychain / EncryptedSharedPreferences ONLY
302
+ ✅ On logout → delete ALL secure storage keys
303
+ ✅ Encrypt sensitive data before storing in SQLite/MMKV
304
+ ✅ Don't log stored values (console.log, print)
305
+ ✅ Use device-only accessibility (not iCloud sync for tokens)
306
+
307
+ ⛔ NEVER: AsyncStorage for tokens
308
+ ⛔ NEVER: UserDefaults for tokens
309
+ ⛔ NEVER: SharedPreferences (unencrypted) for tokens
310
+ ⛔ NEVER: Log token values in debug output
311
+ ⛔ NEVER: Store plain-text passwords
312
+ ```