native-update 1.2.0 → 1.3.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.
Files changed (37) hide show
  1. package/Readme.md +36 -22
  2. package/docs/CHANGELOG.md +168 -0
  3. package/docs/EXAMPLE_APPS_SIMPLIFICATION_PLAN.md +384 -0
  4. package/docs/EXAMPLE_APPS_SIMPLIFICATION_TRACKER.md +390 -0
  5. package/docs/MARKETING_WEBSITE_PLAN.md +659 -0
  6. package/docs/MARKETING_WEBSITE_TRACKER.md +661 -0
  7. package/docs/ROADMAP.md +143 -0
  8. package/docs/SECURITY.md +356 -0
  9. package/docs/api/API.md +557 -0
  10. package/docs/api/FEATURES.md +414 -0
  11. package/docs/guides/key-management.md +1 -1
  12. package/docs/plans/PLANNING_COMPLETE_SUMMARY.md +361 -0
  13. package/docs/plans/TASK_1_ANDROID_EXAMPLE_APP.md +401 -0
  14. package/docs/plans/TASK_2_API_ENDPOINTS.md +856 -0
  15. package/docs/plans/TASK_2_DASHBOARD_UI_UX.md +820 -0
  16. package/docs/plans/TASK_2_DATABASE_SCHEMA.md +704 -0
  17. package/docs/plans/TASK_2_GOOGLE_DRIVE_INTEGRATION.md +646 -0
  18. package/docs/plans/TASK_2_SAAS_ARCHITECTURE.md +587 -0
  19. package/docs/plans/TASK_2_USER_AUTHENTICATION.md +600 -0
  20. package/docs/reports/AUDIT_SUMMARY_2025-12-26.md +203 -0
  21. package/docs/reports/COMPLETE_VERIFICATION.md +106 -0
  22. package/docs/reports/EVENT_FLOW_VERIFICATION.md +80 -0
  23. package/docs/reports/EXAMPLE_APPS_SIMPLIFICATION_COMPLETE.md +369 -0
  24. package/docs/reports/FINAL_STATUS.md +122 -0
  25. package/docs/reports/FINAL_VERIFICATION_CHECKLIST.md +425 -0
  26. package/docs/reports/MARKETING_WEBSITE_COMPLETE.md +466 -0
  27. package/docs/reports/PACKAGE_COMPLETENESS_REPORT.md +130 -0
  28. package/docs/reports/PRODUCTION_STATUS.md +115 -0
  29. package/docs/reports/PROJECT_RESTRUCTURE_2025-12-27.md +287 -0
  30. package/docs/reports/PROJECT_RESTRUCTURE_FINAL_SUMMARY.md +464 -0
  31. package/docs/reports/PUBLISHING_VERIFICATION.md +144 -0
  32. package/docs/reports/RELEASE_READY_SUMMARY.md +99 -0
  33. package/docs/tracking/IMPLEMENTATION_TRACKER.md +303 -0
  34. package/package.json +2 -3
  35. package/backend-template/README.md +0 -56
  36. package/backend-template/package.json +0 -20
  37. package/backend-template/server.js +0 -121
