Files
audi-app/APPLE_DEV_BACKLOG.md
T
tobias e6a9ff4ec8 Apple-Backlog traegt jetzt den Ablauf eines Xcode-Laufs
Auf die Frage, welche Datei man am Mac in die Hand nimmt: der Backlog war die
richtige Antwort, ihm fehlte aber genau das - er beschrieb den Zustand und die
Pruefliste, nicht den Ablauf.

Neuer Abschnitt "Wie ein Lauf abläuft": was vorher zu tun ist (git pull; das
Skript bricht selbst ab, wenn der Baum unsauber oder HEAD nicht gleich
origin/main ist), der eine Befehl samt seiner dreizehn Schritte, dass die
Fassung aus manifest.json kommt und nichts von Hand hochzuzaehlen ist, das
einmalige Schluesselbund-"Immer erlauben" samt Symptom wenn man es uebersieht,
und danach Push plus der itms-services-Link in Safari - ausdruecklich ohne ?v=,
mit Verweis auf den Befund aus Abschnitt CK.

Damit ist die Datei als alleinige Uebergabe brauchbar; AGENTS.md braucht man nur
noch fuers Warum. OFFEN.md 1.1 verweist entsprechend darauf.
2026-09-07 12:09:36 +02:00

207 lines
8.4 KiB
Markdown

