native-update 2.0.0 → 3.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.
Files changed (258) hide show
  1. package/Readme.md +28 -14
  2. package/android/manifest-additions.xml +28 -0
  3. package/android/src/main/AndroidManifest.xml +3 -7
  4. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +21 -13
  5. package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +196 -29
  6. package/android/src/main/java/com/aoneahsan/nativeupdate/NativeUpdatePlugin.kt +21 -36
  7. package/cli/AGENTS.md +15 -1
  8. package/cli/CLAUDE.md +15 -1
  9. package/cli/commands/backend-create.js +56 -15
  10. package/cli/commands/bundle-create.js +39 -7
  11. package/cli/commands/monitor.js +72 -51
  12. package/cli/index.js +10 -24
  13. package/cli/package.json +11 -3
  14. package/dist/esm/app-review/app-review-manager.js +0 -1
  15. package/dist/esm/app-review/index.js +0 -1
  16. package/dist/esm/app-review/platform-review-handler.js +0 -1
  17. package/dist/esm/app-review/review-conditions-checker.js +0 -1
  18. package/dist/esm/app-review/review-rate-limiter.js +0 -1
  19. package/dist/esm/app-review/types.js +0 -1
  20. package/dist/esm/app-update/app-update-checker.js +0 -1
  21. package/dist/esm/app-update/app-update-installer.d.ts +1 -0
  22. package/dist/esm/app-update/app-update-installer.js +19 -8
  23. package/dist/esm/app-update/app-update-manager.js +0 -1
  24. package/dist/esm/app-update/app-update-notifier.js +0 -1
  25. package/dist/esm/app-update/index.js +0 -1
  26. package/dist/esm/app-update/platform-app-update.js +12 -3
  27. package/dist/esm/app-update/types.js +0 -1
  28. package/dist/esm/background-update/background-scheduler.js +0 -1
  29. package/dist/esm/background-update/index.js +0 -1
  30. package/dist/esm/background-update/notification-manager.js +0 -1
  31. package/dist/esm/config/support.js +0 -1
  32. package/dist/esm/core/analytics.d.ts +13 -0
  33. package/dist/esm/core/analytics.js +15 -1
  34. package/dist/esm/core/cache-manager.js +0 -1
  35. package/dist/esm/core/config.d.ts +0 -15
  36. package/dist/esm/core/config.js +0 -4
  37. package/dist/esm/core/errors.d.ts +1 -0
  38. package/dist/esm/core/errors.js +1 -1
  39. package/dist/esm/core/event-emitter.d.ts +0 -3
  40. package/dist/esm/core/event-emitter.js +8 -3
  41. package/dist/esm/core/logger.js +0 -1
  42. package/dist/esm/core/performance.js +0 -1
  43. package/dist/esm/core/plugin-manager.js +3 -1
  44. package/dist/esm/core/security.d.ts +11 -0
  45. package/dist/esm/core/security.js +27 -1
  46. package/dist/esm/definitions.d.ts +0 -11
  47. package/dist/esm/definitions.js +0 -1
  48. package/dist/esm/index.d.ts +3 -2
  49. package/dist/esm/index.js +3 -1
  50. package/dist/esm/live-update/bundle-manager.d.ts +8 -0
  51. package/dist/esm/live-update/bundle-manager.js +20 -1
  52. package/dist/esm/live-update/certificate-pinning.js +0 -1
  53. package/dist/esm/live-update/delta-processor.d.ts +1 -1
  54. package/dist/esm/live-update/delta-processor.js +3 -1
  55. package/dist/esm/live-update/download-manager.js +9 -2
  56. package/dist/esm/live-update/rollout-checker.d.ts +1 -1
  57. package/dist/esm/live-update/rollout-checker.js +5 -6
  58. package/dist/esm/live-update/update-manager.js +0 -1
  59. package/dist/esm/live-update/version-manager.d.ts +0 -12
  60. package/dist/esm/live-update/version-manager.js +0 -68
  61. package/dist/esm/plugin.js +69 -43
  62. package/dist/esm/security/crypto.js +11 -7
  63. package/dist/esm/security/validator.js +0 -1
  64. package/dist/esm/types/rollout.d.ts +85 -0
  65. package/dist/esm/types/rollout.js +25 -0
  66. package/dist/esm/web.d.ts +8 -0
  67. package/dist/esm/web.js +148 -54
  68. package/dist/plugin.cjs.js +1 -2
  69. package/dist/plugin.esm.js +1 -2
  70. package/dist/plugin.js +2 -3
  71. package/docs/CHANGELOG.md +124 -0
  72. package/docs/CLAUDE.md +1 -1
  73. package/docs/MANUAL-TASKS.md +17 -0
  74. package/docs/MARKETING_WEBSITE_TRACKER.md +18 -2
  75. package/docs/MIGRATION.md +83 -0
  76. package/docs/PACKAGES.md +167 -0
  77. package/docs/PERFORMANCE.md +110 -0
  78. package/docs/PROJECT_COMPLETION_TRACKER.md +4 -35
  79. package/docs/README.md +0 -1
  80. package/docs/REMAINING_FEATURES.md +123 -76
  81. package/docs/ROADMAP.md +200 -120
  82. package/docs/SECURITY-IF-REPO-PUBLIC.md +232 -0
  83. package/docs/TESTING_REQUIREMENTS.md +1 -112
  84. package/docs/ai-knowledge-base/00-project-profile.md +38 -0
  85. package/docs/ai-knowledge-base/01-features.md +46 -0
  86. package/docs/ai-knowledge-base/02-routes.md +72 -0
  87. package/docs/ai-knowledge-base/03-tech-stack.md +57 -0
  88. package/docs/ai-knowledge-base/README.md +23 -0
  89. package/docs/analytics-tracking.md +37 -0
  90. package/docs/capacitor-official-plugins.md +46 -0
  91. package/docs/capawesome-plugins.md +29 -0
  92. package/docs/deployment/HOSTINGER_DEPLOY.md +75 -34
  93. package/docs/deployment/PRODUCTION-DEPLOY-CHECKLIST.md +184 -0
  94. package/docs/docs-site/plan.md +201 -0
  95. package/docs/docs-site/scope.md +127 -0
  96. package/docs/docs-site/tracker.json +235 -0
  97. package/docs/error-handling-tracking.md +37 -0
  98. package/docs/guides/testing-guide.md +15 -41
  99. package/docs/package-audit.md +41 -0
  100. package/docs/play-store/ASO-METADATA.md +5 -0
  101. package/docs/play-store/DATA-SAFETY.md +5 -0
  102. package/docs/play-store/DECLARATIONS.md +5 -0
  103. package/docs/play-store/README.md +27 -0
  104. package/docs/play-store/RELEASE-NOTES.md +99 -0
  105. package/docs/play-store/RELEASE-STEPS.md +6 -0
  106. package/docs/play-store/STORE-LISTING.md +7 -0
  107. package/docs/play-store/SUBMISSION-CHECKLIST.md +5 -0
  108. package/docs/production-readiness.md +1 -1
  109. package/docs/project-audit/2026-05-16/00-FINALIZATION-PLAN.md +123 -0
  110. package/docs/project-audit/2026-05-16/01-BATCH-PLAN.md +227 -0
  111. package/docs/project-audit/2026-05-16/02-AUDIT-FINDINGS.md +144 -0
  112. package/docs/project-audit/2026-05-16/sessions/batch-01.md +42 -0
  113. package/docs/project-audit/2026-05-16/sessions/batch-02.md +74 -0
  114. package/docs/project-audit/2026-05-16/sessions/batch-03.md +71 -0
  115. package/docs/project-audit/2026-05-16/sessions/batch-04.md +88 -0
  116. package/docs/project-audit/2026-05-16/sessions/batch-05.md +63 -0
  117. package/docs/project-audit/2026-05-16/sessions/batch-06.md +103 -0
  118. package/docs/project-audit/2026-05-16/sessions/batch-07.md +61 -0
  119. package/docs/project-audit/2026-05-16/sessions/batch-08.md +101 -0
  120. package/docs/project-audit/2026-05-16/sessions/batch-09.md +105 -0
  121. package/docs/project-audit/2026-05-16/sessions/batch-10.md +102 -0
  122. package/docs/project-audit/AUDIT-HISTORY.md +74 -0
  123. package/docs/project-audit/BATCH-PLAN.md +168 -0
  124. package/docs/project-audit/MARKETING-WEBSITE-FINDINGS-2026-05-11.md +73 -0
  125. package/docs/project-audit/PRODUCTION-READINESS-AUDIT-2026-05-08.md +275 -0
  126. package/docs/project-finalization/00-tracker.json +60 -0
  127. package/docs/project-knowledge-base/01-system-overview.md +39 -30
  128. package/docs/project-knowledge-base/02-routes-pages-forms-users.md +87 -81
  129. package/docs/project-knowledge-base/03-tech-stack-modules-services.md +140 -108
  130. package/docs/project-knowledge-base/04-data-models-integrations.md +191 -254
  131. package/docs/project-knowledge-base/05-docs-corpus-inventory.md +83 -20
  132. package/docs/project-knowledge-base/06-operations-testing-legal-content.md +67 -29
  133. package/docs/project-knowledge-base/README.md +27 -14
  134. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-05-19.md +81 -0
  135. package/docs/rules-tracker.md +102 -0
  136. package/docs/security/PRE-LAUNCH-PENTEST-CHECKLIST.md +116 -0
  137. package/docs/social-media-marketing/README.md +81 -0
  138. package/docs/social-media-marketing/posts-batch-01.md +613 -0
  139. package/docs/social-media-marketing/posts-batch-02.md +528 -0
  140. package/docs/social-media-marketing/whatsapp-messages-batch-01.md +458 -0
  141. package/docs/social-media-marketing/whatsapp-status-batch-01.md +355 -0
  142. package/docs/tracking/finalization-2026-05-16-tracker.json +346 -0
  143. package/docs/tracking/full-audit-tracker.json +121 -0
  144. package/docs/tracking/production-readiness-audit-tracker.json +429 -0
  145. package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +16 -3
  146. package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +71 -47
  147. package/ios/Plugin/NativeUpdatePlugin.swift +14 -9
  148. package/package.json +29 -29
  149. package/cli/node_modules/.yarn-integrity +0 -16
  150. package/cli/node_modules/commander/LICENSE +0 -22
  151. package/cli/node_modules/commander/Readme.md +0 -1148
  152. package/cli/node_modules/commander/esm.mjs +0 -16
  153. package/cli/node_modules/commander/index.js +0 -26
  154. package/cli/node_modules/commander/lib/argument.js +0 -145
  155. package/cli/node_modules/commander/lib/command.js +0 -2179
  156. package/cli/node_modules/commander/lib/error.js +0 -43
  157. package/cli/node_modules/commander/lib/help.js +0 -462
  158. package/cli/node_modules/commander/lib/option.js +0 -329
  159. package/cli/node_modules/commander/lib/suggestSimilar.js +0 -100
  160. package/cli/node_modules/commander/package-support.json +0 -16
  161. package/cli/node_modules/commander/package.json +0 -80
  162. package/cli/node_modules/commander/typings/esm.d.mts +0 -3
  163. package/cli/node_modules/commander/typings/index.d.ts +0 -884
  164. package/cli/yarn.lock +0 -8
  165. package/dist/esm/__tests__/bundle-manager.test.d.ts +0 -1
  166. package/dist/esm/__tests__/bundle-manager.test.js +0 -151
  167. package/dist/esm/__tests__/bundle-manager.test.js.map +0 -1
  168. package/dist/esm/__tests__/config.test.d.ts +0 -1
  169. package/dist/esm/__tests__/config.test.js +0 -70
  170. package/dist/esm/__tests__/config.test.js.map +0 -1
  171. package/dist/esm/__tests__/delta-processor.test.d.ts +0 -1
  172. package/dist/esm/__tests__/delta-processor.test.js +0 -77
  173. package/dist/esm/__tests__/delta-processor.test.js.map +0 -1
  174. package/dist/esm/__tests__/firestore-schema.test.d.ts +0 -1
  175. package/dist/esm/__tests__/firestore-schema.test.js +0 -74
  176. package/dist/esm/__tests__/firestore-schema.test.js.map +0 -1
  177. package/dist/esm/__tests__/integration.test.d.ts +0 -1
  178. package/dist/esm/__tests__/integration.test.js +0 -78
  179. package/dist/esm/__tests__/integration.test.js.map +0 -1
  180. package/dist/esm/__tests__/manifest-reader.test.d.ts +0 -1
  181. package/dist/esm/__tests__/manifest-reader.test.js +0 -271
  182. package/dist/esm/__tests__/manifest-reader.test.js.map +0 -1
  183. package/dist/esm/__tests__/rollout-checker.test.d.ts +0 -1
  184. package/dist/esm/__tests__/rollout-checker.test.js +0 -210
  185. package/dist/esm/__tests__/rollout-checker.test.js.map +0 -1
  186. package/dist/esm/__tests__/security-enforcement.test.d.ts +0 -1
  187. package/dist/esm/__tests__/security-enforcement.test.js +0 -95
  188. package/dist/esm/__tests__/security-enforcement.test.js.map +0 -1
  189. package/dist/esm/__tests__/security.test.d.ts +0 -1
  190. package/dist/esm/__tests__/security.test.js +0 -54
  191. package/dist/esm/__tests__/security.test.js.map +0 -1
  192. package/dist/esm/__tests__/version-manager.test.d.ts +0 -1
  193. package/dist/esm/__tests__/version-manager.test.js +0 -45
  194. package/dist/esm/__tests__/version-manager.test.js.map +0 -1
  195. package/dist/esm/app-review/app-review-manager.js.map +0 -1
  196. package/dist/esm/app-review/index.js.map +0 -1
  197. package/dist/esm/app-review/platform-review-handler.js.map +0 -1
  198. package/dist/esm/app-review/review-conditions-checker.js.map +0 -1
  199. package/dist/esm/app-review/review-rate-limiter.js.map +0 -1
  200. package/dist/esm/app-review/types.js.map +0 -1
  201. package/dist/esm/app-update/app-update-checker.js.map +0 -1
  202. package/dist/esm/app-update/app-update-installer.js.map +0 -1
  203. package/dist/esm/app-update/app-update-manager.js.map +0 -1
  204. package/dist/esm/app-update/app-update-notifier.js.map +0 -1
  205. package/dist/esm/app-update/index.js.map +0 -1
  206. package/dist/esm/app-update/platform-app-update.js.map +0 -1
  207. package/dist/esm/app-update/types.js.map +0 -1
  208. package/dist/esm/background-update/background-scheduler.js.map +0 -1
  209. package/dist/esm/background-update/index.js.map +0 -1
  210. package/dist/esm/background-update/notification-manager.js.map +0 -1
  211. package/dist/esm/config/support.js.map +0 -1
  212. package/dist/esm/core/analytics.js.map +0 -1
  213. package/dist/esm/core/cache-manager.js.map +0 -1
  214. package/dist/esm/core/config.js.map +0 -1
  215. package/dist/esm/core/errors.js.map +0 -1
  216. package/dist/esm/core/event-emitter.js.map +0 -1
  217. package/dist/esm/core/logger.js.map +0 -1
  218. package/dist/esm/core/performance.js.map +0 -1
  219. package/dist/esm/core/plugin-manager.js.map +0 -1
  220. package/dist/esm/core/security.js.map +0 -1
  221. package/dist/esm/definitions.js.map +0 -1
  222. package/dist/esm/firestore/firestore-client.d.ts +0 -109
  223. package/dist/esm/firestore/firestore-client.js +0 -264
  224. package/dist/esm/firestore/firestore-client.js.map +0 -1
  225. package/dist/esm/firestore/index.d.ts +0 -11
  226. package/dist/esm/firestore/index.js +0 -11
  227. package/dist/esm/firestore/index.js.map +0 -1
  228. package/dist/esm/firestore/manifest-reader.d.ts +0 -87
  229. package/dist/esm/firestore/manifest-reader.js +0 -294
  230. package/dist/esm/firestore/manifest-reader.js.map +0 -1
  231. package/dist/esm/firestore/schema.d.ts +0 -507
  232. package/dist/esm/firestore/schema.js +0 -73
  233. package/dist/esm/firestore/schema.js.map +0 -1
  234. package/dist/esm/index.js.map +0 -1
  235. package/dist/esm/live-update/bundle-manager.js.map +0 -1
  236. package/dist/esm/live-update/certificate-pinning.js.map +0 -1
  237. package/dist/esm/live-update/delta-processor.js.map +0 -1
  238. package/dist/esm/live-update/download-manager.js.map +0 -1
  239. package/dist/esm/live-update/rollout-checker.js.map +0 -1
  240. package/dist/esm/live-update/update-manager.js.map +0 -1
  241. package/dist/esm/live-update/version-manager.js.map +0 -1
  242. package/dist/esm/plugin.js.map +0 -1
  243. package/dist/esm/security/crypto.js.map +0 -1
  244. package/dist/esm/security/validator.js.map +0 -1
  245. package/dist/esm/web.js.map +0 -1
  246. package/dist/plugin.cjs.js.map +0 -1
  247. package/dist/plugin.esm.js.map +0 -1
  248. package/dist/plugin.js.map +0 -1
  249. package/docs/FIREBASE_INTEGRATION_TRACKER.md +0 -321
  250. package/docs/FIREBASE_QUERIES_AND_INDEXES_AUDIT.md +0 -221
  251. package/docs/examples/firebase-backend-example.md +0 -27
  252. package/docs/features/laravel-nova-backend/credentials.ignore.md +0 -34
  253. package/docs/guides/no-cost-backend-implementation-plan.md +0 -77
  254. package/docs/guides/no-cost-firestore-google-drive-backend.md +0 -60
  255. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-16.md +0 -454
  256. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-24.md +0 -66
  257. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-25.md +0 -67
  258. /package/docs/{MARKETING_WEBSITE_PLAN.md → archive/MARKETING_WEBSITE_PLAN.md} +0 -0
