v0.8.0 — Phase β-7 App-Store-Vorbereitung

Feature-komplett für TestFlight. App-Icon-Platzhalter, Siri-Shortcut,
Share-Extension, Release-Checklist mit allen externen Apple-Schritten.

- scripts/make-appicon.swift: CoreGraphics-basierter Generator für
  1024×1024 forest-green PNG mit "C"-Letter und Karten-Stack-Schatten
- Asset-Catalog auf Single-Size-AppIcon-Pattern umgestellt
- StudyCardsIntent + CardsAppShortcuts (App Intents): Siri-
  Shortcut "Karten lernen mit Cards" / "Mit Cards lernen"
- CardsShareExtension Target: ShareViewController (UIKit-Bootstrap +
  SwiftUI-Hosting), ShareEditorView mit Text-Edit
- PendingShare + PendingShareStore shared in App-Group
  group.ev.mana.cards
- DeckListView zeigt PendingShare-Banner; Tap navigiert zu
  PendingShareConsumeView mit Deck-Picker + Front/Back-Felder, Submit
  → POST /cards, danach store.remove
- Info.plist: NSPhotoLibraryUsageDescription für Image-Occlusion-
  Picker, NSUserActivityTypes für Universal-Links
- docs/RELEASE_CHECKLIST.md mit externen Schritten: Apple-Developer-
  Portal, App-IDs, App-Group, AASA, Xcode-Archive, TestFlight-Plan,
  App-Store-Connect-Felder, Compliance-Verifikation
- UI-Test robuster (akzeptiert Login oder Decks/Entdecken als
  Launch-Erfolg, unabhängig vom Simulator-Keychain-State)
- 35 Tests + 1 UI-Test grün, alle drei Targets bauen

App-Store-Submission selbst ist externe Aktion und passiert nicht
durch dieses Repo — Schritte in docs/RELEASE_CHECKLIST.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-13 01:13:27 +02:00
parent 55359c5333
commit 0b2ae167b7
16 changed files with 783 additions and 59 deletions

153
docs/RELEASE_CHECKLIST.md Normal file
View file

