App Store Precheck
Ein Ein-Befehl-Gate, das vor jeder iOS-App-Store-Einreichung ausgeführt wird. Es minimiert das Risiko einer Ablehnung, indem es die häufigsten Ablehnungsvektoren statisch scannt, Apples eigenen Metadaten-Linter ausführt, nach Richtlinienänderungen Ausschau hält und eine adversarial Review simuliert.
Dieses Skill ist schreibgeschützt. Es bearbeitet niemals Code, Metadaten oder Assets. Es meldet nur Ergebnisse und schreibt ein Pass-Token. Die detaillierte Methode (jeder Ablehnungsvektor, die Mechanik der Richtlinienprüfung) befindet sich in references/methodology.md; lies sie, wenn du die Hintergründe einer Prüfung benötigst.
Wann ausführen
- Vor dem Archivieren für TestFlight.
- Vor dem Klicken auf "Zur Überprüfung einreichen" in App Store Connect.
- Vor jedem
fastlane deliver/release/pilot(der optionale Upload-Guard-Hook schaltet dieses Gate frei). - Bei jedem Point Release.
Führe es bewusst aus. Dies ist ein manuell ausgelöstes Gate, kein automatischer Hintergrundschritt.
Konfiguration (optional)
Der Scanner erkennt automatisch ein standardmäßiges fastlane- und Xcode-Layout, sodass die meisten Projekte keine Konfiguration benötigen. Um die Erkennung zu überschreiben, kopiere config.example.json nach .appstore-precheck.json im Repository-Stammverzeichnis. Schlüssel: bundleId (erforderlich für Phase 2), iosSourceDir, metadataDir, screenshotsDir, xcstringsPath, paywallGlobs, locales, disclosureKeys.{subscription,trial}, optionalChecks.familyControls, reviewPrepNotes. Die vollständige kommentierte Liste findest du in config.example.json.
Ausgabe-Vertrag
Das Skill erreicht einen von drei Endzuständen:
| Zustand | Bedeutung | .precheck-pass-Token | Guard-Verhalten |
|---|---|---|---|
| GRÜN | Kein FEHLER, ≤2 WARNUNGEN | Geschrieben (60 Min. gültig) | Upload erlaubt |
| GELB | Kein FEHLER, aber 3+ WARNUNGEN | Nicht geschrieben | Guard blockiert; fordert explizite Bestätigung |
| ROT | Mindestens 1 FEHLER | Entfernt | Guard blockiert; zeigt die FEHLER-Liste |
Wenn du dem Benutzer das Urteil präsentierst, beginne mit einer einzigen, charakteristischen Zeile von Pierre (dem französischen App-Review-Kritiker, siehe Phase 3), dann wechsel sofort zur sachlichen, präzisen Aufschlüsselung. Die Stimme ist eine dünne Hülle. Die darunterliegenden Daten – die FEHLER/WARNUNGEN-Liste, file:line-Referenzen und Korrekturen – bleiben sauber und maschinentreu. Schreibe scan.sh-Ausgabe niemals um oder paraphrasiere sie, und beschränke Pierre auf eine Zeile.
Ablauf (5 Phasen: 0–4)
Phase 0: Live-Prüfung auf Richtlinienänderungen
Vergleiche die aktuellen App Store Review Guidelines Abschnittsnummern mit guidelines-baseline.json, um zu erkennen, ob Apple seit der letzten Abstimmung einen Abschnitt hinzugefügt oder entfernt hat. Immer nicht-blockierend (maximal WARNUNG). Eine Abweichung ist eine Lücke in unserer Abdeckung, niemals ein Fehler des Builds. Die Seite wird beim Abruf abgeschnitten, daher ist eine Zwei-Durchlauf-Technik erforderlich; die genauen Aufforderungen und das Abstimmungsverfahren sind in references/methodology.md beschrieben. Die Baseline wird niemals automatisch aktualisiert. Die Abstimmung ist ein bewusster menschlicher Schritt.
Phase 1: Statischer Scan
bash skills/appstore-precheck/scripts/scan.sh
Gibt FAIL: / WARN: / PASS: Zeilen aus, die 20 Ablehnungsvektoren abdecken: Privacy Manifest Konformität (5.1.1(v)), Zweckstrings (5.1.1), ATT (5.1.2), Erwähnung anderer Plattformen (2.3.10), Metadaten-Grenzen (2.3.1), Lokalisierungsparität (2.3.7), Screenshots (2.3.3), Probe- und Auto-Renew-Offenlegungen (3.1.2), Wiederherstellen/AGB/Datenschutz-Links (3.1.2), private API (2.5.1), Mindestfunktionalität (4.0), „Mit Apple anmelden“-Parität (4.8), externe Kauf-Links (3.1.1(a)), eine optionale Screen Time/FamilyControls-Begründung (5.1.5), Tracking/IDFA-SDK ohne ATT-Abfrage (5.1.2), den Export-Compliance-Schlüssel (ITSAppUsesNonExemptEncryption), Support/Datenschutz-URLs in fastlane-Metadaten (2.3), Analyse-SDK vs. PrivacyInfo-Datentypen (5.1.1) und Platzhalter-/Dummy-Metadaten-Kopien (2.1). Die IAP-Prüfungen (8–10) werden automatisch übersprungen, wenn keine In-App-Kauf-Signale vorhanden sind. Die vollständige Prüftabelle befindet sich in references/methodology.md.
Der Scanner ist portables Bash, daher kannst du ihn auch direkt, außerhalb eines Agenten, für einen schnellen CI- oder Pre-Commit-Check ausführen.
Phase 2: Apples offizielles fastlane precheck
Erfordert bundleId in der Konfiguration (oder übergib app_identifier direkt) sowie App Store Connect API-Anmeldedaten. Den Schlüssel niemals committen. Der gebündelte Wrapper erstellt das ASC-API-Key-JSON aus deiner Umgebung, führt precheck aus und löscht den Schlüssel beim Beenden (verwende --dry-run, um den Befehl ohne Anmeldedaten und ohne Netzwerk anzuzeigen):
ASC_KEY_ID=… ASC_ISSUER_ID=… ASC_P8_PATH=/pfad/AuthKey.p8 \
bash skills/appstore-precheck/scripts/phase2-precheck.sh com.example.app
Oder führe es manuell aus: Generiere das Key-JSON aus deiner Umgebung, führe precheck aus und lösche es dann.
fastlane run precheck \
app_identifier:"<DEINE_BUNDLE_ID>" \
api_key_path:"/tmp/asc-key.json" \
include_in_app_purchases:false \
default_rule_level:":error"
rm -f /tmp/asc-key.json # löscht das Geheimnis sofort
Apples eigene Regel-Engine prüft URLs, GitHub-Erwähnungen, Obszönitäten, Apple-Marken, Preissprache und Beta-Schlüsselwörter. Result: true → BESTANDEN; jede Verletzungszeile → FEHLER. IAP wird bereits von Phase 1 abgedeckt, daher vermeidet include_in_app_purchases:false die API-Key-IAP-Einschränkung.
Phase 3: Adversarial Review (am wichtigsten)
Starte einen Unteragenten, der die Rolle von Pierre spielt, einem skeptischen Apple App Review mit dem anspruchsvollen Gaumen eines französischen Kritikers. Verwende diese Aufforderung wörtlich und fülle die App-spezifischen Details ein:
Du bist Pierre, ein erfahrener Apple-App-Reviewer, der wie ein französischer Kritiker rezensiert. Du hast zehntausend Ablehnungen gesehen und bist von keiner beeindruckt. Eine neue Einreichung ist gerade auf deinem Schreibtisch gelandet. Deine Aufgabe ist es, realistisch zu versuchen, sie abzulehnen, ohne Zulassungsbias. Wähle 5 zufällige Richtlinienpunkte aus, verteilt auf die Abschnitte (einen 2.x, zwei 3.x mit Gewichtung auf Paywall, einen 4.x, einen 5.x); wähle bei jedem Durchlauf eine andere Kombination (füge eine Seedzeile ein, damit Wiederholungen variieren). Für jeden Punkt: (Durchgang A) durchsuche die relevanten Dateien nach mindestens 2 konkreten Beweisstücken: Metadaten für 2.3.x; die Paywall-Ansicht + String-Katalog für 3.1.x; Core/Navigation für 4.x; Info.plist + PrivacyInfo für 5.1.x. (Durchgang B) Frage: „Als Reviewer, auf welcher Grundlage würde ich dies beanstanden?“ (Durchgang C) Schreibe einen Ablehnungsentwurf in Apples echter Stimme (Guideline X.Y.Z – Kategorie / Wir haben festgestellt… / Insbesondere… / Nächste Schritte… / Ressourcen…). Weise jedem Punkt ein Risiko zu: ABLEHNUNG-SICHER / ABLEHNUNG-RISIKO / WARNUNG / BESTANDEN. Beende mit einer Einreichungsempfehlung (STOPP / MIT WARNUNGEN EINREICHEN / LOS) und der einzigen wichtigsten Korrektur. Schreibgeschützt: Ändere niemals Dateien; wenn du keine Beweise findest, sage dies, anstatt sie zu erfinden. Halte es unter 500 Wörtern. Füge mindestens ein BESTANDEN und mindestens einen risikobehafteten Punkt ein, um eine realistische Verteilung zu gewährleisten.
Phase 4: Konsolidierung + Token
Die GRÜN/GELB/ROT-Entscheidung und die Token-Aktion sind deterministisch, sie leiten sich ausschließlich aus der Anzahl der FEHLER und WARNUNGEN ab. scripts/verdict.sh berechnet sie, sodass das Urteil maschinell testbar ist und nicht nur ein Agentenurteil darstellt; leite den Scan hinein:
bash skills/appstore-precheck/scripts/verdict.sh < scan-output.txt # gibt VERDICT / COUNTS / TOKEN aus
Es beendet mit 0 bei GRÜN / 1 bei ROT / 2 bei GELB und schreibt oder entfernt mit --apply entsprechend .precheck-pass (bei GELB wird das Token für eine explizite menschliche Bestätigung zurückgehalten). Phase 0–3 erzeugen weiterhin die Erzählung; verdict.sh fixiert lediglich die Schwellenwert-Arithmetik.
- Sammle die Ausgabe von Phase 0–3; zähle FEHLER + WARNUNGEN + BESTANDEN in die Tabelle des Ausgabe-Vertrags ein.
- Gib für jeden FEHLER eine
file:line-Referenz und einen Korrekturvorschlag. - Eröffne das Urteil mit einer Zeile in Pierres Stimme (variiere die Formulierung bei jedem Durchlauf; halte sie kurz und in seinem todernsten, französisch-kritischen Register), dann wechsle zur sachlichen Aufschlüsselung. Entscheide:
- GRÜN: Pierre, widerwillig: "Hmf. Ich finde nichts. Akzeptabel. Gib mir keinen Grund, dies zu bereuen." dann
date +%s > .precheck-pass && echo "token written"(60 Min. gültig). - GELB: Pierre: "Ein paar kleine Hässlichkeiten. Ich würde nicht ablehnen, aber ich habe sie bemerkt." Liste die WARNUNGEN sachlich auf, frage den Benutzer "trotzdem bestätigen und einreichen?", schreibe das Token nur bei Bestätigung.
- ROT: Pierre: "Nein. {n} Fehler. Apple hätte weniger gefunden. Suivant." Kein Token; dann die sachliche FEHLER-Liste mit
file:line+ Korrekturen, und stelle klar, dass die Einreichung GESPERRT ist. Die Pierre-Zeile ist nur Geschmackssache. Die FEHLER/WARNUNGEN-Liste,file:lineund Korrekturen darunter bleiben sachlich und präzise, niemals paraphrasiert.
- GRÜN: Pierre, widerwillig: "Hmf. Ich finde nichts. Akzeptabel. Gib mir keinen Grund, dies zu bereuen." dann
- Gib die abschließende manuelle Checkliste aus (siehe
references/methodology.md).
Regeln
- SCHREIBGESCHÜTZT: Ändere niemals Code oder Assets. Melde nur und schreibe das Token.
- Geschwindigkeit > Vollständigkeit:
scan.shverwendet paralleles grep/jq und ist in Sekunden fertig. - Keine Fehlerunterdrückung: Wenn ein Scan-Befehl fehlschlägt, wird diese Zeile als FEHLER gemeldet und der Scan fortgesetzt.
- Token-Speicherort:
.precheck-passim Repository-Stammverzeichnis; der Guard testet es mit einemmmin -60Filter. - Nur lokal: Für manuelle, lokale Ausführungen konzipiert; halte es aus CI heraus, um falsche Signale zu vermeiden.
Bekannte Grenzen
- Keine Laufzeit-Crash-Tests; das ist Sache von TestFlight und eines Crash Reporters. Nur statische Analyse.
- Mehrere Prüfungen sind beratende WARNUNGEN, die an erkannte Signale gekoppelt sind (Mit Apple anmelden 4.8, externer Kauf 3.1.1(a), Tracking/IDFA ohne ATT, Analyse vs. Datenschutzmanifest, Metadaten-URLs und Platzhalter-Kopien). Der Export-Compliance-Schlüssel wird bei Fehlen gemeldet, aber die eigentliche Verschlüsselungsantwort gehört weiterhin in App Store Connect.
- Der adversarial Reviewer ist eine heuristische Simulation, keine Garantie für Apples Entscheidung.
- Am genauesten für natives Swift / SwiftUI. Die Metadaten-, Datenschutzmanifest-, Screenshot- und Export-Compliance-Prüfungen gelten für jede iOS-App, aber die Code-Prüfungen lesen Swift-Quellcode, daher erkennen sie bei React Native (JavaScript) oder Flutter (Dart) weniger, anstatt falsch auszulösen.
- Nur iOS.
- Phase 0 erkennt nur strukturelle Änderungen (hinzugefügte/entfernte Abschnittsnummern); siehe die Referenz für Details.
Optional: Upload-Guard-Hook
hooks/fastlane-guard.sh blockiert fastlane deliver/pilot/release, sofern kein gültiges .precheck-pass-Token vorhanden ist. In Claude Code wird es automatisch über hooks/hooks.json eingebunden. In anderen Umgebungen bindest du es selbst als Pre-Command-Check ein oder behandelst das Token als manuelles Go/No-Go-Signal.