# Closer — Internal Testing Build Checklist > Steps to prepare, sign, and distribute an internal testing build for the private MVP. Assumes Android Gradle Plugin 8.7.3, Kotlin 2.0.21, minSdk 26, targetSdk/compileSdk 35, and `app.closer` applicationId. Internal testing should verify the product goal: **private, mutual-reveal relationship questions with real encryption and calmer UX**. --- ## 1. Pre-build Checklist ### 1.1 Source readiness - [ ] All feature branches for the MVP merged into the internal testing branch. - [ ] No unintended `TODO` / `FIXME` blockers in release code (documented in `docs/qa/private-mvp-checklist.md`). - [ ] No `com.couplesconnect` package references remain (verified via `grep -RIn` across `app/src`). - [ ] No debug-only logging left in non-debug code paths (verbose/debug logs removed; error logging acceptable). - [ ] Version matches private MVP: `versionName` should be `0.1.x` and `versionCode` incremented for each distributed build. - [ ] `local.properties` contains required secrets but is not committed to git. ### 1.2 Secrets and API keys - [ ] `google-services.json` is present in `app/` and matches the internal testing package (`app.closer`). - [ ] RevenueCat API key defined in `local.properties` as `RC_API_KEY`. - [ ] Firebase App Check debug token removed or disabled for release. - [ ] No hardcoded API keys, tokens, or credentials in Kotlin/XML source. ### 1.3 Build configuration - [ ] `build.gradle.kts` has `isMinifyEnabled = true` and `isShrinkResources = true` for `release`. - [ ] ProGuard rules file (`proguard-rules.pro`) reviewed for Compose, Hilt, Room, Firebase, RevenueCat, and Navigation. - [ ] `compileSdk = 35`, `targetSdk = 35`, `minSdk = 26`. - [ ] `namespace = "app.closer"` and `applicationId = "app.closer"`. - [ ] Kotlin `jvmTarget = "17"` and Java 17 compatibility set. - [ ] `buildConfig = true` and `compose = true` enabled. --- ## 2. Signing Config Checklist ### 2.1 Keystore - [ ] Internal testing keystore generated or available (`.jks` / `.keystore`). - [ ] Keystore password, key alias, and key password stored securely in CI or password manager — not in repo. - [ ] Keystore used for signing is backed up in a secure location (1Password, team vault, hardware token). - [ ] Key validity period covers expected lifetime of the app (Google Play requires validity past 22 Oct 2033 for app signing key uploads). ### 2.2 Gradle signing configuration - [ ] `signingConfigs` block in `app/build.gradle.kts` configured: ```kotlin signingConfigs { create("release") { storeFile = file(System.getenv("KEYSTORE_PATH") ?: "release.keystore") storePassword = System.getenv("KEYSTORE_PASSWORD") keyAlias = System.getenv("KEY_ALIAS") keyPassword = System.getenv("KEY_PASSWORD") } } ``` - [ ] `buildTypes.release` references `signingConfigs.getByName("release")`. - [ ] Local debug builds still use the default debug keystore. ### 2.3 Verify signed APK/AAB - [ ] Build release APK or AAB: `./gradlew :app:assembleRelease` or `:app:bundleRelease`. - [ ] Confirm output is signed: `apksigner verify --verbose app-release.apk`. - [ ] Check certificate fingerprints and expiration. - [ ] Verify v1 (JAR) and v2/v3 APK signatures are present. --- ## 3. Firebase / Production Environment Checklist ### 3.1 Firebase project - [ ] Internal testing Firebase project created/separate from production. - [ ] `app.closer` Android app registered with correct SHA-1/SHA-256 certificates. - [ ] `google-services.json` downloaded and placed in `app/`. ### 3.2 Firebase services - [ ] **Authentication**: Email/password provider enabled (and any OAuth providers used in the app). - [ ] **Firestore**: Security rules reviewed; internal testing rules should match expected MVP rules. - [ ] **Cloud Messaging**: Server key / FCM v1 credentials available for backend/push testing. - [ ] **Crashlytics**: Crashlytics plugin applied and mapping file upload enabled. - [ ] **Analytics**: No PII logged; events reviewed. - [ ] **Remote Config**: Default values in-app handle absent remote values. - [ ] **App Check**: Play Integrity provider configured for release builds; debug provider only for debug/internal. ### 3.3 Firebase secrets - [ ] No Firebase API keys or FCM tokens committed. - [ ] CI injects `google-services.json` or uses environment-based substitution. --- ## 4. Test Account Setup ### 4.1 Device / emulator accounts - [ ] At least two test user accounts available (User A and User B) for couple pairing flows. - [ ] Test accounts use `+` or tagged email addresses for isolation (e.g., `qa+a@closer.app`, `qa+b@closer.app`). - [ ] Passwords stored in team vault; accounts enabled in Firebase Auth allowlist if applicable. ### 4.2 Data seeding - [ ] Seed questions and categories in Firestore/remote config for internal testing. - [ ] Seed at least one premium category and one free category. - [ ] Prepare test RevenueCat products with sandbox pricing. - [ ] Ensure test accounts have predictable subscription states (free, premium, expired). ### 4.3 Test scenarios matrix | Scenario | User A | User B | |----------|--------|--------| | Unpaired new install | fresh account | fresh account | | Paired couple | paired with B | paired with A | | Premium unlock | subscribed | not subscribed | | Different answer states | answered daily | not answered | | Invite expiry | create invite | accept after expiry | --- ## 5. Distribution Checklist ### 5.1 Firebase App Distribution - [ ] Firebase App Distribution Gradle plugin applied (optional but recommended). - [ ] App Distribution configured with tester groups (e.g., `mvp-internal`, `qa-team`). - [ ] Build variant selected: `release` (signed). - [ ] Distribution command run: `./gradlew :app:assembleRelease :app:appDistributionUploadRelease`. - [ ] Testers receive email/notification with download link. - [ ] APK install succeeds and app launches. ### 5.2 Alternative distribution - [ ] If not using App Distribution, use internal Google Play track with closed testing. - [ ] Signed AAB uploaded to Play Console internal testing track. - [ ] Testers added to internal testing list. - [ ] Play Console review status tracked (internal tests may be immediately available). ### 5.3 Verification after install - [ ] App installs and opens on target device. - [ ] Onboarding flow reachable. - [ ] Auth and pairing flows tested end-to-end on distributed build. - [ ] Push notification received and quiet-hours suppression works. - [ ] Paywall loads products in sandbox (where RevenueCat configured). - [ ] Crashlytics reports non-fatal test event and appears in console. --- ## 6. Build Commands Reference ```bash # Debug compile (fast smoke test) ./gradlew :app:compileDebugKotlin # Debug install ./gradlew :app:installDebug # Release APK (signed) ./gradlew :app:assembleRelease # Release AAB (signed) ./gradlew :app:bundleRelease # Firebase App Distribution upload ./gradlew :app:assembleRelease :app:appDistributionUploadRelease ``` --- ## 7. Sign-off | Role | Name | Date | Notes | |------|------|------|-------| | Build engineer | | | | | QA lead | | | | | Product owner | | | |