Bump to 4.4.2: Xcode build-provenance keys in iOS framework Info.plists - #242
Conversation
Re-pins the bundled python-build snapshot to 20260727, which stamps the DT* build-provenance keys Xcode writes into a real framework's Info.plist into every framework generated from a lib-dynload .so, and labels the simulator slice as iPhoneSimulator instead of iPhoneOS (flet-dev/python-build#36). No versions moved: Python 3.12.13 / 3.13.14 / 3.14.6, Pyodide, and dart_bridge 1.6.1 are all unchanged from 20260726. This is the next hypothesis under test for the ITMS-91065 rejection in flet-dev/flet#6724, not a confirmed fix — see the serious_python_darwin 4.4.2 entry for what was ruled out experimentally and what remains open.
Every Python C-extension ships as its own embedded framework, and each carried a fixed `org.python.<module>` CFBundleIdentifier -- org.python.ssl, org.python.hashlib, ... -- byte-identical in every app ever built with serious_python. A framework's bundle identifier also becomes its CODE SIGNING identifier, and that is the one field that survives the `codesign -f` Xcode applies at embed and again at exportArchive (everything else -- certificate chain, team identifier, secure timestamp -- is destroyed). A globally-shared identifier on a framework Apple fingerprints as a listed third-party SDK is the leading explanation for the ITMS-91065 rejection in flet-dev/flet#6724. Setting SERIOUS_PYTHON_BUNDLE_ID rewrites them to `<app id>.<module>` with underscores mapped to hyphens, matching CPython's own iOS support (Platforms/Apple/testbed/Python.xcframework/build/utils.sh). The leading hyphen for underscore-prefixed modules (`_ssl` -> `<app>.-ssl`) is deliberate: it is what keeps `_ssl` distinct from `ssl`, and it is the form CPython ships. The rewrite runs before reconcile_framework_install_names, whose ad-hoc re-sign reseals the modified plists; the stdlib xcframeworks are unsigned at that point so editing them invalidates nothing. Module names come from arbitrary wheels, so anything outside CFBundleIdentifier's [A-Za-z0-9.-] is mapped to a hyphen, and an invalid SERIOUS_PYTHON_BUNDLE_ID leaves the defaults in place with a warning rather than emitting a plist that fails late at export. flet passes the value from flet-dev/flet#6731.
|
Added the bundle-identifier change ( WhatNew Runs in flet passes the value: flet-dev/flet#6731. Why this is the stronger hypothesisA framework's bundle identifier also becomes its code signing identifier, which is the only field that survives It's also the only theory that accounts for every outcome we found:
The leading hyphen is deliberate77 of the 93 frameworks in a representative ValidationModule names come from arbitrary wheels, so anything outside Exercised against real Caveat4.4.2 now carries two independent unproven hypotheses. If a new-app submission passes, we won't know which one did it. Flagged in the changelogs. |
Python.xcframework is staged straight out of dist/xcframeworks by stage_spm.sh and vendored from there by the podspec, so it never passes through site-xcframeworks and kept a shared `org.python.python` -- identical in every app, the same class of identifier the previous commit fixed for the extension frameworks. Verified inert at runtime before renaming: `org.python.python` appears in no shipped binary, and neither Python.framework nor App.framework contains a CFBundleGetBundleWithIdentifier / bundleWithIdentifier lookup. serious_python sets PYTHONHOME explicitly and resolves extensions through the .fwork/.origin path mechanism, not bundle identifiers. rewrite_framework_bundle_ids takes an optional skip list so dart_bridge keeps `dev.flet.dartbridge` -- a vendor-owned reverse-DNS identifier is the shape we're aiming for, not the problem we're fixing. Confirmed against a real build (flet playground abc1.xcarchive): 93 of 98 frameworks were already namespaced, no duplicate identifiers; this covers Python.framework, leaving only Flutter's own three (App, Flutter, objective_c) and dart_bridge.
jni 1.0.1, published 2026-07-27T01:10Z, added global_jni_env.c, which passes a `va_list` where a `void *` is expected. On x86_64 va_list is an array type that decays to a pointer so it compiles; on aarch64 it is a struct, so it is a hard error and `flutter build linux` fails with 19 of them. Tracked upstream at dart-lang/native#3498. This surfaced on the release PR rather than as a scheduled failure because the examples depend on the serious_python packages by path: bumping their version invalidates the committed pubspec.lock, pub re-resolves the whole graph, and picks up the newest transitive versions. Any PR touching package versions after 2026-07-27T01:10Z would have hit it. jni itself arrives via path_provider -> path_provider_android -> jni_flutter -> jni. jni_flutter 1.0.1 declares `jni: ^1.0.0`, so 1.0.0 satisfies it -- the override narrows within the allowed range rather than overriding a constraint. Applied to all three examples; only bridge_example runs in CI, but the other two break identically for anyone building them on an ARM64 Linux host. The flask_example / run_example locks also pick up the current path-dependency version (4.0.0 -> 4.4.1); they were simply stale.
Re-pins the bundled python-build snapshot to 20260727 and bumps all six packages to 4.4.2.
What's in the snapshot
flet-dev/python-build#36 only. Every framework generated from a
lib-dynload.so—_ssl,_hashliband the rest — previously shipped ten hand-writtenInfo.plistkeys and not a singleDT*key, so to Apple's static analysis the bundle didn't look like anything Xcode produced. They now carry the same key set Xcode stamps into a real framework:Also fixes the simulator slice, which claimed
CFBundleSupportedPlatforms=iPhoneOS.No versions moved — Python 3.12.13 / 3.13.14 / 3.14.6, Pyodide, and
dart_bridge1.6.1 are unchanged from 20260726. The manifest diff between the two releases is one line: thereleasefield.Status of flet-dev/flet#6724
This is the next hypothesis under test for
ITMS-91065: Missing signature, not a confirmed fix, and the changelogs say so. Two candidates have now been ruled out experimentally:exportArchivedoes destroys the certificate chain, team identifier and secure timestamp; only the identifier string survives, and that's derived fromCFBundleIdentifierfor an unsigned framework anyway.ITMS-91061alongside the rejection.Testing this needs a new app submitted for App Store review. The check only fires for new apps or updates that newly add a listed SDK, which is why existing Flet apps — including Flet Studio — are unaffected and can't reproduce it.
Verification
gen_version_tables --release-date 20260727regenerated all five tables; the no-arg re-run produces no further diff.4.4.1in any pubspec,build.gradle.kts, or podspec.