@@ -19,8 +19,7 @@ Tested against Hostinger hPanel, shared Business plan, PHP 8.2, MySQL.
19
19
  | PayPal subscription plans | PayPal Dashboard → Subscriptions → Plans (create Pro + Enterprise, copy the `P-...` IDs) |
20
20
  | PayPal webhook ID | Set up in step 4, skip for now |
21
21
  | FilesHub API key | fileshub.zaions.com admin |
22
- | Firebase service account JSON | console.firebase.google.com → Project settingsService accounts Generate private key |
23
- | Google OAuth client | console.cloud.google.com → APIs & Services → Credentials |
22
+ | Google OAuth client | console.cloud.google.com → APIs & Services Credentials (used for both dashboard sign-in and Google Drive) |
24
23
 
25
24
  ---
26
25
 
@@ -78,9 +77,9 @@ The zip is ~67 MB. Upload it to Hostinger via SFTP to `~/uploads/`.
78
77
  3. **SSH**. hPanel → Advanced → SSH Access → Enable (if not already).
79
78
  Note the port (usually 65002) and username.
80
79
 
81
- 4. **Upload secrets** via hPanel File Manager (or SFTP):
82
- - Upload `firebase-credentials.json` to `~/` (not public_html). We'll
83
- move it in step 3.
80
+ 4. **Upload the deploy zip** via hPanel File Manager (or SFTP) to
81
+ `~/uploads/`. (No Firebase credentials file is needed auth is Google
82
+ Socialite + Sanctum, configured entirely via `.env`.)
84
83
 
