# 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 - [x] **Team-ID gesetzt** (`QP3GLU8PH3`, mana e.V.) — `DEVELOPMENT_TEAM` in `project.yml > settings > base`. Greift bei Archive automatisch. - [ ] **App-ID `ev.mana.cardecky`** im Developer-Portal anlegen, falls noch nicht da. Mit Capabilities: App Groups, Keychain Sharing, Associated Domains. - [ ] **App-ID `ev.mana.cardecky.share`** + **`ev.mana.cardecky.widget`** für die Extensions analog anlegen, ebenfalls mit App Groups. - [ ] **App-Group `group.ev.mana.cardecky`** im Portal anlegen und allen drei App-IDs zuweisen. - [ ] **Keychain-Access-Group**: heute `ev.mana.cardecky`. 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 - [x] **AASA-Endpoint** auf `cardecky.mana.how/.well-known/apple-app-site-association` — SvelteKit-Server-Route gebaut in `cards/apps/web/src/routes/.well-known/apple-app-site-association/+server.ts` (2026-05-13). Content-Type `application/json`, paths `/d/*` und `/u/*`. Lokal mit `node build` + curl verifiziert. - [x] **`PUBLIC_APPLE_TEAM_ID=QP3GLU8PH3`** in `cards/infrastructure/docker-compose.production.yml` hinterlegt (Commit folgt). Wird zur Runtime von `$env/dynamic/public` aufgelöst und in den AASA-Response geschrieben. - [x] **Production-Deploy von cards-web** durchgeführt 2026-05-13. Probe von außen: `curl https://cardecky.mana.how/.well-known/apple-app-site-association` liefert `application/json` mit `"appID":"QP3GLU8PH3.ev.mana.cardecky"`. Cloudflare-Tunnel reicht den Endpoint sauber durch (kein HTML-Captive, kein Redirect). - [ ] **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/` 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.cardecky`. - [ ] **App-Name** + **Subtitle** (max 30 Zeichen): - Name: "Cards" - Subtitle: "Karteikarten — Verein mana" - [ ] **Description** (de + en, max 4000 Zeichen). Vorschlag in [`docs/MARKETING_COPY.md`](MARKETING_COPY.md) — vor Submission gegenlesen und Vereins-Tonalität schärfen. - [ ] **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. - [x] **Privacy-Policy-URL**: `https://cardecky.mana.how/privacy` (live seit 2026-05-13, SvelteKit-Route mit Verein-Content). - [x] **Support-URL**: `https://cardecky.mana.how/help` (live, FAQ + Kontakt-Email kontakt@mana-ev.ch). - [ ] **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.