diff --git a/AGENTS.md b/AGENTS.md index 0fe7d60..8a7cb82 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4604,11 +4604,13 @@ via log (single `audi_dashboard` loader warning, no traceback). --- -## AI. iOS signing prepared, and the one thing that blocks it (2026-08-29) +## AI. iOS app built, signed ad-hoc, and prepared for over-the-air install (2026-08-29) Task was: build the iOS app, sign it, commit the result — `UMSETZUNGSPLAN.md` Phase 10 step 7, the -last open item of that phase. **Result: everything except the signature itself is done and -verified; the signature is blocked on a fact about the Apple account, not on this repo.** +last open item of that phase. **Result: done.** A signed `.ipa` exists and is committed; the +over-the-air delivery around it is built but not yet exercised (no HTTPS host running — see the end +of this section). Read this section start to finish before touching iOS signing: it went through two +wrong assumptions and one badly-signposted failure, all recorded below on purpose. What was verified on this machine (Xcode 26.4, Node 22.20, `main` at `2026.8.28.18`): @@ -4619,9 +4621,9 @@ What was verified on this machine (Xcode 26.4, Node 22.20, `main` at `2026.8.28. 8.5 MB `App.app`. So the code, the plugins and the Swift-package graph are all fine on device; nothing but provisioning is missing. -**The blocker, verbatim from Apple:** `Communication with Apple failed: Your team has no devices -from which to generate a provisioning profile.` The account authenticates fine (Xcode reached Apple -and got a real answer, not an auth error) — team `RMACS9VLS4`, certificate +**The first blocker (since resolved), verbatim from Apple:** `Communication with Apple failed: Your +team has no devices from which to generate a provisioning profile.` The account authenticated fine +(Xcode reached Apple and got a real answer, not an auth error) — team `RMACS9VLS4`, certificate `Apple Development: paul.nothaft@me.com (C9L892Z59P)`, valid until 2027-07-17. Apple issues a development profile only for **named devices**, and this team has none registered. No iPhone is connected (`xcrun devicectl list devices` → none) and no device was ever paired with this Mac (no @@ -4632,47 +4634,74 @@ machine with no phone attached: - an App-Store-method export needs no devices but produces an IPA that iOS refuses to sideload; - a locally `codesign`-ed `.app` without an embedded profile will not install either. -**Correction, same day: this is a FREE account, not a paid membership.** Xcode's own cache says so -— `defaults read com.apple.dt.Xcode` → `IDEProvisioningTeamByIdentifier`: -`teamName = "Paul Nothaft (Personal Team)"`, `teamType = "Personal Team"`, -**`isFreeProvisioningTeam = 1`**. The note further up this file claiming "Paul has an Apple -Developer Program" (section on the 2026-08-17 port) is therefore **wrong** and must not be relied -on. Consequences, all confirmed against Apple's membership comparison and the free-provisioning -limits: +**Interlude, same day: the account was free at that moment.** Xcode's cache said +`teamName = "Paul Nothaft (Personal Team)"`, **`isFreeProvisioningTeam = 1`** — which meant no +portal device management, and a 7-day expiry on profile, App ID and device registration alike. The +owner then **bought the Apple Developer Program** and registered the iPhone through the portal. -- **There is no portal route to register a device.** Certificates, Identifiers & Profiles device - management is a paid-membership feature. A free team registers a device only by having it - **physically connected to this Mac and trusted**; Xcode then does it via - `-allowProvisioningUpdates`. So "add the UDID on the website" is not an option here. -- **Everything expires after 7 days** — provisioning profile, App ID and device registration alike. - The app stops launching and has to be rebuilt and reinstalled, forever, every week. -- Ceilings: 3 devices per platform, 10 App IDs per 7 days. -- Whether `-exportArchive` even yields a usable `.ipa` for a free team is **untested and doubtful** - — free provisioning is built around "Run straight onto the connected device" from Xcode, not - around exporting a redistributable archive. If the export step fails once a phone is attached, - install directly instead of debugging the export. +**Two things this taught, both worth keeping:** -**What to do (owner):** connect the iPhone by cable, tap "Trust", then run the script below. That -is the only path with this account type. If the weekly re-install turns out to be intolerable, the -paid Apple Developer Program (99 €/year) is what buys the 1-year signature, portal-side UDID -registration without the phone present, and 100 devices — `UMSETZUNGSPLAN.md` Phase 10 already -flagged this as an owner decision, and it is now a decision with a known answer on one side. +1. **A paid enrolment upgrades the existing team; it does not create a new one.** The Team ID stayed + `RMACS9VLS4` — the same string that had belonged to the Personal Team. This file briefly claimed + the opposite and the signing script briefly refused to run because of it. Verified by the issued + profile: team `RMACS9VLS4`, valid **2026-08-29 → 2027-08-29** (a year, not seven days). +2. **The note further up this file claiming "Paul has an Apple Developer Program" (2026-08-17 + section) was wrong when written and right by accident twelve days later.** It is marked in place. + +**`errSecInternalComponent` and a build that hangs forever: it is the keychain, not the code.** After +the first successful profile fetch, `xcodebuild` sat at the `CodeSign` step for 20+ minutes with no +output, then failed with `errSecInternalComponent`. Diagnosis that settled it, worth repeating +because the symptom points nowhere useful on its own: `lsof -p -i` showed **no network +sockets** (so not a timestamp-server stall, the other classic cause), and `sample ` showed the +stack parked in `SecKeyCreateSignature` → `SecCDSAKeyCopyOperationResult` → `mach_msg` — blocked on +the security daemon, i.e. an unanswered **"allow codesign to use this key?" dialog** sitting on the +GUI. Fix is the owner clicking **"Always Allow"** (not "Allow" — a single archive signs 25+ binaries +and would re-prompt each time). Deliberately not used: `security set-key-partition-list`, which does +the same non-interactively but only by putting the login password on a command line. + +**Result: it worked.** `App.ipa`, 2.4 MB, exported **ad-hoc**, signed +`Apple Distribution: Paul Nothaft (RMACS9VLS4)`, embedded profile +`iOS Team Ad Hoc Provisioning Profile: app.datametric360` valid to 2027-08-29, one provisioned device +(`00008130-001C089E3E8A001C`), `get-task-allow: false`. Committed to +`companion-app/auslieferung/App.ipa` — `ios/` is gitignored, so without a tracked path the artifact +would exist on one Mac only. + +**Over-the-air install, built as `companion-app/scripts/ios-luftweg.sh `.** Emits +`manifest.plist` + a small install page + the icons into `ios/build/luftweg/`, reading bundle id and +version out of the `.ipa` rather than repeating them. The binding constraint is **HTTPS with a +publicly trusted certificate** for both the manifest and the `.ipa` — iOS refuses plain HTTP and +self-signed certs, so Home Assistant's `/local/` over the tailnet does **not** qualify. The fit for +this project is `tailscale serve --bg ` (real Let's Encrypt cert on `*.ts.net`, no open port, +iPhone already on the tailnet); the Phase 12 Cloudflare tunnel would do it later too. The link must +be opened in **Safari** — other browsers do not hand `itms-services://` to the system. Script +refuses a non-`https://` base outright rather than producing a manifest that fails silently on the +phone. + +**Still open at end of session:** this Mac is logged out of Tailscale (`BackendState: NeedsLogin`), +so no host was serving yet and the over-the-air install is **built but not yet exercised end to end**. +Also untouched: `MARKETING_VERSION` is still `1.0`/`1` from the Capacitor scaffold, so successive +`.ipa`s are indistinguishable in iOS Settings — harmless for installing, mildly annoying later. **What was built instead of a hand-clicked Xcode signature:** `companion-app/scripts/ios-signieren.sh` — build → `cap sync` → signed archive → `.ipa` export, one command. It exists because `ios/` is gitignored on purpose (regenerable from the web bundle), which means **any signing setting clicked in Xcode is silently lost at the next `npx cap add ios`**. A versioned script is the only place the -team ID can survive. `APPLE_TEAM_ID` overrides it; output lands in `ios/build/App.ipa` (already -covered by the `ios/` ignore, no build artifact enters git). Verified by running it end to end: it -passes build, sync and archive setup and stops exactly at Apple's device requirement, nowhere else. +team ID can survive (`APPLE_TEAM_ID` overrides it). It copies the finished `.ipa` to +`auslieferung/`, which *is* tracked, for the same reason. -Deliberately **not** done: committing an unsigned `.ipa` as a stand-in. It is not what was asked -for, it cannot be installed as-is, and a per-build ~6 MB binary would sit in the git history -forever. The OTA path already covers "new UI without Xcode" (section above) — Xcode is only needed -when native code or the signature itself changes. +Deliberately **not** done: committing an unsigned `.ipa` as a stand-in while signing was still +blocked. It could not have been installed, and it is not what was asked for. Once the signature +worked, the real 2.4 MB artifact went in. -Phase 10 step 7 therefore stays **unchecked** in `UMSETZUNGSPLAN.md`: the app is not on the phone -yet, and marking it done would be exactly the silent staleness this project keeps designing against. +**Do not confuse the two things called "OTA" in this repo.** The older one (section on +`@capgo/capacitor-updater`) swaps the *web bundle* inside an already-installed app and is the normal +route for UI changes — no Xcode, no Apple. The new `ios-luftweg.sh` installs a whole new *native +app* and is only needed when native code, plugins or the signature change. Reaching for the second +when the first would do means a pointless Apple round trip. + +Phase 10 step 7 is **ticked** in `UMSETZUNGSPLAN.md`; step 8's own acceptance test (app starts +natively, token lands in the Keychain) is **not** — that needs the app actually running on the phone, +which needs the HTTPS host below. --- diff --git a/UMSETZUNGSPLAN.md b/UMSETZUNGSPLAN.md index 690add0..f814d72 100644 --- a/UMSETZUNGSPLAN.md +++ b/UMSETZUNGSPLAN.md @@ -424,12 +424,16 @@ nicht ein Riesencommit. > Offen bleibt allein das Signieren aufs eigene Gerät — das braucht das > angeschlossene iPhone und die Apple-ID des Besitzers. > -> **2026-08-29:** Schritt 7 vorbereitet, aber nicht abschließbar. Der Gerätebau -> (arm64, Release) läuft fehlerfrei durch, das Signieren scheitert -> ausschließlich daran, dass dem Team `RMACS9VLS4` **kein Gerät** bekannt ist: -> Apple erzeugt ein Development-Profil nur für konkrete UDIDs. Der ganze -> Ablauf steckt jetzt in `companion-app/scripts/ios-signieren.sh` und läuft -> bis genau zu diesem Punkt. Details in `AGENTS.md` Abschnitt AI. +> **2026-08-29: Schritt 7 erledigt.** Der Besitzer hat das bezahlte +> Entwicklerkonto gelöst und das iPhone im Portal registriert; die Team-Kennung +> blieb dabei `RMACS9VLS4` (die bezahlte Mitgliedschaft stuft das bestehende +> Team hoch, sie legt kein neues an). Ergebnis: `companion-app/auslieferung/App.ipa`, +> 2,4 MB, **Ad-hoc** signiert mit `Apple Distribution: Paul Nothaft`, Profil +> gültig bis 29.08.2027. Zwei Skripte tragen das: +> `scripts/ios-signieren.sh` (bauen und signieren) und `scripts/ios-luftweg.sh` +> (Manifest und Installationsseite für die Übertragung über die Luft). +> Offen bleibt allein ein HTTPS-Host, der die Dateien ausliefert — siehe +> Schritt 8. Fallstricke und Diagnosen in `AGENTS.md` Abschnitt AI. **Ziel:** Die App läuft auf dem iPhone. Zwei Stufen — erst PWA (sofort nutzbar), dann Capacitor (Keychain + QR-Scan). @@ -456,21 +460,27 @@ nicht ein Riesencommit. (Offline-JS-QR-Bibliothek, keine Netzabfrage) als QR anzeigt. Inhalt des QR: JSON `{"url": "...", "token": "..."}`. Wenn das zusammen > 1 Tag Aufwand wird: weglassen — manuelles Einfügen ist die beschlossene, ausreichende Lösung. -7. **iOS-Sideload:** statt Xcode von Hand jetzt `bash companion-app/scripts/ios-signieren.sh` - (baut Webbündel, synchronisiert die Hülle, archiviert signiert, exportiert die `.ipa`). - Die Team-Kennung steht im Skript, weil `ios/` gitignored ist und jede in Xcode geklickte - Einstellung beim nächsten `npx cap add ios` verschwinden würde. - ⚠️ **Voraussetzung, die kein Skript herstellen kann:** das iPhone muss **per Kabel an diesem - Mac hängen und vertraut sein**. Sonst: „Your team has no devices from which to generate a - provisioning profile". Die UDID stattdessen auf developer.apple.com einzutragen geht **nicht** — - das ist ein Recht der bezahlten Mitgliedschaft, und das Konto ist ein kostenloses Personal Team - (`isFreeProvisioningTeam = 1`, belegt 2026-08-29, siehe `AGENTS.md` Abschnitt AI). - ⚠️ Entscheidungspunkt für den Besitzer, jetzt mit bekannter Faktenlage: das Konto **ist** - kostenlos, die Signatur läuft also alle **7 Tage** ab (Profil, App-ID und Geräteeintrag - gleichermaßen — App wöchentlich neu aufspielen). Ein bezahltes Entwicklerkonto (99 €/Jahr) - macht daraus 1 Jahr und erlaubt die Geräteregistrierung ohne angeschlossenes Telefon. - Bei 7-Tage-Schmerz ist die PWA-Stufe die Alltagslösung, Capacitor das Extra für Keychain/QR. -8. ✅ Fertig wenn: App startet nativ auf dem iPhone, Token liegt im Keychain (Test: App löschen und +7. ✅ **iOS-Sideload (erledigt 2026-08-29):** `bash companion-app/scripts/ios-signieren.sh` + baut Webbündel, synchronisiert die Hülle, archiviert signiert und exportiert die `.ipa` + nach `companion-app/auslieferung/`. Die Team-Kennung steht im Skript, weil `ios/` gitignored + ist und jede in Xcode geklickte Einstellung beim nächsten `npx cap add ios` verschwinden würde. + Der Entscheidungspunkt Kostenlos-vs-Bezahlt ist entschieden: **bezahltes Konto**, damit + Signatur ein Jahr gültig statt sieben Tage, und Geräteregistrierung über das Portal ohne + angeschlossenes Telefon. + ⚠️ **Falle, die viel Zeit kostet:** beim ersten Signieren fragt der Schlüsselbund per Dialog + um Erlaubnis. Wird der nicht beantwortet, hängt `xcodebuild` wortlos minutenlang und endet + mit `errSecInternalComponent`. Im Dialog **„Immer erlauben"** wählen — ein Archiv signiert + über 25 Binärdateien und würde sonst jedes Mal erneut fragen. +8. **Übertragung über die Luft** (statt Kabel): `bash companion-app/scripts/ios-luftweg.sh + https://` erzeugt `manifest.plist`, Installationsseite und Symbole in + `ios/build/luftweg/`. Der Ordner muss über **HTTPS mit öffentlich vertrauenswürdigem + Zertifikat** ausgeliefert werden — iOS lehnt einfaches HTTP und selbstsignierte Zertifikate + ab, Home Assistant unter `/local/` genügt also **nicht**. Passend: `tailscale serve --bg + ` (echtes Let's-Encrypt-Zertifikat auf `*.ts.net`, kein offener Port, iPhone ohnehin + im Tailnet); der Cloudflare-Tunnel aus Phase 12 täte es später ebenso. Link auf dem iPhone in + **Safari** öffnen — andere Browser reichen `itms-services://` nicht ans System weiter. + ⏳ Offen: dieser Mac ist bei Tailscale abgemeldet, es läuft also noch kein Host. +9. ✅ Fertig wenn: App startet nativ auf dem iPhone, Token liegt im Keychain (Test: App löschen und neu installieren → Token weg; Backup/Restore-Verhalten notieren), QR-Einrichtung funktioniert oder ist dokumentiert entfallen. 9. Committen; `AGENTS.md` Block A Punkte QR/Secure-Storage abhaken. diff --git a/companion-app/README.md b/companion-app/README.md index 2b5a4f1..6ead431 100644 --- a/companion-app/README.md +++ b/companion-app/README.md @@ -68,6 +68,17 @@ veröffentlicht**, und dieses Repository bleibt privat. `../design-system/` kommt bewusst ohne diese Dateien aus, weil es nach außen hochgeladen wird — dort niemals Markendateien ablegen. +## Die signierte App + +`auslieferung/App.ipa` ist der fertige, **Ad-hoc signierte** Stand (Team +`RMACS9VLS4`, Profil gültig bis 29.08.2027, nur für das eingetragene iPhone). +Neu bauen: `bash scripts/ios-signieren.sh` - baut Webbündel, synchronisiert die +Hülle, signiert und legt die `.ipa` wieder hier ab. + +Beim ersten Signieren fragt der Schlüsselbund um Erlaubnis. Dort **„Immer +erlauben"** wählen, sonst hängt `xcodebuild` wortlos und endet nach Minuten mit +`errSecInternalComponent`. + ## Noch offen - Native Hülle selbst: `ios/`/`android/` (von `npx cap add` erzeugt, absichtlich @@ -76,12 +87,10 @@ dort niemals Markendateien ablegen. (Keychain/Keystore) ist dagegen bereits vollständig angebunden (`src/api/ablageNativ.ts`, von `main.tsx` aktiviert) und wird automatisch aktiv, sobald die Hülle existiert -- Signierte `.ipa`: `scripts/ios-signieren.sh` baut und signiert in einem - Durchlauf, **sobald das iPhone per Kabel am Mac hängt und vertraut ist**. - Vorher bricht Apple den Profilabruf ab - das ist die einzige verbleibende - Hürde, der Gerätebau selbst läuft fehlerfrei durch. Das Konto ist ein - kostenloses Personal Team: die UDID lässt sich nicht auf developer.apple.com - nachtragen, und die Signatur verfällt alle 7 Tage +- Übertragung über die Luft: `scripts/ios-luftweg.sh https://` erzeugt + Manifest und Installationsseite; es fehlt nur noch ein Host, der den Ordner + über **HTTPS mit gültigem Zertifikat** ausliefert (`tailscale serve` + angedacht, dieser Mac ist dort noch abgemeldet) - QR-Einrichtung als Alternative zum Einfügen des Tokens - Live-Ansicht der laufenden Fahrt: gebaut, aber über `src/funktionen.ts` abgeschaltet, bis der FMM003 echte Werte liefert diff --git a/companion-app/auslieferung/App.ipa b/companion-app/auslieferung/App.ipa new file mode 100644 index 0000000..88b8d11 Binary files /dev/null and b/companion-app/auslieferung/App.ipa differ diff --git a/companion-app/scripts/ios-luftweg.sh b/companion-app/scripts/ios-luftweg.sh new file mode 100755 index 0000000..85ad9b0 --- /dev/null +++ b/companion-app/scripts/ios-luftweg.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +# Bereitet die Installation ueber die Luft vor: legt neben der signierten .ipa +# die manifest.plist und eine kleine Installationsseite ab. +# +# bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net +# +# Warum das noetig ist: iOS installiert eine App nur dann ueber die Luft, wenn +# ein itms-services-Link auf eine manifest.plist zeigt, die wiederum die +# Adresse der .ipa enthaelt. Beide Adressen muessen ueber **HTTPS mit einem +# oeffentlich vertrauenswuerdigen Zertifikat** erreichbar sein - einfaches HTTP +# und selbstsignierte Zertifikate lehnt iOS kommentarlos ab. Home Assistant +# unter /local/ genuegt dafuer nicht, das laeuft im Tailnet unverschluesselt. +# +# Passend dazu und ohne offenen Port: `tailscale serve` liefert ein echtes +# Let's-Encrypt-Zertifikat auf ..ts.net aus. Voraussetzung +# ist, dass in der Tailscale-Verwaltung HTTPS-Zertifikate aktiviert sind. +# +# tailscale serve --bg ios/build/luftweg +# +# Danach den ausgegebenen Link auf dem iPhone in **Safari** oeffnen (andere +# Browser reichen itms-services nicht an das System weiter). +set -euo pipefail + +if [ $# -lt 1 ]; then + echo "Aufruf: bash scripts/ios-luftweg.sh " >&2 + echo "Beispiel: bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net" >&2 + exit 1 +fi + +BASIS="${1%/}" +if [ "${BASIS#https://}" = "$BASIS" ]; then + echo "FEHLER: Die Basis-Adresse muss mit https:// beginnen." >&2 + echo "iOS verweigert die Installation ueber die Luft ueber unverschluesseltes HTTP." >&2 + exit 1 +fi + +HIER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +APP="$(dirname "$HIER")" +IPA="$APP/auslieferung/App.ipa" +ZIEL="$APP/ios/build/luftweg" + +[ -f "$IPA" ] || { echo "FEHLER: $IPA fehlt - erst scripts/ios-signieren.sh laufen lassen." >&2; exit 1; } + +# Version aus der .ipa selbst lesen statt sie hier zu wiederholen: zwei Quellen +# fuer dieselbe Angabe waeren eine zu viel. +AUSPACK="$(mktemp -d)" +trap 'rm -rf "$AUSPACK"' EXIT +unzip -q "$IPA" -d "$AUSPACK" +PLIST="$(find "$AUSPACK/Payload" -maxdepth 2 -name Info.plist | head -1)" +KENNUNG="$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$PLIST")" +VERSION="$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$PLIST")" + +rm -rf "$ZIEL" +mkdir -p "$ZIEL" +cp "$IPA" "$ZIEL/App.ipa" +cp "$APP/public/symbol-192.png" "$ZIEL/symbol-192.png" +cp "$APP/public/symbol-512.png" "$ZIEL/symbol-512.png" + +cat > "$ZIEL/manifest.plist" < + + + + items + + + assets + + + kindsoftware-package + url$BASIS/App.ipa + + + kinddisplay-image + url$BASIS/symbol-192.png + + + kindfull-size-image + url$BASIS/symbol-512.png + + + metadata + + bundle-identifier$KENNUNG + bundle-version$VERSION + kindsoftware + titleDataMetric360 + + + + + +PLISTENDE + +# Das kaufmaennische Und muss in HTML maskiert werden, sonst schneidet Safari +# den Link hinter dem url-Parameter ab. +cat > "$ZIEL/index.html" < + + + +DataMetric360 installieren + +
+

