diff --git a/AGENTS.md b/AGENTS.md index d53252e..0fe7d60 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,8 @@ # AGENTS.md — Project state, review findings, open items, and working rules -**Last updated: 2026-08-23** (merged the `umsetzung-datametric360` branch — companion app phases +**Last updated: 2026-08-29** (iOS signing prepared end to end — device build verified, signature +blocked on a device registration at Apple, see section AI; 2026-08-23: merged the +`umsetzung-datametric360` branch — companion app phases 1–10 done, see `UMSETZUNGSPLAN.md`; 2026-08-13: cleaned up remaining EU Data Act residue, fixed oversized toggle switches, and fixed a desktop-layout audit (settings button / rings logo / popups overflowing past the capped content column) — see `DESIGN_AUDIT_2026-08-13.md`; 2026-08-16: fixed @@ -1435,7 +1437,8 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed panel fix and feature from the six days since (HIG audit rounds, receipt upload, trip editing, Inspektion forecast, ...) existed only in `homeassistant/www/audi-dashboard-app.js`. User decision: port everything now, before any native build work (Android build itself - deprioritized/uncertain per the user - Paul has an Apple Developer Program and will help with + deprioritized/uncertain per the user - Paul has an Apple Developer Program **[WRONG, see + section AI: it is a free Personal Team, not a paid membership]** and will help with iOS signing). Audited both codebases field-by-field (not by diffing the panel's CSS/markup, which doesn't transfer to `@audi-dash/ui` components) and found six real, mechanically distinct gaps, all fixed: @@ -4601,6 +4604,78 @@ via log (single `audi_dashboard` loader warning, no traceback). --- +## AI. iOS signing prepared, and the one thing that blocks it (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.** + +What was verified on this machine (Xcode 26.4, Node 22.20, `main` at `2026.8.28.18`): + +- `npm run typecheck` clean, `npm test` 146/146 green, `npm run build` clean, `npx cap sync ios` + clean (both plugins found: secure-storage 8.0.0, capgo/updater 8.51.14). +- **Simulator build (Release) succeeds.** +- **Device build (Release, `generic/platform=iOS`, arm64) succeeds** with signing switched off — + 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 +`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 +`~/Library/Developer/CoreDevice`, no iOS DeviceSupport). There is no route around this from a +machine with no phone attached: + +- development / ad-hoc profiles both require registered UDIDs; +- 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: + +- **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. + +**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. + +**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. + +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. + +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. + +--- + ## Working conventions (observed — keep them) - German is the project language: identifiers, comments, commits, UI texts. Exceptions: diff --git a/UMSETZUNGSPLAN.md b/UMSETZUNGSPLAN.md index 4d59585..690add0 100644 --- a/UMSETZUNGSPLAN.md +++ b/UMSETZUNGSPLAN.md @@ -423,6 +423,13 @@ nicht ein Riesencommit. > echte Daten. `CapacitorHttp` umgeht die CORS-Beschränkung der WebView. > 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. **Ziel:** Die App läuft auf dem iPhone. Zwei Stufen — erst PWA (sofort nutzbar), dann Capacitor (Keychain + QR-Scan). @@ -449,9 +456,19 @@ 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:** `npx cap open ios`, in Xcode Signing mit eigener Apple-ID, aufs Gerät bauen. - ⚠️ Entscheidungspunkt für den Besitzer: mit kostenlosem Apple-Konto läuft die Signatur nach - **7 Tagen** ab (App neu aufspielen); ein bezahltes Entwicklerkonto (99 €/Jahr) macht 1 Jahr. +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 neu installieren → Token weg; Backup/Restore-Verhalten notieren), QR-Einrichtung funktioniert diff --git a/companion-app/README.md b/companion-app/README.md index 34cc009..2b5a4f1 100644 --- a/companion-app/README.md +++ b/companion-app/README.md @@ -76,6 +76,12 @@ 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 - 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/scripts/ios-signieren.sh b/companion-app/scripts/ios-signieren.sh new file mode 100755 index 0000000..9a51ed7 --- /dev/null +++ b/companion-app/scripts/ios-signieren.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# Baut die native iOS-Huelle und signiert sie zu einer installierbaren .ipa. +# Nur auf einem Mac mit Xcode lauffaehig. Siehe ../../UMSETZUNGSPLAN.md Phase 10. +# +# Warum es dieses Skript gibt: `ios/` ist absichtlich gitignored (aus dem +# Webbuendel jederzeit wiederherstellbar). Damit verschwindet aber auch jede +# Signatureinstellung, die man in Xcode von Hand setzt, beim naechsten +# `npx cap add ios` wieder. Die Team-Kennung gehoert deshalb hierher - in eine +# versionierte Datei - und wird dem Build von aussen mitgegeben. +# +# Voraussetzung, die dieses Skript nicht herstellen kann: das iPhone muss +# per Kabel an diesem Mac haengen und vertraut sein. Apple erzeugt ein +# Development-Profil nur fuer konkrete Geraete, und dieses Konto ist ein +# kostenloses Personal Team - da gibt es keine Geraeteverwaltung auf +# developer.apple.com, das Anmelden der Geraetekennung macht Xcode selbst ueber +# -allowProvisioningUpdates am angeschlossenen Telefon. Ohne Telefon bricht der +# Archivschritt mit "Your team has no devices" ab; das ist kein Fehler im +# Projekt. +# +# Ebenfalls Folge des kostenlosen Kontos: Profil, App-ID und Geraeteeintrag +# verfallen nach 7 Tagen, die App muss dann neu aufgespielt werden. +# +# Ungeprueft, weil bisher kein Geraet zur Verfuegung stand: ob der +# -exportArchive-Schritt mit einem Personal Team ueberhaupt eine brauchbare +# .ipa liefert. Kostenloses Signieren ist auf "direkt aufs angeschlossene +# Geraet starten" ausgelegt, nicht auf ein weitergebbares Archiv. Scheitert der +# Export, ist der direkte Weg der richtige, nicht die Fehlersuche am Export: +# xcodebuild -project ios/App/App.xcodeproj -scheme App \ +# -destination 'id=' -allowProvisioningUpdates \ +# DEVELOPMENT_TEAM=$TEAM install +set -euo pipefail + +HIER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +APP="$(dirname "$HIER")" +TEAM="${APPLE_TEAM_ID:-RMACS9VLS4}" +AUSGABE="$APP/ios/build" +ARCHIV="$AUSGABE/DataMetric360.xcarchive" + +cd "$APP" + +echo "==> Webbuendel bauen" +npm run build + +echo "==> Native Huelle synchronisieren" +if [ ! -d ios ]; then + echo "==> ios/ fehlt, wird neu erzeugt" + npx cap add ios +fi +npx cap sync ios + +echo "==> Archiv bauen und signieren (Team $TEAM)" +rm -rf "$AUSGABE" +mkdir -p "$AUSGABE" +xcodebuild \ + -project ios/App/App.xcodeproj \ + -scheme App \ + -configuration Release \ + -destination 'generic/platform=iOS' \ + -archivePath "$ARCHIV" \ + -allowProvisioningUpdates \ + 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. +cat > "$AUSGABE/ExportOptions.plist" < + + + + methoddevelopment + teamID$TEAM + signingStyleautomatic + stripSwiftSymbols + + +PLIST + +echo "==> .ipa exportieren" +xcodebuild -exportArchive \ + -archivePath "$ARCHIV" \ + -exportOptionsPlist "$AUSGABE/ExportOptions.plist" \ + -exportPath "$AUSGABE" \ + -allowProvisioningUpdates + +echo +echo "Fertig: $AUSGABE/App.ipa" +echo "Aufs Geraet: xcrun devicectl device install app --device $AUSGABE/App.ipa"