# Minimum OS versions are appropriately configured

- **Pattern:** `ab-001942` (`mobile-store-readiness.build-config.min-os-version`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001942
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001942)

## Why it matters

Apple and Google enforce minimum OS version floors that increase over time — failing to set an explicit minimum leaves your app exposed to device configurations your dependencies no longer support. Android SDK 21 (Android 5.0), a common implicit default, lacks critical APIs used by modern libraries including SafetyNet, biometric auth APIs, and foreground service types required for background tasks. Google Play enforces a 2-year rolling minimum target-and-minimum policy (android-minimum-target-sdk), rejecting updates that fall below it. On iOS, apps without an explicit `minimumVersion` may be installed on iOS 12 devices where SwiftUI, Combine, and async/await runtime availability differs, producing crashes that reach production users and trigger store review flags from user-reported bugs.

## Severity rationale

High because an unset or too-low minimum OS version causes crashes on unsupported devices and Google Play actively rejects updates that fall below its rolling SDK minimum floor.

## Remediation

Set explicit minimum values in both `app.json` and the Android Gradle file — do not rely on implicit defaults.

```json
// app.json
{
  "expo": {
    "ios": { "minimumVersion": "13.0" }
  }
}
```

```gradle
// android/app/build.gradle
defaultConfig {
  minSdkVersion 24      // Android 7.0
  targetSdkVersion 35
  compileSdkVersion 35
}
```

After updating `minSdkVersion`, run the full test suite on a device or emulator running Android 7.0 (API 24) to catch any API calls that don't exist below your old minimum. Google Play's policy page (external android-minimum-target-sdk) publishes the current floor — check it before every major release cycle.

## Detection

- **ID:** `min-os-version`
- **Severity:** `high`
- **What to look for:** Check `app.json` for `ios.minimumVersion` and `android.minSdkVersion` (in `app.json` or `android/app/build.gradle`). Count the minimum OS version declarations across all config files. iOS minimum should be 13.0 or higher (stores require recent OS). Android minimum should be SDK 24 (Android 7.0) or higher (covers ~99% of active devices).
- **Pass criteria:** minSdkVersion is at least 24 for Android (API 7.0+), and iOS minimum is at least 13.0. Both values must be explicitly set — implicit defaults do not count. Report: "Android minSdkVersion=X, iOS minimum=Y."
- **Fail criteria:** minSdkVersion is below 24 (Android 6.0 or earlier), iOS minimum is below 13.0, or values are missing from configuration.
- **Skip (N/A) when:** Project targets only one platform (check only the targeted platform).
- **Detail on fail:** `"Android minSdkVersion is 21 (Android 5.0) — too old. Stores recommend 24+"` or `"iOS minimum version not specified in app.json"`
- **Remediation:** Minimum OS versions ensure your app runs on supported, secure platforms. Update configuration:
  1. In app.json:
     ```json
     "ios": { "minimumVersion": "13.0" }
     ```
  2. In android/app/build.gradle:
     ```gradle
     android {
       compileSdkVersion 34
       defaultConfig {
         minSdkVersion 24      // Android 7.0
         targetSdkVersion 34
       }
     }
     ```
  3. Choose minimums based on:
     - iOS: 13.0+ (80%+ of active devices)
     - Android: 24+ (SDK 7.0, covers ~99% of active devices)
  4. Update `package.json` and Expo SDK version if targeting older OSes

## External references

- external apple-minimum-os — https://developer.apple.com/news/upcoming-requirements/
- external android-minimum-target-sdk — https://support.google.com/googleplay/android-developer/answer/11926878

Taxons: regulatory-conformance

HTML version: https://auditbuffet.com/patterns/ab-001942