# Apple Dev Backlog (DM360)
Alles, was einen **Xcode-Lauf** oder das **Apple Developer Portal** braucht,
wird hier gesammelt - und nur hier.
**Warum:** ein Xcode-Lauf lohnt sich nicht für eine einzelne native Änderung.
Er wird erst gestartet, wenn eine nennenswerte Menge zusammengekommen ist; die
Entscheidung darüber trifft der Eigentümer, nicht eine Sitzung.
## Arbeitsregel (verbindlich)
* Jede Aufgabe, die Xcode oder das Apple-Portal braucht, kommt **in diese
Datei**, in derselben Sitzung, in der sie auffällt - nicht in eine Notiz im
Bericht und nicht nur in `AGENTS.md`.
* **Nichts davon wird von sich aus gestartet.** Ein Xcode-Lauf ist eine
Handlung des Eigentümers am Mac; eine Sitzung bereitet ihn vor und meldet,
wenn sich genug angesammelt hat.
* Was **ohne** Xcode geht, gehört nicht hierher: Änderungen an der Oberfläche
der App reisen im OTA-Bündel (`@capgo/capacitor-updater`), Änderungen am Panel
und am Backend über die Selbstaktualisierung der Integration. Nur nativer
Code, Plugins, Berechtigungen, Signatur und Auslieferungsweg brauchen einen
Lauf.
* Erledigtes wird **nicht gelöscht**, sondern nach unten unter „Erledigt"
verschoben - mit der Fassung, in der es ausgeliefert wurde. Sonst wird
dieselbe Frage in einem halben Jahr wieder aufgemacht.
---
## Stand der ausgelieferten App
Gemessen am Artefakt `companion-app/auslieferung/App.ipa`, nicht aus dem
Gedächtnis (06.09.2026):
| | |
|---|---|
| Fassung | **2026.9.4.17** (Build 1), App und Erweiterung gleich |
| Bundle-ID | `app.datametric360`, Erweiterung `app.datametric360.teilen` |
| Profile | beide Ad Hoc, **2 Geräte**, gültig bis **2027-08-29** |
| Berechtigungen | Standort, Kalender (beide Schlüssel), Kamera - alle vorhanden |
| `packageClassList` | **6 Klassen - beide eigenen Plugins fehlen** |
Zum Vergleich: das Repository steht auf `2026.9.6.5`. Der Abstand ist **kein**
Rückstand - alles dazwischen war Oberfläche und Backend und reist über OTA. Was
wirklich auf einen Lauf wartet, steht unten.
---
## Wie ein Lauf abläuft
**Diese Datei ist die Übergabe.** Wer am Mac sitzt - mit oder ohne Claude am
Xcode - braucht keine weitere: hier steht der Stand, der eine Befehl, und was
danach zu prüfen ist. `AGENTS.md` ist nur für das *Warum* nötig.
### Vorher
Nichts vorzubereiten außer einem aktuellen Stand:
```bash
git pull
```
Das Skript prüft das selbst und **bricht ab**, wenn der Arbeitsbaum nicht sauber
oder `HEAD` nicht gleich `origin/main` ist - sonst signierte es einen veralteten
Stand. Ebenso bricht es ab, wenn das Zielgerät nicht im Team eingetragen ist
(„Your team has no devices"); das ist dann eine Portal-Sache, kein Projektfehler.
### Der Lauf
```bash
bash companion-app/scripts/ios-signieren.sh
```
Ein Befehl, von jedem Verzeichnis im Repository aus. Er wechselt selbst nach
`companion-app/` und erledigt der Reihe nach: Git-Stand prüfen, Webbündel bauen,
native Hülle synchronisieren, Standort-/Kalender-/Kamera-Berechtigung eintragen,
Share-Erweiterung einrichten, App-Symbol einspielen, Versionsnummern setzen,
Archiv bauen und signieren, `.ipa` exportieren, **die fertige `.ipa` gegenlesen**
und die Auslieferung über die Luft vorbereiten.
**Die Fassung kommt aus `custom_components/audi_dashboard/manifest.json`** - es
gibt nichts von Hand hochzuzählen. Beim Schreiben dieser Zeilen wäre das
`2026.9.6.5`.
**Einmalig beim ersten Signieren:** der Schlüsselbund fragt, ob `codesign` den
Schlüssel benutzen darf. **„Immer erlauben"** wählen, nicht „Erlauben" - ein
Archiv signiert über 25 Programmteile und fragte sonst jedes Mal erneut. Bleibt
der Lauf minutenlang beim Signieren stehen, wartet er auf genau diesen Dialog.
### Danach
```bash
git add companion-app/auslieferung && git commit && git push
```
Das Telefon lädt die `.ipa` aus dem Repository - ohne diesen Push ändert sich
dort nichts. Danach in **Safari** auf dem Telefon öffnen (andere Browser reichen
`itms-services://` nicht an das System weiter):
```
itms-services://?action=download-manifest&url=https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/companion-app/auslieferung/manifest.plist
```
Die Adresse trägt **kein** `?v=` - ein zweites Fragezeichen zerlegt den
Parameter, und weil iOS die Rückfrage erst aus dem geladenen Manifest baut,
passiert dann sichtbar gar nichts (Abschnitt CK).
Zum Schluss die eine Prüfung, die kein Skript abnehmen kann - siehe Abschnitt C
unten.
---
## A. Wartet auf einen Xcode-Lauf
### A1. Zwei eigene Plugins sind auf dem Telefon tot
**Auswirkung: Zwischenablage und Kalendereintrag funktionieren nicht.** Das ist
die einzige Position mit sichtbarem Ausfall.
Capacitor 8 registriert ausschließlich, was in `packageClassList` der
`capacitor.config.json` im Bündel steht (`CapacitorBridge.swift`,
`registerPlugins()`). Diese Liste erzeugt `cap sync` aus den installierten
npm-Paketen - app-eigene Plugins sind keine. Beide Klassen liegen nachweislich
im Programm der ausgelieferten `.ipa` und werden trotzdem nie registriert.
*Korrektur liegt im Repo* (`a99ae43`): `ios-teilen-einrichten.mjs` trägt die
Klassen nach jedem `cap sync` nach und liest ihre Namen aus den Swift-Dateien
selbst, damit sie nicht an zwei Stellen gepflegt werden. `ios-signieren.sh`
**bricht ab**, wenn eine davon im fertigen Bündel fehlt.
Hintergrund vollständig: `AGENTS.md`, Abschnitt DH und CM.
### A2. Installationslink ohne zweites Fragezeichen
`ios-luftweg.sh` hängte den Cache-Brecher `?v=` auch an die Manifest-Adresse
**innerhalb** des `itms-services`-Links - damit steht dort ein zweites `?`, der
Abruf scheitert, und weil iOS die Rückfrage erst aus dem geladenen Manifest
baut, passiert sichtbar gar nichts.
*Korrektur liegt im Repo* (`6365136`). Die bereits ausgelieferte
`auslieferung/index.html` wurde von Hand nachgezogen; das Skript zieht beim
nächsten Lauf nach. Hintergrund: `AGENTS.md`, Abschnitt CK.
---
## B. Wartet auf das Apple Developer Portal
Derzeit **nichts offen.** App-Gruppe, beide App-IDs und die Gerätefreigabe sind
eingerichtet (Abschnitt AK), die Profile laufen bis 2027-08-29.
Vorzumerken, aber noch lange hin:
* **2027-07-17** - das Entwicklerzertifikat läuft ab.
* **2027-08-29** - beide Bereitstellungsprofile laufen ab.
* Ein **neues Gerät** braucht eine Registrierung im Portal *und* frisch
ausgestellte Profile. Ein bereits ausgestelltes Profil erfährt von einem neuen
Gerät nichts - deshalb räumt `ios-signieren.sh` die zwischengespeicherten
Profile vor dem Bauen weg (Abschnitt AI).
---
## C. Nach dem Lauf zu prüfen
Am **fertigen Bündel**, nicht am Projekt. Die Begründung steht in Abschnitt AK:
von fünf Fehlern der nativen Hülle haben vier einen erfolgreichen Archivlauf
erzeugt und sind erst am entpackten `.ipa` aufgefallen.
Das Skript prüft selbst und bricht ab, wenn etwas fehlt:
1. Die Erweiterung hat ein echtes Programm.
2. App und Erweiterung tragen dieselbe `CFBundleShortVersionString` **und** eine
brauchbare `CFBundleVersion` (ohne die lehnt iOS die Installation der ganzen
App ab - Abschnitt CD).
3. Die App-Gruppe steht in den Entitlements **beider** Ziele.
4. Beide eigenen Plugin-Klassen stehen in `packageClassList`.
**Von Hand bleibt genau eine Prüfung** - auf dem Gerät: einen Beleg über das
Teilen-Blatt schicken, ein PDF aus der Zwischenablage einfügen, einen
Kalendereintrag anlegen. Ob die Plugins *registriert* sind, sagt Punkt 4; ob sie
*tun*, was sie sollen, sagt nur das Telefon.
---
## Was der Lauf von selbst erledigt
Damit es niemand ein zweites Mal von Hand macht: `ios-signieren.sh` trägt bei
jedem Lauf Standort-, Kalender- und Kamera-Berechtigung ein, richtet die
Share-Erweiterung ein, spielt das App-Symbol ein und setzt die Versionsnummern
in beide Ziele. Das muss sein, weil `companion-app/ios/` gitignored ist und von
`npx cap add ios` jederzeit neu erzeugt wird - alles, was man in Xcode
anklickt, wäre danach weg (Abschnitt AI).
Unvermeidlich von Hand bleiben: die einmalige Portal-Einrichtung, das
Schlüsselbund-„Immer erlauben" beim ersten Signieren, und `git push` der
fertigen `.ipa`, weil das Telefon sie aus dem Repository lädt.
---
## Erledigt
| Fassung | Was |
|---|---|
| 2026.9.4.17 | Kamera-Berechtigung für den QR-Scanner |
| 2026.9.4.7 | `CFBundleVersion` in beiden Bündeln - die App war vorher nicht installierbar |
| 2026.9.4.5 | Versionsnummern von App und Erweiterung angeglichen |
| 2026.9.2.7 | Share-Erweiterung, Zwischenablage- und Kalender-Plugin gebaut und signiert |
| 2026.8.30.8 | Erste signierte `.ipa`, Luftweg über Gitea eingerichtet |