85
84
  ---
86
85
 
@@ -108,14 +107,6 @@ rm -rf public_html
108
107
  ln -s app/public public_html
109
108
  ```
110
109
 
111
- Drop in the Firebase credentials file:
112
-
113
- ```bash
114
- mkdir -p ~/domains/nativeupdatebe.aoneahsan.com/app/storage
115
- mv ~/firebase-credentials.json ~/domains/nativeupdatebe.aoneahsan.com/app/storage/
116
- chmod 600 ~/domains/nativeupdatebe.aoneahsan.com/app/storage/firebase-credentials.json
117
- ```
118
-
119
110
  Configure the environment:
120
111
 
121
112
  ```bash
@@ -150,14 +141,17 @@ FILESHUB_BASE_URL=https://fileshub.zaions.com
150
141
  FILESHUB_API_KEY=_________
151
142
  FILESHUB_APP_ID=native-update
152
143
 
153
- # Firebase
154
- FIREBASE_PROJECT_ID=_________
155
- FIREBASE_CREDENTIALS_PATH=storage/firebase-credentials.json
144
+ # Sanctum (OAuth-issued bearer tokens)
145
+ SANCTUM_TOKEN_EXPIRATION=10080 # minutes (7 days)
146
+
147
+ # Frontend (for OAuth redirect back to the dashboard SPA)
148
+ FRONTEND_URL=https://nativeupdate.aoneahsan.com
156
149
 
