Der AASA-Endpoint auf cardecky.mana.how ist in cards/apps/web/src/routes/.well-known/apple-app-site-association/+server.ts gebaut (Commit bdce9c98 im cards-Repo). Produktion braucht jetzt nur noch die echte PUBLIC_APPLE_TEAM_ID als Env-Var + Deploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
148 lines
6.9 KiB
Markdown
148 lines
6.9 KiB
Markdown
# 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
|
||
|
||
- [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.
|
||
- [ ] **`PUBLIC_APPLE_TEAM_ID`** als Env-Var im cards-web-Production-
|
||
Deployment setzen. Default ist Platzhalter `XXXXXXXXXX` — Apple
|
||
lehnt die AASA mit Default-Wert ab.
|
||
- [ ] **Production-Deploy von cards-web** mit der echten Team-ID muss
|
||
laufen bevor TestFlight-Tester die Universal-Links nutzen können.
|
||
- [ ] **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.
|