|
| 1 | +# ADR-0045 — Adopt iOS and iPadOS 15 as the app deployment floor |
| 2 | + |
| 3 | +- Status: **Accepted** |
| 4 | +- Date: 2026-08-27 |
| 5 | +- Extends: [ADR-0044](0044-start-app-v020-beta-train-at-build-5.md) |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +The retained PyBLE `0.2.0 (5)` TestFlight artifact was compiled with an |
| 10 | +iOS/iPadOS deployment target of `13.0`. Transporter accepted the package far |
| 11 | +enough to report advisory `90068`: Apple announced that App Store Connect will |
| 12 | +require `MinimumOSVersion` `15.0` or later beginning in Spring 2027. |
| 13 | + |
| 14 | +The existing IPA validator proved signing, entitlements, nested-code safety, |
| 15 | +and Xcode software-information integrity, but did not enforce a deployment |
| 16 | +floor. Its successful result was therefore compatible with the genuine `13.0` |
| 17 | +value encoded in the app, frameworks, resource bundles, and Mach-O load |
| 18 | +commands. Re-exporting or editing a signed archive cannot change that compiled |
| 19 | +contract safely. |
| 20 | + |
| 21 | +The project can retain iOS/iPadOS 13 and 14 compatibility temporarily, or move |
| 22 | +the maintained source floor to 15 before Apple begins rejecting uploads. The |
| 23 | +maintainer chose the latter so future features and distribution artifacts use |
| 24 | +one forward-compatible default instead of deferring the migration to a release |
| 25 | +deadline. |
| 26 | + |
| 27 | +## Decision |
| 28 | + |
| 29 | +1. **Raise the maintained source floor to 15.0.** Every Runner Xcode build |
| 30 | + configuration MUST set `IPHONEOS_DEPLOYMENT_TARGET` to `15.0`. Generated |
| 31 | + Flutter and Swift-package configuration must inherit that floor rather than |
| 32 | + introducing another authored version literal. |
| 33 | + |
| 34 | +2. **Make the source setting executable.** A repository test MUST enumerate |
| 35 | + every authored Xcode deployment-target declaration, require the expected |
| 36 | + configuration count, and require exact value `15.0`. A missing, duplicate, |
| 37 | + lower, or independently changed configuration fails before merge. |
| 38 | + |
| 39 | +3. **Enforce the compiled application payload.** The exported-IPA gate MUST |
| 40 | + require the top-level application's `MinimumOSVersion` and main Mach-O |
| 41 | + build-version command to encode an iOS minimum of at least `15.0`. A bundled |
| 42 | + dependency may retain a lower compatibility floor because it can still run |
| 43 | + inside a higher-floor application; it does not lower the application's |
| 44 | + installation requirement. This extends rather than replaces the existing |
| 45 | + signature, nested-code, and Xcode software-information checks. |
| 46 | + |
| 47 | +4. **Require a clean rebuild.** A deployment-floor change MUST rebuild and |
| 48 | + re-archive the application and all embedded content from source. Editing an |
| 49 | + `Info.plist`, Mach-O load command, archive, or IPA after compilation/signing, |
| 50 | + or merely re-exporting an older archive, is prohibited. |
| 51 | + |
| 52 | +5. **Preserve build 5 as history.** The retained `0.2.0 (5)` IPA, checksum, |
| 53 | + archive, source commit, and TestFlight plan continue to describe the exact |
| 54 | + iOS/iPadOS 13 artifact submitted through Transporter. They MUST NOT be |
| 55 | + relabelled as iOS/iPadOS 15. |
| 56 | + |
| 57 | +6. **Do not create build 6 in this change.** The package identity remains |
| 58 | + `0.2.0+5` because this source-only change is not an external candidate or |
| 59 | + store upload. A later external artifact MUST receive the next globally |
| 60 | + monotonic build number under ADR-0044 and complete its own validation and |
| 61 | + handoff record. |
| 62 | + |
| 63 | +## Consequences |
| 64 | + |
| 65 | +- Future PyBLE iOS and iPadOS builds install only on version 15.0 or later; |
| 66 | + devices limited to versions 13 and 14 cannot install or update to those |
| 67 | + builds. |
| 68 | +- The existing build-5 TestFlight artifact remains eligible on its encoded |
| 69 | + platform range and remains distinguishable from any later candidate. |
| 70 | +- Store validation will fail locally if a project configuration or the |
| 71 | + compiled top-level application regresses below the maintained floor. |
| 72 | +- Raising the deployment floor changes no PBLE/1 behavior, firmware baseline, |
| 73 | + application feature, Android minimum, or current app version/build identity. |
| 74 | + |
| 75 | +## Alternatives considered |
| 76 | + |
| 77 | +- **Wait until Spring 2027.** Temporarily preserves iOS/iPadOS 13 and 14 for |
| 78 | + new builds, but leaves a known distribution migration on the critical path |
| 79 | + and permits new features to keep treating the older floor as the default. |
| 80 | +- **Patch or re-export build 5.** Rejected because the minimum is compiled into |
| 81 | + Mach-O load commands as well as bundle metadata, and because an uploaded |
| 82 | + build identity and signed historical artifact must remain immutable. |
| 83 | +- **Upload build 6 immediately.** Rejected for this change because the |
| 84 | + maintainer requested a future-source default only; external candidate |
| 85 | + creation, physical acceptance, and TestFlight upload remain separate work. |
| 86 | +- **Set only Release to 15.0.** Rejected because Debug/Profile divergence would |
| 87 | + hide compatibility failures during development and testing. |
| 88 | + |
| 89 | +## Related |
| 90 | + |
| 91 | +- [App build and distribution requirements](../specifications/App/specs.md#9-build-versioning--distribution--bld) |
| 92 | +- [App test design](../specifications/App/TDD.md#159-ios-and-ipados-deployment-floor-gate) |
| 93 | +- [Build 5 TestFlight handoff](../testing/testflight/0.2.0-build-5.md) |
| 94 | +- [Apple `MinimumOSVersion`](https://developer.apple.com/documentation/BundleResources/Information-Property-List/MinimumOSVersion) |
| 95 | + |
| 96 | +<!-- SPDX-License-Identifier: MIT --> |
0 commit comments