19 — Production go-live checklist
The operational contract between the Release owner (Abhijit) and DevOps for putting Swasti V3 into production. Read alongside note 14 — Repos & deployment (env/branch map) and note 15 — Release runbook (the staging mechanics).
Two repos, two halves:
- Mobile app —
frappe_mform_swasti_app. DevOps builds the prod AAB offmainand uploads it to the Play Store. - Backend —
frappe_mform_swasti. Deployed toswasti.mform.in.
Legend: 👤 = Release owner · 🛠️ = DevOps · [ ] = gate to tick.
Credentials are NOT in this document. Prod Frappe admin login and the Play-review login are shared separately/securely — this KB page is a shared link.
🚨 0. Pre-build blockers (fix BEFORE the prod build)
These are real, currently-open in the repo. The prod build is not shippable until all three are cleared.
- 🛠️ Release signing key. The Gradle wiring is now in place —
android/app/build.gradle.ktsloads an upload keystore fromandroid/key.propertiesand only falls back to debug signing when that file is absent. Remaining (DevOps): generate the upload keystore, drop inandroid/key.properties(gitignored, DevOps-held), build the signed AAB, and enrol in Play App Signing. Full steps in Appendix B below. Reuse the same upload key for every future release — and back it up (losing it blocks app updates). - 👤 Prod API URL — done.
env/prod.jsonnow points tohttps://swasti.mform.in(was a placeholder). Reachesmainvia the promotion flow. - ✅
google-services.json— not required. Thecom.google.gms.google-servicesGradle plugin is not applied, so the build never consumes it and Firebase isn’t wired into the app at runtime. Firebase is used only for App Distribution (staging/uat tester drops, via CLI); prod ships via the Play Store, so no prodgoogle-services.json/ prod Firebase app is needed.
1. Pre-go-live gates (all green before promoting)
- 👤 UAT verified + sign-off captured (PM/client). Link the sign-off.
- 👤 All prod-scope SWF tickets closed or explicitly deferred; no open blockers.
- 👤 Known-open items accepted in writing (e.g. any SWF still pending — call them out so they’re not a surprise in prod).
- 👤 Version decided.
versionName+versionCode. Play Store requiresversionCodestrictly greater than the last production upload. (App readspubspecversion viaappVersionProvider— never hardcode.) - 👤 “What’s new” / release notes drafted (per locale).
2. Code freeze & promotion to main (👤)
- App:
uat→mainPR raised, reviewed, merged.mainis the prod source of truth (PR-only — never push straight tomain/uat). - Tag the app prod commit (e.g.
v1.0.0) so the exact build is reproducible. - Backend: confirm the prod commit on
frappe_mform_swasti(deploys offdevelopmentper branch policy) and tag it. - No dev/staging-only artefacts in prod: the pre-filled test surveyor login is dev/staging only — confirm it does not appear in the prod build. Debug logging off; no test flags.
3. Prod build configuration (🛠️ — off main)
- Repo/branch:
frappe_mform_swasti_app@main. - Flavor:
prod→ applicationIdcom.dhwani.swasti, app name “Swasti” (confirmed inbuild.gradle.kts). - Artifact: AAB (Android App Bundle) —
flutter build appbundle --flavor prod --release --dart-define-from-file=env/prod.json. ⚠️--dart-define-from-file=env/prod.jsonis MANDATORY — the backend URL is a--dart-define(String.fromEnvironment('FRAPPE_URL')), and without it the app silently defaults tohttp://swasti.local:8000(local bench) and is completely broken (login fails / points nowhere). Same applies toflutter run. (Not an APK; Play Store needs the bundle.) - Signing: real upload keystore (§0),
versionCodebumped, Play App Signing enrolled. -
env/prod.json→https://swasti.mform.in(§0) is what got built. -
src/prod/google-services.jsonpresent (or confirmed not needed) (§0). - INTERNET permission in
android/app/src/main/AndroidManifest.xml✓ (already present — release builds need it in the main manifest). - R8/minify + resource shrink as configured; smoke-test the release build so obfuscation doesn’t crash anything.
4. Backend prod deploy (🛠️)
- DB backup taken before any migrate.
- Deploy to
swasti.mform.in: pull the prod commit +bench migrate; verify migrate EXIT 0 and run any required patches. - Offline-mode gate: Mobile Configuration
enabled=1+offline_enabled=1on prod — otherwise saves go server-only and never persist offline (known trap). - Roles present:
Swasti Surveyor(data perms) andMobile User(mobile-control login gate) — see note 16. - Masters seeded: geography (state→village), schemes, document masters, option masters, donors/partners.
- 🔑 Geography scoping per surveyor: every prod surveyor MUST have Frappe
User Permissionrows for their assigned geography. Without them, Frappe applies no restriction and a surveyor can pull all members/data via bulk-fetch. Provision and verify per surveyor before they log in. - mobile-control app installed + configured on prod (auth + bulk-fetch endpoints).
5. Play Store listing — assets & metadata (👤 provides → 🛠️ uploads)
Everything DevOps needs to create/update the Play Console listing. Almost all of it is provided below — only the two items marked ⏳ still need input. Full copy in Appendix C; assets in Appendix D.
Store listing text
- App name:
Swasti mForm - Short description:
Offline-first field app for Swasti surveyors — members, health, schemes & more. - Full description: drafted (Appendix C).
- Category: Business · Tags: data collection, field work, NGO
- Contact email + website: DevOps-managed (set in Play Console).
- Privacy policy URL: the DevOps-managed standard Dhwani privacy policy.
Graphic assets
- App icon 512×512:
https://swasti-kb-7930d5fc.pages.dev/store-assets/icon-512.png - Feature graphic 1024×500:
https://swasti-kb-7930d5fc.pages.dev/store-assets/feature-1024x500.png - Phone screenshots: 3 drafts linked (Appendix D) — ⏳ re-shoot clean from a uat/prod build before submission.
- (optional) tablet screenshots / promo video — not needed.
Play Console declarations (🛠️ fills using these answers)
-
Content rating (IARC): Utility / Productivity; no violence, sexual content, profanity, gambling, or user-generated content → Everyone / PEGI 3.
-
Data safety: collected = personal info, demographic, health info, photos/documents — all for app functionality, not shared with third parties, not sold, encrypted in transit, deletion on request. Geography is manually selected — no precise/GPS location. (Full table in Appendix C; must match the privacy policy.)
-
Target audience & content: adults (18+) — internal work app for authorised field staff (not a children’s app).
-
App access (review login): prod demo surveyor created →
playstore.review@swasti.mform.in. Password shared separately with DevOps (not in this public doc) for the Play Console “App access” field. Verified: logs in via the mobile-control endpoint (mobile_control.api.api_auth.login→ HTTP 200 + access token). ⚠️ Scope to a demo geography or disable before real beneficiary data lands at go-live (currently no geography restriction; prod has 0 members today).Mobile-login account recipe (confirmed — no special perms beyond these): enabled
User+ password + rolesMobile User(the actual mobile-login gate —MOBILE_USER_ROLES) +Swasti Surveyor(data perms). 2FA must be off (it is, on prod). That’s the complete set — nothing else is required to log in. See note 16 — surveyor onboarding. -
Ads: none · Countries: India · Pricing: Free.
-
Sensitive permissions / government app: none applicable. App uses INTERNET + camera/storage (document photos); no SMS, call-log, precise-location, or other sensitive permissions; not a government app.
6. Release rollout (🛠️)
- Upload AAB → track: internal → closed → production (or production with staged rollout, recommend 10–20% to start)
- “What’s new” notes attached per locale
- Submit for review (the first production release can take hours–days for Google review)
7. Post-go-live verification (👤 + 🛠️)
- Install from the Play Store on a clean device
- App shows correct version (
appVersionProvider) - Login as a prod surveyor
- Create a member → sync → verify on
swasti.mform.in - Geography scoping: surveyor sees only their geography’s members
- Offline-first: airplane-mode save → reconnect → sync drains
- Smoke each module: Member, Scheme, Health, Livelihood, Document + a follow-up (visit numbering)
- Crashlytics/monitoring: no startup crashes; watch the first hours
8. Rollback / incident
- Play Store: halt the staged rollout; roll back to the previous production release (you can’t instantly “unpublish” — halt + hotfix)
- Backend: restore the pre-migrate DB backup / redeploy the previous commit
- Comms: notify PM/client + testers
9. Sign-off
| Gate | Owner | Status | Date |
|---|---|---|---|
| Pre-build blockers cleared (§0) | 👤/🛠️ | ||
| UAT sign-off | 👤 | ||
Prod build off main (signed AAB) | 🛠️ | ||
| Backend deployed + provisioned | 🛠️ | ||
| Play Store assets + declarations | 👤/🛠️ | ||
| Submitted to production | 🛠️ | ||
| Post-go-live verification | 👤/🛠️ |
Appendix — what DevOps needs from the Release owner (quick handover list)
mainprod commit/tag (app) + backend prod commit/tag.- Upload keystore +
key.properties(or confirm Play App Signing key) — held by DevOps, never in the repo. env/prod.json=https://swasti.mform.in+src/prod/google-services.json(or confirm not needed).- All Play Store assets (icon, feature graphic, screenshots) + listing text. (Privacy policy URL is the DevOps-managed standard Dhwani policy.)
- Data safety + content rating answers.
- Review login (prod/demo surveyor) — shared separately.
- Prod Frappe admin creds — shared separately (not in this doc).
Appendix B — Create the release signing key & build a signed AAB
The Gradle config already supports a real release key — android/app/build.gradle.kts loads android/key.properties and signs release with it; it falls back to the debug key only when that file is absent (so dev/staging builds are unaffected). DevOps does the following on the prod build machine.
1. Generate the upload keystore (one-time)
keytool -genkey -v -keystore ~/swasti-upload.jks \
-keyalg RSA -keysize 2048 -validity 10000 -alias swasti-upload
- Use strong, distinct store + key passwords; store them in the DevOps secret vault.
- Back up the
.jks+ passwords off-machine. If lost, you cannot publish app updates (barring a Play App Signing key reset).
2. Create android/key.properties (gitignored — never commit)
storePassword=<store password>
keyPassword=<key password>
keyAlias=swasti-upload
storeFile=/absolute/path/to/swasti-upload.jks
(key.properties, *.jks, *.keystore are already in .gitignore.)
3. Build the signed AAB (off main, prod flavor)
flutter build appbundle --flavor prod --release --dart-define-from-file=env/prod.json
⚠️ The --dart-define-from-file=env/prod.json is mandatory — it sets FRAPPE_URL=https://swasti.mform.in. Omit it and the build silently defaults to http://swasti.local:8000 (local bench) and won’t work.
→ build/app/outputs/bundle/prodRelease/app-prod-release.aab. Because key.properties is present, this is signed with the upload key, not debug. (Sanity check: keytool -printcert -jarfile <aab> should show the upload cert, not the Android debug cert.)
4. Play App Signing (first release)
- On the first upload to Play Console, opt into Play App Signing: Google holds the app signing key; your keystore is the upload key.
- Every later release must be signed with the same upload key.
versionCodemust strictly increase.
Appendix C — Play Store listing content (DRAFT — 👤 to confirm, 🛠️ to upload)
Drafted copy + form answers. Review/adjust before upload. Anything in [brackets] needs a real value from PM/leadership.
Store listing text
- App name (≤30):
Swasti mForm(alt: “Swasti Field App”) - Short description (≤80):
Offline-first field app for Swasti surveyors — members, health, schemes & more. - Full description (≤4000):
Swasti mForm is the field data-collection app for Swasti’s community programs. It lets authorised field surveyors register members and run program workflows even with no network — data is saved on the device and syncs automatically when a connection is available.
Built for the field • Works fully offline; auto-syncs when back online • One member profile feeds every program • Fast, guided forms with built-in validation
Programs supported • Member registration & profiling • Scheme applications + follow-ups (eligibility-aware) • Health screening, follow-up visits & re-screening • Livelihood (goat-rearing / FPCL) applications & repayment tracking • Document applications & follow-ups
Access: This is a tool for authorised Swasti field staff only and requires a login provided by the program. It is not a consumer app.
- Category: Business (alt: Productivity) · Tags: data collection, field work, NGO
- Contact email: [support email — confirm] · Website: [https://… — confirm]
- Privacy policy URL: the standard Dhwani privacy policy — managed by DevOps (they supply/maintain the URL).
Content rating (IARC questionnaire)
- Category: Utility / Productivity / Communication
- No violence, sexual content, profanity, gambling, or user-to-user content → expected rating Everyone / PEGI 3.
Data safety form (Play Console)
The app collects and transmits the following on behalf of the program:
| Data type | Collected | Purpose | Shared w/ 3rd parties |
|---|---|---|---|
| Personal info (name, DOB, gender, phone, address) | Yes | App functionality (program delivery) | No |
| Demographic (caste, religion, occupation, income) | Yes | App functionality | No |
| Health info (screening readings, conditions) | Yes | App functionality | No |
| Photos/Documents (uploaded evidence) | Yes | App functionality | No |
| Location (geography is manually selected, not GPS/precise) | No precise location | — | No |
- Encryption in transit: Yes (HTTPS).
- Data deletion: users can request deletion via [contact].
- Data is not sold; it is stored in Swasti’s own Frappe backend and used only for program delivery/M&E.
- ⚠️ Confirm these answers with PM — they must match the privacy policy exactly or Play rejects the submission.
App access (for Google review)
Login is required → provide a working review login (a prod/demo surveyor) in the Play Console “App access” section. Shared separately, not in this doc.
Appendix D — Outstanding assets & blockers (status)
| Item | Status | Owner | Note |
|---|---|---|---|
| App name + descriptions | ✅ Drafted (Appendix C) | 👤 confirm | — |
| Content rating + data safety answers | ✅ Drafted (Appendix C) | 👤 confirm | must match privacy policy |
| App icon 512×512 | ✅ Created | 👤 review | store-assets/icon-512.png (also linked below). On-brand placeholder (magenta + leaf, bold “S”) — the prior launcher icon was the stock Flutter logo. Swap for the official brand icon if one exists. |
| Feature graphic 1024×500 | ✅ Created | 👤 review | store-assets/feature-1024x500.png. On-brand placeholder; swap for a designed version if preferred. |
| Phone screenshots (2–8) | ⏳ DRAFTS captured | 👤 | 3 draft shots from the dev build (1080×2280) linked below — they carry a “DEV” ribbon (and Home shows a test-data sync banner), so re-capture from a clean uat/prod build before submission. Target set: (1) Home, (2) Members, (3) Member detail tabs, (4) a form (e.g. Health screening), (5) a follow-up with Visit Number. |
| Privacy policy URL | ✅ Dhwani policy (DevOps-managed) | 🛠️ | Standard Dhwani privacy policy, managed by DevOps — they provide the URL for the listing. No app-specific policy needed. |
| Contact email + website | ❓ Confirm | 👤 | For the store listing. |
Asset downloads (public KB):
- Icon 512×512 —
https://swasti-kb-7930d5fc.pages.dev/store-assets/icon-512.png - Feature graphic 1024×500 —
https://swasti-kb-7930d5fc.pages.dev/store-assets/feature-1024x500.png - Screenshots — DRAFT (dev build; re-shoot clean before submission):
https://swasti-kb-7930d5fc.pages.dev/store-assets/screenshots/01-home.pnghttps://swasti-kb-7930d5fc.pages.dev/store-assets/screenshots/02-members.pnghttps://swasti-kb-7930d5fc.pages.dev/store-assets/screenshots/03-member-detail.png