157
- # Google OAuth (for Google Drive integration in dashboard)
150
+ # Google OAuth — sign-in (Socialite) AND Google Drive integration
158
151
  GOOGLE_CLIENT_ID=_________
159
152
  GOOGLE_CLIENT_SECRET=_________
160
- GOOGLE_REDIRECT_URI=${APP_URL}/api/dashboard/google-drive/callback
153
+ GOOGLE_REDIRECT_URI=${APP_URL}/api/auth/google/callback
154
+ GOOGLE_DRIVE_REDIRECT_URI=${APP_URL}/api/dashboard/google-drive/callback
161
155
 
162
156
  # PayPal (live)
163
157
  PAYPAL_MODE=live
@@ -182,9 +176,13 @@ php artisan key:generate --force
182
176
  find . -type d -exec chmod 755 {} \;
183
177
  find . -type f -exec chmod 644 {} \;
184
178
  chmod -R 775 storage bootstrap/cache
185
- chmod 600 .env storage/firebase-credentials.json
179
+ chmod 600 .env
186
180
  ```
187
181
 
182
+ > The full, authoritative env contract (every `[REQUIRED]`/`[OPTIONAL]` key with its purpose)
183
+ > is `backend/.env.example`. Populate the server `.env` from it — an incomplete `.env` (missing
184
+ > a required key) is a common cause of a booting-but-500 backend.
185
+
188
186
  Run migrations and cache config for production:
189
187
 
190
188
  ```bash
@@ -204,9 +202,10 @@ curl -sS https://nativeupdatebe.aoneahsan.com/api/health
204
202
  ```
205
203
 
206
204
  Log in to Nova at `https://nativeupdatebe.aoneahsan.com/nova` with an
207
- email listed in `ADMIN_EMAILS` (Firebase-authenticated via the website
208
- dashboard) and verify the Apps / Builds / ApiKeys / SigningKeys /
209
- Subscriptions resources render.
205
+ email listed in `ADMIN_EMAILS` (sign in via Google — Socialite issues the
206
+ Sanctum session; the first sign-in by an `ADMIN_EMAILS` address is granted
207
+ the `super-admin` role) and verify the Apps / Builds / ApiKeys /
208
+ SigningKeys / Subscriptions resources render.
210
209
 
211
210
  ---
212
211
 
@@ -243,12 +242,15 @@ Should contain `PayPal webhook received` or `PayPal subscription activated`.
243
242
 
244
243
  ---
245
244
 
246
- ## 5. (Optional) Cron for scheduled tasks
245
+ ## 5. Cron for scheduled tasks (REQUIRED as of v3.1.0)
247
246
 
248
- The current backend has no scheduled jobs. Add a cron only if/when
249
- `app/Console/Kernel.php` grows `$schedule` entries.
247
+ The backend now runs a scheduled job: `analytics:cleanup` (defined in
248
+ `routes/console.php`) prunes old `device_activities` **and**
249
+ `analytics_events` rows monthly. Without the scheduler cron below those
250
+ tables grow unbounded, so this cron is now required, not optional.
250
251
 
251
- hPanel → Advanced → Cron Jobs → Add:
252
+ hPanel → Advanced → Cron Jobs → Add (runs every minute; Laravel's
253
+ scheduler decides internally when each job is actually due):
252
254
 