@ -0,0 +1,153 @@
# RELEASE_CHECKLIST — cards-native
Externe Schritte vor App-Store-Submission. Alles unter dieser
Sektion läuft NICHT durch das Repo — sondern durch das Apple-
Developer-Portal, App-Store-Connect, das Cards-Web-Repo (für
AASA) und über Xcode (für Build + Sign).
## Vor TestFlight (intern, kein Apple-Review)
### Apple-Developer-Konfiguration
- [ ] **Team-ID prüfen** für den mana-e.V.-Apple-Developer-Account.
Eintragen in `project.yml > settings > base > DEVELOPMENT_TEAM`
(oder per-Scheme in Xcode unter "Signing & Capabilities").
- [ ] **App-ID `ev.mana.cards`** im Developer-Portal anlegen, falls
noch nicht da. Mit Capabilities: App Groups, Keychain Sharing,
Associated Domains.
- [ ] **App-ID `ev.mana.cards.share`** + **`ev.mana.cards.widget`** für
die Extensions analog anlegen, ebenfalls mit App Groups.
- [ ] **App-Group `group.ev.mana.cards`** im Portal anlegen und allen
drei App-IDs zuweisen.
- [ ] **Keychain-Access-Group**: heute `ev.mana.cards`. Wenn
Shared-Keychain mit `memoro-native` gewünscht (siehe
`mana/docs/MANA_SWIFT.md` Phase γ), auf
`$(AppIdentifierPrefix)ev.mana.shared` umstellen und
`AppConfig.manaAppConfig.keychainAccessGroup` setzen.
- [ ] **Provisioning Profiles** für alle drei Targets generieren
(Development + Distribution). Bei "Automatic Signing" macht
Xcode das beim ersten Build selbst, wenn das Team-ID stimmt.
### Asset-Polish
- [ ] **AppIcon ersetzen.** Heute Platzhalter aus
`scripts/make-appicon.swift` (forest-green "C"). Vor Submission
durch ein vom Designer erstelltes Icon austauschen
(`Sources/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png`).
- [ ] **Marketing-Versionsnummer** in `project.yml` setzen
(`MARKETING_VERSION` → "1.0.0").
- [ ] **Build-Nummer** monoton inkrementieren bei jedem TestFlight-
Upload (`CURRENT_PROJECT_VERSION`).
### Server-seitige Vorbedingungen
- [ ] **AASA-Endpoint** auf `cardecky.mana.how/.well-known/apple-app-site-association`
ausliefern (heute 404). Format:
```json
{
"applinks": {
"apps": [],
"details": [{
"appID": "<TEAMID>.ev.mana.cards",
"paths": ["/d/*"]
}]
}
}
```
Content-Type muss `application/json` sein (nicht `text/html`).
Aufgabe ans Cards-Web-Repo.
- [ ] **cardecky-api.mana.how** muss erreichbar bleiben — die App
ist 100% Online-write. Health-Probe verifizieren.
### Build + Archive
- [ ] `xcodegen generate`
- [ ] In Xcode: Product → Archive (Destination "Any iOS Device")
- [ ] Im Organizer: Validate App
- [ ] Distribute App → TestFlight & App Store
### TestFlight-Test-Plan
- [ ] **Endurance:** 200+ Karten lernen, Flugmodus zwischendurch.
- [ ] **Cross-Device:** Web↔Native parallel. Karte gegrade in App →
Web zeigt nach Reload identischen Review-State.
- [ ] **Widget:** ans Home-Screen pinnen, Due-Count nach App-Refresh.
- [ ] **Universal-Link:** `https://cardecky.mana.how/d/<slug>` in
Safari öffnen → App startet auf Explore-Tab + Public-Deck-Detail.
- [ ] **Share-Extension:** Text in Safari markieren → Teilen → "Als
Karte speichern" → Karte landet in der App.
- [ ] **Siri-Shortcut:** "Hey Siri, Karten lernen" → App öffnet.
- [ ] **Daily-Reminder:** Tagesgrenze überqueren, Notification kommt
zur konfigurierten Uhrzeit.
- [ ] **Login/Logout:** kompletter Auth-Roundtrip.
- [ ] **Offline-Grades:** Reviews offline machen, online gehen,
`PendingGrade`-Queue läuft leer.
## Vor App-Store-Submission (öffentliches Review)
### App-Store-Connect
- [ ] **App-Eintrag erstellen** unter https://appstoreconnect.apple.com
mit Bundle-ID `ev.mana.cards`.
- [ ] **App-Name** + **Subtitle** (max 30 Zeichen):
- Name: "Cards"
- Subtitle: "Karteikarten — Verein mana"
- [ ] **Description** (de + en, max 4000 Zeichen). Vorschlag siehe
`docs/MARKETING_COPY.md` (existiert noch nicht — TODO).
- [ ] **Keywords** (max 100 Zeichen, comma-separated):
"Karteikarten,Spaced Repetition,Lernen,Vokabeln,Anki,Flashcards,FSRS,mana,Verein,Open Source"
- [ ] **Screenshots** für iPhone 16 Pro Max + iPhone SE-3 + iPad Pro.
6.7", 6.5", 5.5", iPad 12.9" — siehe Apple's Specs.
- [ ] **Privacy-Policy-URL** — vermutlich `cardecky.mana.how/privacy`
oder `mana-ev.ch/privacy`. **Verifizieren.**
- [ ] **Support-URL**`cardecky.mana.how/help` oder Verein-Kontakt.
- [ ] **Marketing-URL** (optional) — `cardecky.mana.how`.
- [ ] **Age-Rating**: vermutlich 4+ (no objectionable content).
- [ ] **Pricing**: Free.
- [ ] **App-Privacy** (Data Type Declaration):
- Email-Adresse (für Login)
- User-Inhalt (Karten, Decks)
- Nutzungsdaten (FSRS-Reviews)
- **Nicht** für Tracking verwendet.
### Compliance / Verein-Werte
- [ ] **Lese `mana/docs/COMPLIANCE.md`** und prüfe, dass keine
Telemetrie, kein Crash-Reporter, kein SaaS-Tracker in Submission-
Build (Stripe + APNs sind die akzeptierten Ausnahmen — Cards
nutzt keines davon heute).
- [ ] **Subscriptions / In-App-Purchases**: Marketplace-Paid-Decks
sind über `mana-credits` abgewickelt, nicht über StoreKit. Im
App-Store-Connect "no In-App-Purchases" auswählen, **außer**
wir wollen vor Submission StoreKit für `mana-credits` einführen
(separate Architektur-Frage).
### Hub-App vs Standalone-App (siehe MANA_SWIFT.md)
- [x] Entschieden: separate Apps. memoro-native und cards-native sind
eigenständige App-Store-Einträge. Keine Hub-App.
## Carryover-Tasks (β-6 / β-7-Reste)
- [x] Siri-Shortcut via App Intents (`StudyCardsIntent`) — funktional,
v1: nur "App öffnen". Erweiterung "Direkt in Default-Deck-Study"
kann später kommen.
- [x] Share-Extension "Save as Card" — Pragma-Lösung: Extension
speichert `PendingShare` in App-Group, Haupt-App zeigt Banner,
User wählt Ziel-Deck und Back-Text. Kein direkter API-Call aus
der Extension (Auth-State wäre kompliziert, Pragma reicht für v1).
- [ ] **Card-Edit** (PATCH `/cards/:id`): heute deferred, ergänzen wenn
Beta-User danach fragen.
- [ ] **Anki-Import**: heute deferred, weil Web client-side parsed
und kein Server-Endpoint existiert. Native bräuchte eigenen
`.apkg`-Parser (sqlite-basiert) — eigener Sprint.
## Nach Submission
- [ ] **Monitoring**: nach Release `cardecky-api.mana.how/healthz` und
Rate-Limit-Auslastung beobachten — Native-App kann Last-Spitzen
erzeugen.
- [ ] **DSGVO-Endpoint** (`/api/v1/dsgvo/export`, `/delete`) testweise
aus Native triggerbar machen (β-7-Extension oder β-8).
- [ ] **Update-Cadence**: erstmal alle 2-4 Wochen ein Build.
Build-Nummer monoton, Marketing-Version semver.