diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index d64dd9c..0761d9c 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -51,7 +51,9 @@ Gerät, kein 30-Tage-Ablauf, einzeln widerrufbar). Deutsch und Englisch, iPad zweispaltig, offline der letzte Stand mit Datum. Stufe 1 ✅: Gerüst, Netzwerkschicht, Anmeldung samt zweitem Faktor und -Pflicht-Passwortwechsel, Kontenliste. Stufen 2–7 (Lesen, Schreiben, -Arbeitsliste, Nebenräume, Erweiterungen, voller CSV-Import) stehen aus. +Pflicht-Passwortwechsel, Kontenliste. Übersetzt fehlerfrei, 28 Tests grün, +läuft im Simulator; das Xcode-Projekt entsteht aus `ios/project.yml`. +Stufen 2–7 (Lesen, Schreiben, Arbeitsliste, Nebenräume, Erweiterungen, voller +CSV-Import) stehen aus. **Stand, Entscheidungen und offene Punkte: `ios/UEBERGABE.md`.** diff --git a/ios/README.md b/ios/README.md index 579a5c6..7187bd2 100644 --- a/ios/README.md +++ b/ios/README.md @@ -1,28 +1,38 @@ # Certain für iOS -Native App zum Certain-Backend. Der Code hier ist **nie übersetzt worden** — auf -der Maschine, auf der er entstanden ist, gibt es kein Xcode. Rechne beim ersten -Bauen mit Fehlern und schick sie mir; das ist eingeplant. +Native App zum Certain-Backend. > **Wer hier weiterarbeitet, liest zuerst [UEBERGABE.md](UEBERGABE.md).** Dort > steht, was entschieden ist, was fertig ist, was als Nächstes dran ist und -> welche Eigenheiten das Backend hat. Dieses README erklärt nur, wie man den -> Code ins Projekt bekommt. +> welche Eigenheiten das Backend hat. Dieses README erklärt nur das Projekt. -## Projekt anlegen +## Bauen und starten -1. Xcode → neues Projekt → **App**, Schnittstelle **SwiftUI**, Sprache **Swift**. -2. Mindestversion auf **iOS 26** stellen. -3. Als Geräte **iPhone und iPad** ankreuzen. -4. Die Datei `ContentView.swift`, die Xcode anlegt, **löschen** — `App/` bringt - einen eigenen Einstiegspunkt mit. -5. Die Ordner aus `ios/` per Ziehen ins Projekt übernehmen, mit *Create groups* - (nicht *folder references*). -6. `Texte/de.lproj` und `Texte/en.lproj` übernehmen und unter - *Project → Info → Localizations* **Deutsch** und **Englisch** eintragen. - Deutsch ist die Grundsprache. +Einfach `Certain.xcodeproj` öffnen — es liegt mit im Repository. -Der Ordner `Tests/` gehört in ein Test-Ziel, nicht in das App-Ziel. +Die Wahrheit ist aber `project.yml`: eine XcodeGen-Spezifikation, aus der das +Projekt entsteht. **Wer eine Swift-Datei anlegt, läuft danach einmal +`xcodegen generate`**, sonst kennt Xcode sie nicht. Ein neuer *Ordner* will +ausserdem eine Zeile unter `sources:`. + +``` +brew install xcodegen # einmalig +cd ios && xcodegen generate +xcodebuild -project Certain.xcodeproj -scheme Certain \ + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build +xcodebuild -project Certain.xcodeproj -scheme Certain \ + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' test +``` + +Festgelegt sind dort: Bündelkennung `com.scarriffle.certain`, Team +`PP34X97WS3`, iPhone und iPad, Grundsprache Deutsch, **iOS 26** als +Mindestversion, Sprachfassung Swift 5. Wer mit einem anderen Apple-Konto baut, +trägt seine Team-ID in `project.yml` ein. + +**Nur https.** App Transport Security steht auf der Voreinstellung, ein Server +unter `http://…` wird also abgewiesen — auch `http://localhost` beim +Entwickeln. Das ist Absicht: über die Verbindung geht die Gerätemarke, ein +Vollzugang. Wer eine Ausnahme braucht, trägt sie bewusst in `project.yml` ein. ## Was wohin gehört @@ -90,12 +100,17 @@ heraus, dass `created_at` ohne Zeitzone und mit Mikrosekunden kommt (`2026-10-20T14:18:15.780705`) — dafür hat `Zeitpunkt` einen dritten Leser, und `GrundlagenTests` deckt den Fall ab. -**Nicht geprüft:** Ob das Ganze übersetzt. Kein Xcode auf der Maschine, auf -der es entstanden ist. +**Ebenfalls geprüft:** Dass es übersetzt. Ein einziger Fehler in 2600 blind +geschriebenen Zeilen (`[:]` statt `[]` in `CertainClient.schickeDatei`), danach +keine Warnung im eigenen Code, 28 Tests grün, Start im Simulator bis zur +Serverabfrage. -### Wo es beim ersten Bauen am ehesten klemmt +**Nicht geprüft:** Der Weg gegen ein echtes Backend — anmelden, zweiter Faktor, +Marke anlegen, Konten laden. -Nach abnehmender Wahrscheinlichkeit: +### Wo es beim ersten Bauen am ehesten klemmte + +Nichts davon trat ein; die Liste bleibt als Landkarte der heiklen Stellen. 1. **`@testable import Certain`** in `Tests/GrundlagenTests.swift` — muss auf den Namen deines App-Ziels zeigen. Heisst es anders, anpassen. diff --git a/ios/UEBERGABE.md b/ios/UEBERGABE.md index 92551a7..cf52c5c 100644 --- a/ios/UEBERGABE.md +++ b/ios/UEBERGABE.md @@ -6,7 +6,7 @@ haben: was entschieden ist, was fertig ist, was als Nächstes dran ist, und was ich über das Backend herausgefunden habe. Lies sie ganz, bevor du anfängst — die Abschnitte „Was das Backend vorgibt" und „Fallen" ersparen dir Tage. -Stand: 20.10.2026, Commit `6b86a6b`. Alles committet und gepusht. +Stand: 21.10.2026, Commit `ffe1870`. Alles committet und gepusht. --- @@ -21,15 +21,23 @@ native iOS-App in `ios/`, die sich über eine eingegebene Server-Adresse (wie Dashboard, Arbeitsliste, Kategorien, Tags, Einstellungen, Bankabruf und der volle CSV-Import. -### Die wichtigste Rahmenbedingung +### Die Rahmenbedingung, die es nicht mehr gibt -Auf der Maschine, auf der der Code entsteht, **gibt es kein Xcode**. Der Swift- -Code wird blind geschrieben und nie übersetzt. Der Nutzer legt das Projekt an, -übersetzt und meldet die Fehler zurück. +Bis zum 21.10.2026 stand hier: es gibt kein Xcode, der Swift-Code wird blind +geschrieben und nie übersetzt. **Das gilt nicht mehr.** Auf dieser Maschine +liegt Xcode 27 mit Simulatoren für iOS 26.5 und 27, und `ios/project.yml` +erzeugt das Projekt. Übersetzen, Tests und Starten im Simulator gehen hier +direkt: -Daraus folgt die Arbeitsweise: **kleine Stufen, jede für sich übersetzbar.** -Nicht zehntausend Zeilen schreiben und dann einen Berg Fehlermeldungen -hinterlassen. Nach jeder Stufe übersetzt der Nutzer. +``` +cd ios && xcodegen generate # nach jeder neuen Datei +xcodebuild -project Certain.xcodeproj -scheme Certain \ + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build # oder test +``` + +**Übersetze nach jeder Stufe selbst, statt dem Nutzer Fehler zu hinterlassen.** +Die kleinen Stufen bleiben trotzdem richtig — nicht wegen der Fehlersuche, +sondern damit jede Stufe für sich benutzbar ist. --- @@ -44,7 +52,7 @@ Alle schon gefallen. **Nicht erneut fragen.** | Zusätzlicher Umfang | Arbeitsliste/Eingang, Kategorien und Tags, Einstellungen, Bankabruf anstossen | | Dashboard | Feste iOS-Ansicht, kein Raster | | iOS-Mindestversion | **iOS 26** | -| Ablieferung | Flache Ordner unter `ios/`, der Nutzer legt das Xcode-Projekt an | +| Ablieferung | Flache Ordner unter `ios/`; das Projekt entsteht seit dem 21.10. aus `project.yml` | | Anmeldung | App-Token (im Backend ergänzt, siehe unten) | | Erweiterungen | Teilen-Menü für Dateien, Kurzbefehle/Siri | | Sprachen | Deutsch **und** Englisch | @@ -224,7 +232,8 @@ sie beide Richtungen anbietet. Nötig für Stufe 3. | `Konten/` | `KontenListe` — die erste Fachansicht | | `Einstellungen/` | Platzhalter: zeigt den Zugang und lässt abmelden | | `Texte/` | `de.lproj` und `en.lproj`, zeilengleich | -| `Tests/` | `GrundlagenTests` — reine Logik, Swift Testing | +| `Tests/` | `GrundlagenTests` — reine Logik, Swift Testing, 28 Stück | +| `project.yml` | XcodeGen-Spezifikation, erzeugt `Certain.xcodeproj` | ### Wie die Anmeldung abläuft @@ -249,11 +258,17 @@ Wegwerf-Datenbank, Felder flach ausgeben, mit den `CodingKeys` vergleichen. (Das Passwort der Dev-Datenbank unter `backend/data/app.db` ist unbekannt — nicht raten, eine frische Testdatenbank nehmen.) -### Was nicht geprüft ist +### Dass es übersetzt, ist inzwischen geprüft -**Ob es übersetzt.** Der Nutzer hatte Stufe 1 beim Schreiben dieser Datei noch -nicht gebaut. Rechne damit, dass seine erste Rückmeldung Fehlermeldungen sind — -das ist eingeplant und kein Rückschlag. +Am 21.10.2026 gebaut, getestet und gestartet (Commit `ffe1870`). Genau **ein** +Übersetzungsfehler in 2600 blind geschriebenen Zeilen: der Vorgabewert +`[String: String] = []` in `CertainClient.schickeDatei` musste `[:]` heissen. +Sonst keine Fehler, keine Warnung im eigenen Code. Die 28 Tests laufen durch, +die App startet im Simulator bei der Serverabfrage. + +**Noch nicht geprüft: der Weg gegen ein echtes Backend.** Anmelden, zweiter +Faktor, Marke anlegen, Kontenliste — das lief bisher nur gegen die Modelle, +nicht gegen einen laufenden Server. Siehe „Klartext-HTTP" unten. --- @@ -306,20 +321,26 @@ Einwand und will den vollen Import trotzdem. ## 7. Fallen und Arbeitsweise -### Beim Übersetzen am ehesten verdächtig +### Klartext-HTTP — der nächste Stolperstein -Nach abnehmender Wahrscheinlichkeit: +Das Projekt läuft mit der Voreinstellung von App Transport Security, also +**nur https**. Ein selbstgehosteter Server im Heimnetz unter `http://…` wird +abgewiesen, und `http://localhost` beim Entwickeln ebenso — obwohl +`ServerAnsicht` http ausdrücklich zulässt und ein Test das festhält +(„http bleibt http"). Wer gegen ein lokales Backend prüfen will, braucht +in `project.yml` eine ATS-Ausnahme. Das ist eine Sicherheitsentscheidung des +Nutzers: über Klartext geht die Gerätemarke, ein Vollzugang, mit jeder +Anfrage mit. -1. **`@testable import Certain`** in `Tests/GrundlagenTests.swift` muss auf den - Namen des App-Ziels zeigen. -2. **`Lader` ist eine generische `@Observable`-Klasse** — die ungewöhnlichste - Konstruktion im Code. Wird bisher nur in `KontenListe` benutzt. -3. **Nebenläufigkeit:** `AppZustand` ist `@MainActor`, `CertainClient` ein - Actor. An den Übergängen kann es unter strikter Prüfung Warnungen setzen. -4. **`Tab` und `.tabViewStyle(.sidebarAdaptable)`** setzen iOS 18 voraus — bei - iOS 26 als Mindestversion kein Problem. -5. Die Tests nutzen **Swift Testing** (`import Testing`, `@Test`, `#expect`), - nicht XCTest. +### Was beim Übersetzen auffiel + +Alles, was hier als verdächtig stand, hat gehalten: `Lader` als generische +`@Observable`-Klasse, der `@MainActor`/Actor-Übergang zwischen `AppZustand` +und `CertainClient`, `Tab` mit `.tabViewStyle(.sidebarAdaptable)`, Swift +Testing statt XCTest. Eine Einschränkung: Das Projekt baut in **Sprachfassung +Swift 5**. Unter Swift 6 greift die strikte Nebenläufigkeitsprüfung, und die +Übergänge sind darauf nicht geschrieben — wer umstellen will, rechnet mit +Arbeit an genau diesen Stellen. ### Schreibende Aufrufe mit Query statt Körper @@ -336,6 +357,8 @@ Leicht zu übersehen, das Backend macht es an mehreren Stellen: Commit. Fertige Arbeit wird committet und gepusht, ohne Rückfrage. - **Kommentare erklären das Warum**, nicht das Was — und zwar das, was der Code nicht zeigen kann. Das ganze Projekt ist so geschrieben; halte es durch. +- **Neue Swift-Datei?** Danach `cd ios && xcodegen generate`. Die Ordner stehen + einzeln in `project.yml`; ein neuer Ordner will dort eine Zeile. - **Tests**: `cd backend && ./.venv/Scripts/python.exe -m pytest tests/ -q` (Python 3.12 im venv; das System-Python kann nicht bauen). Dauert rund zwei Minuten — im Hintergrund laufen lassen.