253
255
  ```
254
256
  * * * * * cd ~/domains/nativeupdatebe.aoneahsan.com/app && php artisan schedule:run >/dev/null 2>&1
@@ -270,16 +272,15 @@ mv app app.old
270
272
  mkdir app && cd app
271
273
  unzip -q ~/uploads/nu-backend-NEW.zip -d .
272
274
 
273
- # Carry over secrets + credentials
275
+ # Carry over secrets + stored files
274
276
  cp ../app.old/.env .env
275
- cp ../app.old/storage/firebase-credentials.json storage/firebase-credentials.json
276
277
  cp -a ../app.old/storage/app storage/ 2>/dev/null || true
277
278
 
278
279
  # Fix perms
279
280
  find . -type d -exec chmod 755 {} \;
280
281
  find . -type f -exec chmod 644 {} \;
281
282
  chmod -R 775 storage bootstrap/cache
282
- chmod 600 .env storage/firebase-credentials.json
283
+ chmod 600 .env
283
284
 
284
285
  # Rebuild caches + apply migrations
285
286
  php artisan migrate --force
@@ -318,12 +319,52 @@ Migrations that were applied on the new release may need a manual
318
319
 
319
320
  ## 8. Known Hostinger constraints
320
321
 
321
- - **No persistent queue workers.** The backend uses `QUEUE_CONNECTION=database`
322
- and currently dispatches nothing async. If that changes, add a 1-minute
323
- cron running `php artisan queue:work --stop-when-empty`.
324
- - **No Redis.** Cache + sessions use the MySQL `CACHE_STORE=database` driver.
325
- - **PHP 8.2 is the stable default.** PHP 8.3 is available but untested.
322
+ - **No persistent queue workers needed.** The backend uses
323
+ `QUEUE_CONNECTION=database`, but the only async work the update-check
324
+ device-activity + analytics writes is dispatched with
325
+ `dispatch(...)->afterResponse()`, which runs **in-process** during the
326
+ request's terminating phase (no `queue:work` daemon required). If a
327
+ future feature dispatches a real queued job, add a 1-minute cron running
328
+ `php artisan queue:work --stop-when-empty`.
329
+ - **No Redis.** Cache + sessions use the MySQL `CACHE_STORE=database`
330
+ driver. The v3.1.0 latest-build cache (`App::getLatestBuildForChannel`,
331
+ 45s TTL) works with any driver, including `database` and `file`.
332
+ - **PHP 8.3+ is required** (Laravel 13 / `composer.json` `php: ^8.3`).
333
+ Select PHP 8.3 or newer in hPanel → Advanced → PHP Configuration before
334
+ deploying; PHP 8.2 will fail to boot the framework.
326
335
  - **Node/npm are not available via SSH on all plans.** The Vite build step
327
336
  runs locally; the zip ships pre-built `public/build/` assets.
328
337
  - **Nova admin assets** are served from `public/vendor/nova/...` after
329
338
  `php artisan nova:publish` — re-run after every deploy.
339
+
340
+ ---
341
+
342
+ ## 9. v3.1.0 deploy notes
343
+
344
+ This release adds one migration and shifts two hot-path writes; nothing in
345
+ the standard deploy flow above changes, but confirm each of these:
346
+
347
+ 1. **Run the new migration.** `php artisan migrate --force` applies
348
+ `2026_07_02_000001_extend_builds_channel_index` (adds a covering index
349
+ `builds_channel_lookup_idx` on `builds(app_id, channel, status,
350
+ created_at)`). Purely additive — no data change, safe to run live.
351
+ 2. **Re-cache config/routes/views** after the swap (already in the deploy
352
+ steps): `php artisan config:cache && php artisan route:cache &&
353
+ php artisan view:cache`.
354
+ 3. **Confirm the scheduler cron** from section 5 exists — `analytics:cleanup`
355
+ now also prunes `analytics_events`, so the monthly run matters.
356
+ 4. **No queue worker required** — see section 8 (the update-check writes run
357
+ via `afterResponse()`).
358
+
359
+ ### Large bundle downloads (optional)
360
+
361
+ `BundleController@download` streams bundle files through PHP (a
362
+ `StreamedResponse`). This is deliberate: it keeps the signed-URL / auth
363
+ check as the single chokepoint in front of every download. On a server with
364
+ `mod_xsendfile` (Apache) or `X-Accel-Redirect` (nginx), that streaming can
365
+ be offloaded to the web server after the auth check by returning an
366
+ `X-Sendfile` / `X-Accel-Redirect` header instead of the file body — freeing
367
+ the PHP-FPM worker for the duration of the transfer. This is a documented
368
+ option only; it is **not implemented** (Hostinger shared hosting does not
369
+ expose the needed web-server config, and the current streaming approach is
370
+ correct and safe as-is).
@@ -0,0 +1,184 @@
1
+ # Production Deployment Checklist — Native Update Backend (Laravel 13 + Nova 5)
2
+
3
+ **Last updated:** 2026-07-02
4
+ **Scope:** `backend/` only. The plugin (`/`) and website (`website/`) ship via npm/Firebase Hosting respectively and have their own pipelines.
5
+ **Companion:** `docs/deployment/HOSTINGER_DEPLOY.md` (host-specific steps for Hostinger).
6
+
7
+ This checklist is the source of truth for "is this deploy safe to ship?". Run through it on every release until automation in `.github/workflows/release.yml` (Batch 8) replaces the manual gates.
8
+
9
+ > **v3.1.0 deploy notes:** (1) Requires **PHP ≥ 8.3** (Laravel 13). (2) Runs one new migration
10
+ > `2026_07_02_000001_extend_builds_channel_index` (additive covering index — safe live). (3) The
11
+ > latest-build cache (`App::getLatestBuildForChannel`, 45s TTL) works with any `CACHE_STORE` incl.
12
+ > `database`/`file`. (4) The update-check device/analytics writes use `dispatch(...)->afterResponse()`
13
+ > — in-process, **no queue worker required**. (5) `analytics:cleanup` now prunes `analytics_events`
14
+ > too, so the scheduler cron (§5) is **required**, not optional.
15
+
16
+ ---
17
+
18
+ ## 0 · Pre-flight (local machine, before pushing the deploy zip)
19
+
20
+ - [ ] `git status` is clean on the branch you're shipping from.
21
+ - [ ] `git pull --rebase` against the deploy branch — no unmerged remote work.
22
+ - [ ] `composer install --no-interaction` succeeds.
23
+ - [ ] `php artisan test` is **green** (all Feature + Unit tests pass).
24
+ - [ ] `php artisan route:list --except-vendor` shows the routes you expect (no accidental new public routes).
25
+ - [ ] `php -l app/` and `php -l routes/` report no syntax errors.
26
+
27
+ ---
28
+
29
+ ## 1 · `.env` for production (NOT committed; copied to server)
30
+
31
+ The committed `.env.example` has `[REQUIRED]` tags on every var. On the server, populate a real `.env` with the production values. Verify each of these is set correctly:
32
+
33
+ - [ ] `APP_ENV=production`
34
+ - [ ] `APP_DEBUG=false` — **never** `true` in production (leaks stack traces, env, DB creds).
35
+ - [ ] `APP_KEY` — generated once via `php artisan key:generate` on the server (or copied from a sealed vault). Never re-rotate without re-encrypting cookies/sessions.
36
+ - [ ] `APP_URL=https://nativeupdatebe.aoneahsan.com`
37
+ - [ ] `LOG_CHANNEL=daily`, `LOG_LEVEL=warning` (or `error`) — `debug` floods disk and leaks request shapes.
38
+ - [ ] `CORS_ALLOWED_ORIGINS=https://nativeupdate.aoneahsan.com[,...]` — explicit list, no wildcards.
39
+ - [ ] DB creds (`DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`) — production DB, not staging.
40
+ - [ ] FilesHub: `FILESHUB_API_KEY`, `FILESHUB_BASE_URL`, `FILESHUB_APP_ID=native-update`.
41
+ - [ ] Sanctum: `SANCTUM_TOKEN_EXPIRATION=10080` (minutes — 7 days; tune for security/UX trade-off).
42
+ - [ ] Google OAuth (Socialite sign-in + Drive picker): `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI=${APP_URL}/api/auth/google/callback`, `GOOGLE_DRIVE_REDIRECT_URI=${APP_URL}/api/dashboard/google-drive/callback`. Both redirect URIs must be registered in Google Cloud Console for the OAuth client.
43
+ - [ ] PayPal: `PAYPAL_MODE=live`, `PAYPAL_LIVE_*` filled, `PAYPAL_PLAN_PRO`, `PAYPAL_PLAN_ENTERPRISE`, `PAYPAL_WEBHOOK_ID`.
44
+ - [ ] RBAC bootstrap: `ADMIN_EMAILS=ahsan@…[,…]` — first sign-in by any of these emails auto-assigns `super-admin` via spatie/laravel-permission.
45
+ - [ ] Cache + queue: `CACHE_STORE=redis` (recommended for prod), `QUEUE_CONNECTION=redis` if Redis is available. Keep `database` only on tiny single-server deploys, and ensure `queue:work` is daemonized (see step 4).
46
+ - [ ] File permissions on `.env`: `chmod 640` and owner = web user. NEVER world-readable.
47
+
48
+ ---
49
+
50
+ ## 2 · Deploy artifact (zip)
51
+
52
+ The `backend/CLAUDE.md` "Production Deployment Zip Standard" section is the canonical zip recipe. Quick version:
53
+
54
+ ```bash
55
+ cd backend
56
+ php artisan optimize:clear
57
+ composer install --no-dev --optimize-autoloader --classmap-authoritative
58
+ npm ci && npm run build # builds Vite assets if Nova-themed
59
+ # zip into ../production-deploy/backend-production-YYYYMMDD-HHMMSS.zip
60
+ ```
61
+
62
+ After zipping:
63
+ ```bash
64
+ composer install # restore dev deps locally so tests still work
65
+ ```
66
+
67
+ - [ ] Zip excludes `tests/`, `node_modules/`, `.git/`, `*.sqlite`, `storage/logs/*.log`, `storage/framework/{cache/data,sessions,views}/*`.
68
+ - [ ] Zip includes `vendor/` (production-only), built `public/build/` Vite assets, `composer.lock`, `package-lock.json`.
69
+
70
+ ---
71
+
72
+ ## 3 · On-server deploy (after upload + extract)
73
+
74
+ Run these in order on the server, as the web user:
75
+
76
+ ```bash
77
+ # 1. Install production deps if you didn't ship vendor/
78
+ composer install --no-dev --optimize-autoloader
79
+
80
+ # 2. Build front-end assets if not pre-built (yarn, not npm; usually pre-built in the zip)
81
+ yarn install && yarn build
82
+
83
+ # 3. Run migrations against production DB (forced — no prompt)
84
+ php artisan migrate --force
85
+
86
+ # 4. Symlink storage if first deploy
87
+ php artisan storage:link
88
+
89
+ # 5. Cache config + routes + views (don't skip — speeds boot 5–10x)
90
+ php artisan config:cache
91
+ php artisan route:cache
92
+ php artisan view:cache
93
+
94
+ # 6. Refresh permissions on storage + bootstrap/cache
95
+ chown -R www-data:www-data storage bootstrap/cache
96
+ chmod -R u+rwX,g+rX,o-rwx storage bootstrap/cache
97
+ ```
98
+
99
+ - [ ] `php artisan about` reports `APP_DEBUG=false`, correct DB, correct queue/cache drivers.
100
+ - [ ] `php artisan health-check` (or hit `/up`) returns 200.
101
+ - [ ] Curl an API endpoint with a known-bad token — expect `401`, not a stack trace.
102
+
103
+ ---
104
+
105
+ ## 4 · Long-running processes (must be daemonized)
106
+
107
+ `QUEUE_CONNECTION=database` (or `redis`) means jobs only run when a worker is alive. Without this, PayPal webhook handling, future analytics rollups, etc. will pile up silently.
108
+
109
+ - [ ] systemd unit OR supervisor entry that runs `php artisan queue:work --tries=3 --max-time=3600` on boot.
110
+ - [ ] Worker auto-restarts on failure.
111
+ - [ ] Worker reload on deploy: `php artisan queue:restart` is run at end of step 3.
112
+ - [ ] Log rotation configured for `storage/logs/laravel-*.log` (Laravel's `daily` channel rotates by date but doesn't prune).
113
+
114
+ If using Horizon (Redis):
115
+ - [ ] `horizon` service is up.
116
+ - [ ] `/horizon` route is admin-gated (NOT publicly accessible).
117
+
118
+ ---
119
+
120
+ ## 5 · Scheduler cron (if using `app/Console/Kernel.php` schedule)
121
+
122
+ Every Laravel project that uses `Schedule::command(...)` needs:
123
+
124
+ ```cron
125
+ * * * * * cd /var/www/nativeupdatebe && php artisan schedule:run >> /dev/null 2>&1
126
+ ```
127
+
128
+ - [ ] Cron entry exists for the web user.
129
+ - [ ] `php artisan schedule:list` shows the expected scheduled jobs.
130
+
131
+ ---
132
+
133
+ ## 6 · Security gates
134
+
135
+ - [ ] HTTPS is forced at the web-server level (nginx 301 from `:80`, or Cloudflare full-strict).
136
+ - [ ] HSTS header is set with `max-age=31536000; includeSubDomains; preload`.
137
+ - [ ] `/.env`, `/storage/`, `/.git/`, `/composer.json` return 404 over HTTP (not the file). Test with `curl -I`.
138
+ - [ ] `/nova` is reachable but rejects non-super-admin users (test with a `user`-role account → redirect / 403).
139
+ - [ ] `/horizon` (if used) is admin-gated.
140
+ - [ ] PayPal webhook (`/api/webhooks/paypal`) verifies signatures — test by POSTing junk; expect 401.
141
+ - [ ] Rate-limit on `/api/v1/updates/check` (configured via `throttle:` middleware) — verify by sending 60+ requests; expect 429.
142
+ - [ ] CORS preflight: `curl -X OPTIONS -H "Origin: https://evil.example" https://nativeupdatebe.aoneahsan.com/api/v1/updates/check` returns no `Access-Control-Allow-Origin` for the bogus origin (config/cors.php uses an explicit allowlist).
143
+ - [ ] RBAC bootstrap: every email listed in `ADMIN_EMAILS` will auto-receive the `super-admin` role on first sign-in. Verify the list matches the product stance (invite-only via `ADMIN_EMAILS` + manual `php artisan native-update:role-assign` for adds; open signup = leave `ADMIN_EMAILS` empty so everyone joins as `user`).
144
+
145
+ ---
146
+
147
+ ## 7 · Post-deploy smoke
148
+
149
+ - [ ] Sign in via Google OAuth on the website dashboard — token issued, Nova accessible for any `super-admin`.
150
+ - [ ] Create an App in the dashboard — row appears in DB.
151
+ - [ ] Generate an API key — works.
152
+ - [ ] Hit `/api/v1/updates/check` from a real device or curl with a valid `X-API-Key` and `X-Device-ID` — returns 200 + manifest.
153
+ - [ ] Trigger a PayPal sandbox subscription end-to-end (in sandbox mode) and verify the webhook lands as a row update.
154
+ - [ ] Tail `storage/logs/laravel-$(date +%F).log` for 5 minutes — no `error`/`emergency` lines.
155
+
156
+ ---
157
+
158
+ ## 8 · Rollback plan
159
+
160
+ - [ ] Previous deploy's zip is preserved in `production-deploy/` (immutable artifact name).
161
+ - [ ] DB migrations were reversible OR a snapshot was taken pre-migration.
162
+ - [ ] Rollback procedure is one of: `(a)` swap symlinks back to the prior release dir, `(b)` re-extract the prior zip.
163
+ - [ ] `queue:restart` is run after rollback so workers pick up the prior code path.
164
+
165
+ ---
166
+
167
+ ## 9 · Sign-off
168
+
169
+ | Field | Value |
170
+ |---|---|
171
+ | Release tag | _e.g. `backend-v1.4.0`_ |
172
+ | Deployed at | _UTC timestamp_ |
173
+ | Deployed by | _name + git commit SHA_ |
174
+ | Database snapshot | _path / id_ |
175
+ | Smoke-test result | _link to log_ |
176
+ | Approver | _name_ |
177
+
178
+ Append this row to `docs/deployment/DEPLOY-LOG.md` after each deploy.
179
+
180
+ ---
181
+
182
+ ## Future automation (Batch 8)
183
+
184
+ This manual checklist will be reduced once `.github/workflows/release.yml` automates: artifact build, test gate, deployment-zip creation, and tag-pinned publish. Items in §1 (env), §6 (security gates), and §7 (post-deploy smoke) will remain manual because they touch live secrets and live traffic.
@@ -0,0 +1,201 @@
1
+ # Documentation Site — Batch Plan
2
+
3
+ **Goal**: Ship a complete, public, SEO-ready Docusaurus documentation site for `native-update` v3.x in 10 batches. Each batch = one prompt = one commit per affected repo. Resumable via `tracker.json`.
4
+
5
+ **Two repos affected**:
6
+ 1. `native-update/` (this repo) — owns the plan + tracker. Single planning commit per batch.
7
+ 2. `native-update-docs/` (sibling, separate public GitHub repo) — owns the actual docs site. One commit per batch in this repo.
8
+
9
+ **Cooldown after final batch**: 7 days. After all 10 batches complete, this prompt becomes a no-op until 7 days have passed (matches the project-wide `production-readiness-audit-tracker.json` pattern).
10
+
11
+ ---
12
+
13
+ ## Skill bindings (apply per batch where listed)
14
+
15
+ | Domain | Skill |
16
+ |---|---|
17
+ | Diátaxis info architecture | `documentation-writer` |
18
+ | Technical writing voice | `technical-writing` |
19
+ | AI-citable structure | `ai-seo` |
20
+ | Marketing landing copy | `copywriting` |
21
+ | Broad SEO + GSC | `seo` |
22
+ | Firebase Hosting setup | `firebase-hosting-basics` |
23
+ | Firebase config/CLI | `firebase-basics` |
24
+
25
+ Invoke matching skills BEFORE the first Edit/Write of each batch.
26
+
27
+ ---
28
+
29
+ ## Batch 1 — Foundation & first pages ✅ (this batch)
30
+
31
+ **Skills**: `documentation-writer`, `ai-seo`, `copywriting`
32
+
33
+ **In `native-update`**:
34
+ - `docs/docs-site/scope.md` — what we document, locked
35
+ - `docs/docs-site/plan.md` — this file
36
+ - `docs/docs-site/tracker.json` — JSON status, resumable
37
+ - Update root `CLAUDE.md` + `AGENTS.md` with a "Docs Site" record pointing at the tracker
38
+
39
+ **In `native-update-docs/` (new sibling)**:
40
+ - Init: `package.json`, `tsconfig.json`, `.gitignore`, `.editorconfig`
41
+ - `docusaurus.config.ts` — brand metadata, SEO defaults, OG image, Ahsan author footer
42
+ - `sidebars.ts` — full target structure (placeholders for sections written in later batches)
43
+ - `src/css/custom.css` — brand color palette + dark-mode tuning
44
+ - `src/pages/index.tsx` — homepage (hero + features + CTA)
45
+ - `static/img/logo.svg`, `static/img/favicon.svg`, `static/img/social-card.svg`
46
+ - `static/robots.txt` (skeleton — full allow-list ships in Batch 10)
47
+ - `docs/intro.md` — "What is native-update?" (definition-first, 600+ words)
48
+ - `docs/getting-started/installation.md` — install steps, peer-dep note, platform setup quick reference
49
+ - `docs/getting-started/quick-start.md` — 5-minute first OTA update tutorial
50
+ - `docs/about-the-author.md` — Ahsan Mahmood credits page (links, contact)
51
+ - `README.md`, `CLAUDE.md`, `AGENTS.md` — repo metadata + freshness rules
52
+ - `yarn install`, `git init`, first commit
53
+ - `~/.dev-ports.json` — register port 5960
54
+
55
+ **Verification**: `yarn build` (in sibling) exits 0; `yarn typecheck` (if available) exits 0; tracker updated.
56
+
57
+ ---
58
+
59
+ ## Batch 2 — SDK Reference: Live Update (OTA)
60
+
61
+ **Skills**: `documentation-writer`, `ai-seo`
62
+
63
+ Write `docs/reference/sdk/live-update/`:
64
+ - `overview.md` — what live-update does, when to use it
65
+ - `methods.md` — all 20 methods grouped (lifecycle, channels, downloads, validation, cancellation), each with TypeScript signature + parameters table + return type + example + errors thrown
66
+ - `types.md` — `BundleInfo`, `SyncOptions`, `SyncResult`, `DownloadOptions`, `LatestVersion`, `DeleteOptions`, `ValidateOptions`, `ValidationResult`, `CheckForUpdateResult`, `DownloadUpdateOptions`
67
+ - `enums.md` — `UpdateStrategy`, `UpdateMode`, `BundleStatus`, `SyncStatus`
68
+ - `events.md` — `downloadProgress`, `updateStateChanged`
69
+ - `config.md` — `LiveUpdateConfig` field-by-field
70
+
71
+ Estimated: 8–10 pages, ~6,000 words total.
72
+
73
+ ---
74
+
75
+ ## Batch 3 — SDK Reference: App Update + App Review
76
+
77
+ **Skills**: `documentation-writer`, `ai-seo`
78
+
79
+ Write `docs/reference/sdk/app-update/` (5 methods, AppUpdateInfo, OpenAppStoreOptions, InstallStatus enum, 6 events) and `docs/reference/sdk/app-review/` (2 methods, AppReviewConfig, ReviewResult, CanRequestReviewResult, throttling rules).
80
+
81
+ Estimated: 7–8 pages.
82
+
83
+ ---
84
+
85
+ ## Batch 4 — SDK Reference: Background Updates + Security + Core
86
+
87
+ **Skills**: `documentation-writer`, `ai-seo`
88
+
89
+ Write `docs/reference/sdk/background-update/` (8 methods, BackgroundUpdateConfig, NotificationPreferences, 2 events, BackgroundUpdateType + NotificationPriority enums), `docs/reference/sdk/security/` (getSecurityInfo, SecurityConfig, ChecksumAlgorithm, CertificatePinning, UpdateErrorCode 20+ codes), `docs/reference/sdk/core/` (initialize/isInitialized/reset/cleanup/configure + PluginInitConfig).
90
+
91
+ Estimated: 9–11 pages.
92
+
93
+ ---
94
+
95
+ ## Batch 5 — CLI Reference
96
+
97
+ **Skills**: `documentation-writer`, `technical-writing`
98
+
99
+ Write `docs/reference/cli/`:
100
+ - `overview.md` — install, global flags, exit codes
101
+ - `init.md`, `keys-generate.md`, `bundle-create.md`, `bundle-sign.md`, `bundle-verify.md`, `server-start.md`, `monitor.md`, `backend-create.md`
102
+
103
+ Each command page: synopsis, flags table, examples, common errors.
104
+
105
+ Estimated: 9 pages.
106
+
107
+ ---
108
+
109
+ ## Batch 6 — Backend setup guides
110
+
111
+ **Skills**: `documentation-writer`, `technical-writing`
112
+
113
+ Write `docs/backend/`:
114
+ - `overview.md` — when to self-host, hosted SaaS comparison
115
+ - `laravel-nova-self-host.md` — full setup (env, migrations, queues, signing keys, Nova auth, Firebase token verification)
116
+ - `node-express-minimal.md` — based on `example-apps/node-express`
117
+ - `api-contract.md` — every public endpoint, request/response shape, signing
118
+ - `nova-admin-overview.md` — what each Nova resource manages
119
+
120
+ Estimated: 5 pages, dense.
121
+
122
+ ---
123
+
124
+ ## Batch 7 — Platform guides
125
+
126
+ **Skills**: `documentation-writer`, `technical-writing`
127
+
128
+ Write `docs/platforms/`:
129
+ - `android.md` — manifest additions, permissions, ProGuard rules, WorkManager constraints, signing setup
130
+ - `ios.md` — Info.plist keys, capabilities, background modes, App Store Review setup
131
+ - `web.md` — browser dev fallback, limitations, when to use
132
+
133
+ Estimated: 3 long pages (~2,000 words each).
134
+
135
+ ---
136
+
137
+ ## Batch 8 — Tutorials & how-to guides
138
+
139
+ **Skills**: `documentation-writer`, `ai-seo`, `copywriting`
140
+
141
+ Write `docs/tutorials/` and `docs/how-to/`:
142
+ - Tutorial: end-to-end first OTA update (install → keypair → bundle → sign → upload → device verifies → applies)
143
+ - Tutorial: backend-first walkthrough (Laravel install → first app → first build → first device check)
144
+ - How-to: manage release channels (production/staging/beta)
145
+ - How-to: rotate signing keys without breaking active bundles
146
+ - How-to: roll back a bad bundle
147
+ - How-to: migrate from CodePush
148
+ - How-to: integrate with CI/CD (GitHub Actions example)
149
+ - How-to: test bundles in development
150
+
151
+ Estimated: 8 pages.
152
+
153
+ ---
154
+
155
+ ## Batch 9 — Concepts & explanations
156
+
157
+ **Skills**: `documentation-writer`, `ai-seo`
158
+
159
+ Write `docs/concepts/`:
160
+ - `how-ota-updates-work.md`
161
+ - `bundle-integrity-and-signing.md`
162
+ - `update-strategies-compared.md` (immediate vs background vs manual)
163
+ - `architecture.md` (with mermaid diagrams)
164
+ - `security-model.md`
165
+ - `error-handling-philosophy.md`
166
+
167
+ Estimated: 6 pages, deeper writing.
168
+
169
+ ---
170
+
171
+ ## Batch 10 — SEO + Firebase deploy + GitHub publish
172
+
173
+ **Skills**: `seo`, `ai-seo`, `firebase-hosting-basics`, `firebase-basics`
174
+
175
+ - Per-page meta head injection (canonical, OG, Twitter Card) via `docusaurus.config.ts`
176
+ - `static/robots.txt` final form (full AI-bot allow list)
177
+ - `static/llms.txt` + `static/llms-full.txt`
178
+ - `static/humans.txt`, `static/.well-known/security.txt`
179
+ - `static/sitemap-index.json`
180
+ - JSON-LD injection per page (TechArticle + FAQPage where applicable)
181
+ - `firebase.json`, `.firebaserc`, hosting config
182
+ - GitHub Actions workflow: build + deploy on push to `main`
183
+ - README publish instructions (GH + Firebase + Search Console + Bing Webmaster)
184
+ - Update tracker `last_run.completed_at` and `next_allowed_run_after` (today + 7 days)
185
+ - Final commit in both repos
186
+
187
+ Estimated: 1 dense pass.
188
+
189
+ ---
190
+
191
+ ## Resumability protocol (for future runs of this prompt)
192
+
193
+ When this prompt is re-run:
194
+
195
+ 1. Read `docs/docs-site/tracker.json`.
196
+ 2. If `last_run.status == "complete"` AND today < `last_run.next_allowed_run_after` → SKIP. Tell the user "Docs site is complete; next allowed run after `<date>`. Use the docs site or open an issue if anything is missing."
197
+ 3. If `last_run.status == "in_progress"` → find the lowest-indexed batch with `status != "completed"` in `batches[]` and resume there. Do NOT redo earlier batches.
198
+ 4. After completing each batch: append a row to `batches[]`, update `current_batch` and `progress_pct`. ONE commit per batch in each affected repo.
199
+ 5. After Batch 10: set `last_run.status = "complete"`, `last_run.completed_at = today`, `last_run.next_allowed_run_after = today + 7 days`.
200
+
201
+ **Override conditions** (run a fix-only batch even within cooldown): explicit user bypass; broken `yarn build` in sibling repo; production incident; published page returns 404 or 5xx; Lighthouse SEO drops below 95.