@@ -0,0 +1,856 @@
1
+ # Task 2: API Endpoints Plan
2
+
3
+ **Created:** 2025-12-27
4
+ **Status:** 📝 Planning
5
+ **Backend:** Firebase Cloud Functions (Node.js 22)
6
+
7
+ ---
8
+
9
+ ## 🎯 Objectives
10
+
11
+ Design and implement a complete REST API for:
12
+ - User management
13
+ - App CRUD operations
14
+ - Build upload and management
15
+ - Google Drive integration
16
+ - Configuration generation
17
+ - Public endpoints for app update checks
18
+
19
+ ---
20
+
21
+ ## 🏗️ Backend Architecture
22
+
23
+ ### Technology Stack
24
+ - **Runtime:** Node.js 22 (Firebase Functions)
25
+ - **Language:** TypeScript
26
+ - **Database:** Firestore
27
+ - **Storage:** Firebase Storage (temp) + Google Drive (permanent)
28
+ - **Authentication:** Firebase Auth (verify ID tokens)
29
+ - **Encryption:** crypto (AES-256-GCM for Drive tokens)
30
+
31
+ ### Project Structure
32
+ ```
33
+ functions/
34
+ ├── src/
35
+ │ ├── index.ts # Main entry point
36
+ │ ├── middleware/
37
+ │ │ ├── auth.ts # Auth verification
38
+ │ │ ├── validation.ts # Request validation
39
+ │ │ └── error-handler.ts # Error handling
40
+ │ ├── services/
41
+ │ │ ├── drive-service.ts # Google Drive operations
42
+ │ │ ├── build-service.ts # Build management
43
+ │ │ ├── config-service.ts # Config generation
44
+ │ │ └── analytics-service.ts # Analytics tracking
45
+ │ ├── routes/
46
+ │ │ ├── auth.ts # Auth endpoints
47
+ │ │ ├── users.ts # User endpoints
48
+ │ │ ├── apps.ts # App endpoints
49
+ │ │ ├── builds.ts # Build endpoints
50
+ │ │ ├── drive.ts # Drive endpoints
51
+ │ │ ├── config.ts # Config endpoints
52
+ │ │ └── public.ts # Public endpoints
53
+ │ ├── utils/
54
+ │ │ ├── validation.ts # Input validators
55
+ │ │ ├── encryption.ts # Token encryption
56
+ │ │ └── helpers.ts # Helper functions
57
+ │ └── types/
58
+ │ └── index.ts # TypeScript types
59
+ ├── package.json
60
+ └── tsconfig.json
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 🔐 Authentication Middleware
66
+
67
+ All protected endpoints require Firebase Auth token verification.
68
+
69
+ ```typescript
70
+ // src/middleware/auth.ts
71
+ import { auth } from 'firebase-admin';
72
+ import { Request, Response, NextFunction } from 'express';
73
+
74
+ export const verifyAuth = async (req: Request, res: Response, next: NextFunction) => {
75
+ const authHeader = req.headers.authorization;
76
+
77
+ if (!authHeader?.startsWith('Bearer ')) {
78
+ return res.status(401).json({ error: 'Unauthorized' });
79
+ }
80
+
81
+ const token = authHeader.split('Bearer ')[1];
82
+
83
+ try {
84
+ const decodedToken = await auth().verifyIdToken(token);
85
+ req.user = {
86
+ uid: decodedToken.uid,
87
+ email: decodedToken.email,
88
+ emailVerified: decodedToken.email_verified
89
+ };
90
+ next();
91
+ } catch (error) {
92
+ return res.status(401).json({ error: 'Invalid token' });
93
+ }
94
+ };
95
+
96
+ export const requireEmailVerified = (req: Request, res: Response, next: NextFunction) => {
97
+ if (!req.user?.emailVerified) {
98
+ return res.status(403).json({ error: 'Email not verified' });
99
+ }
100
+ next();
101
+ };
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 📡 API Endpoints
107
+
108
+ ### Base URL
109
+ - **Development:** `http://localhost:5001/native-update-dev/us-central1/api`
110
+ - **Production:** `https://us-central1-native-update-prod.cloudfunctions.net/api`
111
+
112
+ ---
113
+
114
+ ## 1. Authentication Endpoints
115
+
116
+ ### POST `/api/auth/signup`
117
+
118
+ **Purpose:** Create new user (handled by Firebase Auth client SDK, backend creates Firestore doc)
119
+
120
+ **Protected:** No
121
+
122
+ **Request:**
123
+ ```json
124
+ {
125
+ "email": "user@example.com",
126
+ "password": "SecurePass123!",
127
+ "displayName": "John Doe"
128
+ }
129
+ ```
130
+
131
+ **Response:**
132
+ ```json
133
+ {
134
+ "success": true,
135
+ "userId": "abc123xyz789",
136
+ "message": "User created successfully. Please verify your email."
137
+ }
138
+ ```
139
+
140
+ **Implementation:**
141
+ ```typescript
142
+ // Triggered by Firebase Auth onCreate
143
+ export const onUserCreate = functions.auth.user().onCreate(async (user) => {
144
+ await db.collection('users').doc(user.uid).set({
145
+ uid: user.uid,
146
+ email: user.email,
147
+ displayName: user.displayName || null,
148
+ photoURL: user.photoURL || null,
149
+ provider: user.providerData[0]?.providerId || 'email',
150
+ emailVerified: user.emailVerified,
151
+ createdAt: admin.firestore.FieldValue.serverTimestamp(),
152
+ lastLogin: admin.firestore.FieldValue.serverTimestamp(),
153
+ driveConnected: false,
154
+ driveEmail: null,
155
+ driveConnectedAt: null,
156
+ plan: 'free',
157
+ planStartDate: null,
158
+ planEndDate: null,
159
+ appsCount: 0,
160
+ buildsCount: 0,
161
+ storageUsed: 0,
162
+ preferences: {
163
+ emailNotifications: true,
164
+ updateNotifications: true,
165
+ theme: 'auto',
166
+ language: 'en'
167
+ },
168
+ updatedAt: admin.firestore.FieldValue.serverTimestamp()
169
+ });
170
+ });
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 2. User Endpoints
176
+
177
+ ### GET `/api/user/profile`
178
+
179
+ **Purpose:** Get user profile
180
+
181
+ **Protected:** Yes
182
+
183
+ **Request:** None (user from auth token)
184
+
185
+ **Response:**
186
+ ```json
187
+ {
188
+ "uid": "abc123xyz789",
189
+ "email": "user@example.com",
190
+ "displayName": "John Doe",
191
+ "photoURL": "https://...",
192
+ "provider": "google.com",
193
+ "emailVerified": true,
194
+ "driveConnected": true,
195
+ "driveEmail": "user@gmail.com",
196
+ "plan": "free",
197
+ "appsCount": 5,
198
+ "buildsCount": 23,
199
+ "storageUsed": 1258291200,
200
+ "preferences": {
201
+ "emailNotifications": true,
202
+ "updateNotifications": true,
203
+ "theme": "dark",
204
+ "language": "en"
205
+ },
206
+ "createdAt": "2025-01-15T10:30:00Z"
207
+ }
208
+ ```
209
+
210
+ ### PUT `/api/user/profile`
211
+
212
+ **Purpose:** Update user profile
213
+
214
+ **Protected:** Yes
215
+
216
+ **Request:**
217
+ ```json
218
+ {
219
+ "displayName": "Jane Doe",
220
+ "photoURL": "https://..."
221
+ }
222
+ ```
223
+
224
+ **Response:**
225
+ ```json
226
+ {
227
+ "success": true,
228
+ "message": "Profile updated successfully"
229
+ }
230
+ ```
231
+
232
+ ### PUT `/api/user/preferences`
233
+
234
+ **Purpose:** Update user preferences
235
+
236
+ **Protected:** Yes
237
+
238
+ **Request:**
239
+ ```json
240
+ {
241
+ "emailNotifications": false,
242
+ "updateNotifications": true,
243
+ "theme": "dark",
244
+ "language": "en"
245
+ }
246
+ ```
247
+
248
+ **Response:**
249
+ ```json
250
+ {
251
+ "success": true,
252
+ "message": "Preferences updated successfully"
253
+ }
254
+ ```
255
+
256
+ ### DELETE `/api/user/account`
257
+
258
+ **Purpose:** Delete user account and all data
259
+
260
+ **Protected:** Yes
261
+
262
+ **Request:** None
263
+
264
+ **Response:**
265
+ ```json
266
+ {
267
+ "success": true,
268
+ "message": "Account deleted successfully"
269
+ }
270
+ ```
271
+
272
+ **Implementation Notes:**
273
+ - Delete all user's apps
274
+ - Delete all user's builds
275
+ - Delete Drive tokens
276
+ - Delete all Firestore documents
277
+ - Delete Firebase Auth user
278
+ - Optionally delete files from Google Drive
279
+
280
+ ---
281
+
282
+ ## 3. App Endpoints
283
+
284
+ ### GET `/api/apps`
285
+
286
+ **Purpose:** List user's apps
287
+
288
+ **Protected:** Yes
289
+
290
+ **Query Params:**
291
+ - `limit` (optional, default: 20)
292
+ - `offset` (optional, default: 0)
293
+
294
+ **Response:**
295
+ ```json
296
+ {
297
+ "apps": [
298
+ {
299
+ "id": "app_abc123",
300
+ "userId": "abc123xyz789",
301
+ "name": "My Awesome App",
302
+ "packageId": "com.example.awesome",
303
+ "icon": "https://...",
304
+ "description": "A great mobile app",
305
+ "platforms": ["ios", "android"],
306
+ "totalBuilds": 5,
307
+ "activeUsers": 1234,
308
+ "lastBuildDate": "2025-01-20T14:30:00Z",
309
+ "createdAt": "2025-01-15T10:30:00Z"
310
+ }
311
+ ],
312
+ "total": 5,
313
+ "limit": 20,
314
+ "offset": 0
315
+ }
316
+ ```
317
+
318
+ ### GET `/api/apps/:appId`
319
+
320
+ **Purpose:** Get app details
321
+
322
+ **Protected:** Yes (must be owner)
323
+
324
+ **Response:**
325
+ ```json
326
+ {
327
+ "id": "app_abc123",
328
+ "userId": "abc123xyz789",
329
+ "name": "My Awesome App",
330
+ "packageId": "com.example.awesome",
331
+ "icon": "https://...",
332
+ "description": "A great mobile app",
333
+ "platforms": ["ios", "android"],
334
+ "channels": {
335
+ "production": {
336
+ "enabled": true,
337
+ "autoUpdate": true,
338
+ "updateStrategy": "background",
339
+ "requireUserConsent": false,
340
+ "minVersion": "1.0.0"
341
+ },
342
+ "staging": { /* ... */ },
343
+ "development": { /* ... */ }
344
+ },
345
+ "totalBuilds": 5,
346
+ "activeUsers": 1234,
347
+ "lastBuildDate": "2025-01-20T14:30:00Z",
348
+ "createdAt": "2025-01-15T10:30:00Z"
349
+ }
350
+ ```
351
+
352
+ ### POST `/api/apps`
353
+
354
+ **Purpose:** Create new app
355
+
356
+ **Protected:** Yes
357
+
358
+ **Request:**
359
+ ```json
360
+ {
361
+ "name": "My Awesome App",
362
+ "packageId": "com.example.awesome",
363
+ "description": "A great mobile app",
364
+ "platforms": ["ios", "android"],
365
+ "icon": "https://..." // optional
366
+ }
367
+ ```
368
+
369
+ **Response:**
370
+ ```json
371
+ {
372
+ "success": true,
373
+ "appId": "app_abc123",
374
+ "message": "App created successfully"
375
+ }
376
+ ```
377
+
378
+ ### PUT `/api/apps/:appId`
379
+
380
+ **Purpose:** Update app details
381
+
382
+ **Protected:** Yes (must be owner)
383
+
384
+ **Request:**
385
+ ```json
386
+ {
387
+ "name": "Updated App Name",
388
+ "description": "Updated description",
389
+ "channels": {
390
+ "production": {
391
+ "enabled": true,
392
+ "autoUpdate": false,
393
+ "updateStrategy": "manual",
394
+ "requireUserConsent": true,
395
+ "minVersion": "1.0.0"
396
+ }
397
+ }
398
+ }
399
+ ```
400
+
401
+ **Response:**
402
+ ```json
403
+ {
404
+ "success": true,
405
+ "message": "App updated successfully"
406
+ }
407
+ ```
408
+
409
+ ### DELETE `/api/apps/:appId`
410
+
411
+ **Purpose:** Delete app and all builds
412
+
413
+ **Protected:** Yes (must be owner)
414
+
415
+ **Response:**
416
+ ```json
417
+ {
418
+ "success": true,
419
+ "message": "App and all builds deleted successfully"
420
+ }
421
+ ```
422
+
423
+ ---
424
+
425
+ ## 4. Build Endpoints
426
+
427
+ ### GET `/api/builds`
428
+
429
+ **Purpose:** List user's builds (across all apps)
430
+
431
+ **Protected:** Yes
432
+
433
+ **Query Params:**
434
+ - `appId` (optional) - Filter by app
435
+ - `channel` (optional) - Filter by channel
436
+ - `platform` (optional) - Filter by platform
437
+ - `limit` (optional, default: 20)
438
+ - `offset` (optional, default: 0)
439
+
440
+ **Response:**
441
+ ```json
442
+ {
443
+ "builds": [
444
+ {
445
+ "id": "build_xyz456",
446
+ "userId": "abc123xyz789",
447
+ "appId": "app_abc123",
448
+ "appName": "My Awesome App",
449
+ "version": "1.0.1",
450
+ "buildNumber": 2,
451
+ "channel": "production",
452
+ "platform": "android",
453
+ "fileName": "app-v1.0.1.zip",
454
+ "fileSize": 31457280,
455
+ "fileType": "zip",
456
+ "checksum": "sha256:a1b2c3d4...",
457
+ "driveFileId": "1a2b3c4d5e6f",
458
+ "driveFileUrl": "https://drive.google.com/...",
459
+ "releaseNotes": "Bug fixes and improvements",
460
+ "status": "active",
461
+ "downloads": 523,
462
+ "uploadedAt": "2025-01-20T14:30:00Z"
463
+ }
464
+ ],
465
+ "total": 23,
466
+ "limit": 20,
467
+ "offset": 0
468
+ }
469
+ ```
470
+
471
+ ### GET `/api/builds/:buildId`
472
+
473
+ **Purpose:** Get build details
474
+
475
+ **Protected:** Yes (must be owner)
476
+
477
+ **Response:**
478
+ ```json
479
+ {
480
+ "id": "build_xyz456",
481
+ "userId": "abc123xyz789",
482
+ "appId": "app_abc123",
483
+ "version": "1.0.1",
484
+ "buildNumber": 2,
485
+ "channel": "production",
486
+ "platform": "android",
487
+ "fileName": "app-v1.0.1.zip",
488
+ "fileSize": 31457280,
489
+ "fileType": "zip",
490
+ "checksum": "sha256:a1b2c3d4e5f6...",
491
+ "driveFileId": "1a2b3c4d5e6f7g8h9i0j",
492
+ "driveFileUrl": "https://drive.google.com/uc?export=download&id=...",
493
+ "releaseNotes": "Bug fixes and performance improvements",
494
+ "releaseType": "patch",
495
+ "status": "active",
496
+ "downloads": 523,
497
+ "installs": 498,
498
+ "uploadedAt": "2025-01-20T14:30:00Z",
499
+ "uploadedBy": "user@example.com"
500
+ }
501
+ ```
502
+
503
+ ### POST `/api/builds/upload`
504
+
505
+ **Purpose:** Upload new build (metadata only, file already in Storage)
506
+
507
+ **Protected:** Yes
508
+
509
+ **Request:**
510
+ ```json
511
+ {
512
+ "appId": "app_abc123",
513
+ "version": "1.0.1",
514
+ "buildNumber": 2,
515
+ "versionCode": 101,
516
+ "bundleVersion": "1.0.1",
517
+ "channel": "production",
518
+ "platform": "android",
519
+ "fileName": "app-v1.0.1.zip",
520
+ "fileSize": 31457280,
521
+ "fileType": "zip",
522
+ "checksum": "sha256:a1b2c3d4e5f6...",
523
+ "releaseNotes": "Bug fixes and improvements",
524
+ "releaseType": "patch",
525
+ "storageFilePath": "temp/uploads/abc123xyz789/file123.zip"
526
+ }
527
+ ```
528
+
529
+ **Response:**
530
+ ```json
531
+ {
532
+ "success": true,
533
+ "buildId": "build_xyz456",
534
+ "message": "Build uploaded successfully",
535
+ "driveFileId": "1a2b3c4d5e6f",
536
+ "downloadUrl": "https://drive.google.com/..."
537
+ }
538
+ ```
539
+
540
+ **Implementation Flow:**
541
+ 1. Verify user owns the app
542
+ 2. Download file from Firebase Storage (temp path)
543
+ 3. Upload to user's Google Drive
544
+ 4. Create build document in Firestore
545
+ 5. Delete temp file from Storage
546
+ 6. Return build ID and Drive URL
547
+
548
+ ### DELETE `/api/builds/:buildId`
549
+
550
+ **Purpose:** Delete build
551
+
552
+ **Protected:** Yes (must be owner)
553
+
554
+ **Response:**
555
+ ```json
556
+ {
557
+ "success": true,
558
+ "message": "Build deleted successfully"
559
+ }
560
+ ```
561
+
562
+ **Implementation Notes:**
563
+ - Delete from Google Drive
564
+ - Delete Firestore document
565
+ - Update app's totalBuilds count
566
+
567
+ ---
568
+
569
+ ## 5. Google Drive Endpoints
570
+
571
+ ### POST `/api/drive/connect`
572
+
573
+ **Purpose:** Connect Google Drive (OAuth callback)
574
+
575
+ **Protected:** Yes
576
+
577
+ **Request:**
578
+ ```json
579
+ {
580
+ "code": "4/0AfJohXm...",
581
+ "userId": "abc123xyz789"
582
+ }
583
+ ```
584
+
585
+ **Response:**
586
+ ```json
587
+ {
588
+ "success": true,
589
+ "message": "Google Drive connected successfully"
590
+ }
591
+ ```
592
+
593
+ **Implementation:**
594
+ - Exchange code for tokens
595
+ - Encrypt tokens
596
+ - Store in drive_tokens collection
597
+ - Update user document
598
+
599
+ ### GET `/api/drive/status`
600
+
601
+ **Purpose:** Check Drive connection status
602
+
603
+ **Protected:** Yes
604
+
605
+ **Response:**
606
+ ```json
607
+ {
608
+ "connected": true,
609
+ "email": "user@gmail.com",
610
+ "connectedAt": "2025-01-15T11:00:00Z",
611
+ "storageUsed": 1258291200
612
+ }
613
+ ```
614
+
615
+ ### POST `/api/drive/disconnect`
616
+
617
+ **Purpose:** Disconnect Google Drive
618
+
619
+ **Protected:** Yes
620
+
621
+ **Response:**
622
+ ```json
623
+ {
624
+ "success": true,
625
+ "message": "Google Drive disconnected successfully"
626
+ }
627
+ ```
628
+
629
+ **Implementation:**
630
+ - Revoke OAuth tokens (optional)
631
+ - Delete drive_tokens document
632
+ - Update user document
633
+
634
+ ---
635
+
636
+ ## 6. Configuration Endpoints
637
+
638
+ ### GET `/api/config/:appId`
639
+
640
+ **Purpose:** Generate plugin configuration for app
641
+
642
+ **Protected:** Yes (must be owner)
643
+
644
+ **Response:**
645
+ ```json
646
+ {
647
+ "capacitorConfig": {
648
+ "plugins": {
649
+ "NativeUpdate": {
650
+ "serverUrl": "https://api.nativeupdate.com",
651
+ "userId": "abc123xyz789",
652
+ "appId": "app_abc123",
653
+ "autoCheck": true,
654
+ "channel": "production"
655
+ }
656
+ }
657
+ },
658
+ "apiEndpoints": {
659
+ "checkUpdate": "https://api.nativeupdate.com/public/updates/app_abc123",
660
+ "downloadBuild": "https://api.nativeupdate.com/public/download/:buildId"
661
+ }
662
+ }
663
+ ```
664
+
665
+ ### GET `/api/config/:appId/download`
666
+
667
+ **Purpose:** Download configuration as JSON file
668
+
669
+ **Protected:** Yes (must be owner)
670
+
671
+ **Response:** File download (application/json)
672
+
673
+ ---
674
+
675
+ ## 7. Public Endpoints (For End Users' Apps)
676
+
677
+ ### GET `/api/public/updates/:appId`
678
+
679
+ **Purpose:** Check for updates (called by user's app)
680
+
681
+ **Protected:** No (public, but requires valid appId)
682
+
683
+ **Query Params:**
684
+ - `channel` (required) - production/staging/development
685
+ - `platform` (required) - ios/android/web
686
+ - `currentVersion` (required) - Current app version
687
+
688
+ **Response:**
689
+ ```json
690
+ {
691
+ "updateAvailable": true,
692
+ "latestVersion": "1.0.1",
693
+ "buildNumber": 2,
694
+ "downloadUrl": "https://drive.google.com/uc?export=download&id=...",
695
+ "fileSize": 31457280,
696
+ "checksum": "sha256:a1b2c3d4e5f6...",
697
+ "releaseNotes": "Bug fixes and improvements",
698
+ "releaseType": "patch",
699
+ "mandatory": false
700
+ }
701
+ ```
702
+
703
+ **Response (No Update):**
704
+ ```json
705
+ {
706
+ "updateAvailable": false,
707
+ "currentVersion": "1.0.1"
708
+ }
709
+ ```
710
+
711
+ **Implementation:**
712
+ 1. Find app by appId
713
+ 2. Query builds for channel + platform
714
+ 3. Get latest version
715
+ 4. Compare with currentVersion (semver)
716
+ 5. Return update info if available
717
+
718
+ ### GET `/api/public/download/:buildId`
719
+
720
+ **Purpose:** Download build (proxy to Google Drive)
721
+
722
+ **Protected:** No (public)
723
+
724
+ **Response:** Redirect to Google Drive download URL or proxy download
725
+
726
+ **Implementation:**
727
+ 1. Find build by buildId
728
+ 2. Get driveFileUrl
729
+ 3. Increment downloads count
730
+ 4. Redirect to Drive URL or stream file
731
+
732
+ ---
733
+
734
+ ## 🛡️ Error Handling
735
+
736
+ ### Standard Error Response
737
+
738
+ ```json
739
+ {
740
+ "error": "Error message here",
741
+ "code": "ERROR_CODE",
742
+ "details": {
743
+ "field": "Additional info"
744
+ }
745
+ }
746
+ ```
747
+
748
+ ### HTTP Status Codes
749
+
750
+ - `200` - Success
751
+ - `201` - Created
752
+ - `400` - Bad Request (validation error)
753
+ - `401` - Unauthorized (not authenticated)
754
+ - `403` - Forbidden (authenticated but not authorized)
755
+ - `404` - Not Found
756
+ - `409` - Conflict (duplicate resource)
757
+ - `500` - Internal Server Error
758
+
759
+ ### Error Codes
760
+
761
+ ```typescript
762
+ enum ErrorCode {
763
+ UNAUTHORIZED = 'UNAUTHORIZED',
764
+ EMAIL_NOT_VERIFIED = 'EMAIL_NOT_VERIFIED',
765
+ NOT_FOUND = 'NOT_FOUND',
766
+ FORBIDDEN = 'FORBIDDEN',
767
+ VALIDATION_ERROR = 'VALIDATION_ERROR',
768
+ DRIVE_NOT_CONNECTED = 'DRIVE_NOT_CONNECTED',
769
+ UPLOAD_FAILED = 'UPLOAD_FAILED',
770
+ DUPLICATE_APP = 'DUPLICATE_APP',
771
+ INTERNAL_ERROR = 'INTERNAL_ERROR'
772
+ }
773
+ ```
774
+
775
+ ---
776
+
777
+ ## 📊 Rate Limiting
778
+
779
+ ### Limits
780
+ - **Public endpoints:** 100 requests/minute per IP
781
+ - **Authenticated endpoints:** 1000 requests/minute per user
782
+ - **Upload endpoint:** 10 uploads/hour per user
783
+
784
+ ### Implementation
785
+ ```typescript
786
+ import rateLimit from 'express-rate-limit';
787
+
788
+ const publicLimiter = rateLimit({
789
+ windowMs: 60 * 1000, // 1 minute
790
+ max: 100,
791
+ message: 'Too many requests from this IP'
792
+ });
793
+
794
+ const authLimiter = rateLimit({
795
+ windowMs: 60 * 1000,
796
+ max: 1000,
797
+ keyGenerator: (req) => req.user?.uid || req.ip
798
+ });
799
+
800
+ const uploadLimiter = rateLimit({
801
+ windowMs: 60 * 60 * 1000, // 1 hour
802
+ max: 10,
803
+ keyGenerator: (req) => req.user?.uid
804
+ });
805
+ ```
806
+
807
+ ---
808
+
809
+ ## ✅ Implementation Checklist
810
+
811
+ ### Setup
812
+ - [ ] Initialize Firebase Functions project
813
+ - [ ] Install dependencies (express, firebase-admin, googleapis, etc.)
814
+ - [ ] Configure TypeScript
815
+ - [ ] Setup environment variables
816
+ - [ ] Configure CORS
817
+
818
+ ### Middleware
819
+ - [ ] Create auth middleware
820
+ - [ ] Create validation middleware
821
+ - [ ] Create error handler
822
+ - [ ] Create rate limiters
823
+
824
+ ### Services
825
+ - [ ] Implement DriveService
826
+ - [ ] Implement BuildService
827
+ - [ ] Implement ConfigService
828
+ - [ ] Implement AnalyticsService
829
+
830
+ ### Endpoints
831
+ - [ ] Implement user endpoints (3)
832
+ - [ ] Implement app endpoints (5)
833
+ - [ ] Implement build endpoints (4)
834
+ - [ ] Implement drive endpoints (3)
835
+ - [ ] Implement config endpoints (2)
836
+ - [ ] Implement public endpoints (2)
837
+
838
+ ### Testing
839
+ - [ ] Unit tests for services
840
+ - [ ] Integration tests for endpoints
841
+ - [ ] Test error handling
842
+ - [ ] Test rate limiting
843
+ - [ ] Test with Postman/Insomnia
844
+
845
+ ### Deployment
846
+ - [ ] Deploy to Firebase (dev environment)
847
+ - [ ] Test in dev
848
+ - [ ] Deploy to production
849
+ - [ ] Monitor logs
850
+ - [ ] Setup alerts
851
+
852
+ ---
853
+
854
+ **Plan Status:** ✅ Complete and ready for implementation
855
+ **Total Endpoints:** 19 endpoints
856
+ **Estimated Time:** 15-20 hours