DataMetric360

+

Version $VERSION

+ Installieren +

In Safari oeffnen. Nach dem Antippen fragt iOS einmal nach,
danach erscheint die App auf dem Startbildschirm.

+
+ +HTMLENDE + +echo "Ordner fertig: $ZIEL" +echo +echo "Ausliefern: tailscale serve --bg $ZIEL" +echo "Auf dem iPhone in Safari oeffnen: $BASIS/" diff --git a/companion-app/scripts/ios-signieren.sh b/companion-app/scripts/ios-signieren.sh index 45b35cd..d14cec1 100755 --- a/companion-app/scripts/ios-signieren.sh +++ b/companion-app/scripts/ios-signieren.sh @@ -32,20 +32,12 @@ set -euo pipefail HIER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" APP="$(dirname "$HIER")" -# Absichtlich ohne Vorgabewert. Hier stand bis 2026-08-29 die Kennung des -# kostenlosen Personal Teams (RMACS9VLS4). Mit dem Wechsel auf eine bezahlte -# Mitgliedschaft entsteht ein *neues* Team mit eigener Kennung - der alte Wert -# wuerde also still weiter mit dem kostenlosen Team signieren (7-Tage-Ablauf) -# statt mit dem bezahlten. Lieber ein klarer Abbruch als eine App, die nach -# einer Woche wortlos stirbt. -TEAM="${APPLE_TEAM_ID:-}" -if [ -z "$TEAM" ]; then - echo "FEHLER: APPLE_TEAM_ID ist nicht gesetzt." >&2 - echo "Die Team-Kennung steht auf developer.apple.com/account unter" >&2 - echo "'Membership details' (10 Zeichen, z. B. A1B2C3D4E5). Dann:" >&2 - echo " APPLE_TEAM_ID=XXXXXXXXXX bash scripts/ios-signieren.sh" >&2 - exit 1 -fi +# Dieselbe Kennung wie zu Zeiten des kostenlosen Kontos: die bezahlte +# Mitgliedschaft hat das bestehende Team hochgestuft, statt ein neues +# anzulegen. Zwischenzeitlich stand hier das Gegenteil - widerlegt am +# 2026-08-29 durch das ausgestellte Profil (Team RMACS9VLS4, Laufzeit ein +# Jahr statt sieben Tage). Ueberschreibbar ueber APPLE_TEAM_ID. +TEAM="${APPLE_TEAM_ID:-RMACS9VLS4}" AUSGABE="$APP/ios/build" ARCHIV="$AUSGABE/DataMetric360.xcarchive" @@ -74,15 +66,17 @@ xcodebuild \ DEVELOPMENT_TEAM="$TEAM" \ archive -# Die Exportart heisst seit Xcode 16 offiziell "debugging"; "development" ist -# weiterhin als Synonym gueltig und funktioniert auch mit aelteren Xcode- -# Versionen, deshalb bleibt es hier stehen. +# Ad-hoc, nicht development: das ist die von Apple vorgesehene Art fuer die +# Installation ueber die Luft (siehe ios-luftweg.sh) und deckt den Weg per +# Kabel gleich mit ab. Sie verlangt ein Apple-Distribution-Zertifikat, das +# -allowProvisioningUpdates bei Bedarf selbst anlegt - moeglich erst seit der +# bezahlten Mitgliedschaft. Die Signatur laeuft damit ein Jahr. cat > "$AUSGABE/ExportOptions.plist" < - methoddevelopment + methodad-hoc teamID$TEAM signingStyleautomatic stripSwiftSymbols @@ -97,6 +91,12 @@ xcodebuild -exportArchive \ -exportPath "$AUSGABE" \ -allowProvisioningUpdates +# Die fertige .ipa liegt versioniert unter auslieferung/, weil ios/ gitignored +# ist und das Ergebnis sonst nur auf diesem einen Mac existierte. +mkdir -p "$APP/auslieferung" +cp "$AUSGABE/App.ipa" "$APP/auslieferung/App.ipa" + echo -echo "Fertig: $AUSGABE/App.ipa" -echo "Aufs Geraet: xcrun devicectl device install app --device $AUSGABE/App.ipa" +echo "Fertig: $APP/auslieferung/App.ipa" +echo "Ueber die Luft: bash scripts/ios-luftweg.sh https://" +echo "Per Kabel: xcrun devicectl device install app --device $APP/auslieferung/App.ipa"