Communitygithub.com

berkayturk/appstore-precheck

Vérification pré-soumission iOS en lecture seule : analyse 20 vecteurs de rejet, enveloppe le fastlane precheck d'Apple, surveille les dérives des directives et effectue une revue contradictoire avant la soumission.

Qu'est-ce que appstore-precheck ?

App Store Precheck est une compétence autonome conçue pour minimiser les risques de rejet avant chaque soumission sur l’App Store iOS. Elle exécute en une seule commande une analyse statique exhaustive couvrant 20 vecteurs de rejet courants (manifestes de confidentialité, chaînes de finalité, mentions d’autres plateformes, limites des métadonnées, etc.), intègre le linter officiel `fastlane precheck` d’Apple, détecte les dérives structurelles des Règles de l’App Store via une vérification diff en direct, et simule une revue adverse via un sous-agent incarnant « Pierre », un critique français exigeant. La compétence est entièrement en lecture seule : elle ne modifie aucun fichier, ne génère qu’un jeton de passage `.precheck-pass` qui expire au bout de 60 minutes, et bloque les commandes `fastlane deliver/pilot/release` via un hook optionnel si le jeton est manquant ou obsolète. Elle supporte les projets Xcode natifs (Swift/SwiftUI), ainsi que React Native et Flutter pour les vérifications de métadonnées et de manifeste. Le niveau de risque est affiché sous trois états (VERT, JAUNE, ROUGE) avec des recommandations claires et des références précises aux fichiers et aux lignes.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add berkayturk/appstore-precheck

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

App Store Precheck

Une commande unique à exécuter avant toute soumission iOS sur l’App Store. Elle minimise le risque de rejet en analysant statiquement les vecteurs de rejet les plus courants, en exécutant le linter de métadonnées officiel d’Apple, en surveillant les dérives des directives, et en simulant une revue contradictoire.

Cette compétence est en lecture seule. Elle ne modifie jamais le code, les métadonnées ou les ressources. Elle se contente de rapporter les résultats et d’écrire un jeton de passage. La méthode détaillée (chaque vecteur de rejet, les mécanismes de vérification des dérives) se trouve dans references/methodology.md ; lisez-la lorsque vous avez besoin des spécificités derrière une vérification.

Quand l’exécuter

  • Avant d’archiver pour TestFlight.
  • Avant de cliquer sur « Soumettre pour révision » dans App Store Connect.
  • Avant toute commande fastlane deliver / release / pilot (le hook de garde optionnel se déclenche ici).
  • À chaque mise à jour mineure.

Exécutez-la délibérément. C’est une porte de contrôle déclenchée par l’humain, pas une étape automatique en arrière-plan.

Configuration (optionnelle)

L’analyseur détecte automatiquement une disposition standard fastlane + Xcode. La plupart des projets n’ont donc aucune configuration nécessaire. Pour forcer la détection, copiez config.example.json vers .appstore-precheck.json à la racine du dépôt. Clés : bundleId (obligatoire pour la Phase 2), iosSourceDir, metadataDir, screenshotsDir, xcstringsPath, paywallGlobs, locales, disclosureKeys.{subscription,trial}, optionalChecks.familyControls, reviewPrepNotes. Consultez config.example.json pour la liste détaillée.

Contrat de sortie

La compétence atteint l’un des trois états finaux :

ÉtatSignificationJeton .precheck-passComportement de la garde
VERTAucun FAIL, ≤2 WARNÉcrit (valide 60 min)Envoi autorisé
JAUNEAucun FAIL mais 3+ WARNNon écritLa garde bloque ; demande une confirmation explicite
ROUGEAu moins 1 FAILSuppriméLa garde bloque ; affiche la liste des FAIL

Lorsque vous présentez le verdict à l’utilisateur, commencez par une seule ligne dans le personnage de Pierre (le critique de l’App Store français, voir Phase 3), puis passez directement au détail chirurgical. La voix est une fine enveloppe. Les données en dessous – la liste FAIL/WARN, les références fichier:ligne et les correctifs – restent propres et fidèles à la machine. Ne réécrivez ni ne paraphrasez jamais la sortie de scan.sh, et limitez Pierre à une seule ligne.

Déroulement (5 phases : 0 à 4)

Phase 0 : Vérification des dérives des directives en direct

Comparez les numéros de section des Règles de l’App Store avec guidelines-baseline.json pour détecter toute section qu’Apple a ajoutée ou supprimée depuis la dernière réconciliation. Toujours non-bloquant (WARN au maximum). Une dérive est une lacune de notre couverture, jamais une faute de la build. La page est tronquée lors de sa récupération, donc elle nécessite une technique en deux passages ; les invites exactes et la procédure de réconciliation se trouvent dans references/methodology.md. La référence n’est jamais mise à jour automatiquement. La réconciliation est une étape humaine délibérée.

Phase 1 : Analyse statique

bash skills/appstore-precheck/scripts/scan.sh

Émet des lignes FAIL: / WARN: / PASS: couvrant 20 vecteurs de rejet : parité du manifeste de confidentialité (5.1.1(v)), chaînes de finalité (5.1.1), ATT (5.1.2), mentions d’autres plateformes (2.3.10), limites des métadonnées (2.3.1), parité localisée (2.3.7), captures d’écran (2.3.3), mentions des essais et renouvellements automatiques (3.1.2), liens Restore/Termes/Confidentialité (3.1.2), API privée (2.5.1), fonctionnalité minimale (4.0), parité « Connexion avec Apple » (4.8), liens d’achat externes (3.1.1(a)), justification optionnelle pour Screen Time / FamilyControls (5.1.5), SDK de suivi/IDFA sans invite ATT (5.1.2), clé de conformité à l’exportation (ITSAppUsesNonExemptEncryption), URLs de support et de confidentialité dans les métadonnées fastlane (2.3), types de données SDK analytics vs PrivacyInfo (5.1.1), et contenu de métadonnées factice (2.1). Les vérifications d’achats intégrés (8–10) sont automatiquement ignorées en l’absence de signaux d’achats intégrés. Le tableau complet des vérifications se trouve dans references/methodology.md.

L’analyseur est un script Bash portable, vous pouvez donc l’exécuter directement, en dehors de tout agent, pour une vérification rapide de CI ou pre-commit.

Phase 2 : fastlane precheck officiel d’Apple

Nécessite bundleId dans la configuration (ou passez app_identifier directement) et des identifiants API App Store Connect. Ne commitez jamais la clé. L’enveloppe fournie construit le fichier JSON de la clé API ASC à partir de votre environnement, exécute precheck et supprime la clé à la sortie (utilisez --dry-run pour prévisualiser la commande sans identifiants et sans réseau) :

ASC_KEY_ID=… ASC_ISSUER_ID=… ASC_P8_PATH=/chemin/AuthKey.p8 \
  bash skills/appstore-precheck/scripts/phase2-precheck.sh com.example.app

Ou exécutez-la manuellement : générez le fichier JSON de la clé depuis votre environnement, lancez precheck, puis supprimez la clé.

fastlane run precheck \
  app_identifier:"<VOTRE_BUNDLE_ID>" \
  api_key_path:"/tmp/asc-key.json" \
  include_in_app_purchases:false \
  default_rule_level:":error"
rm -f /tmp/asc-key.json   # supprimez le secret immédiatement

Le moteur de règles d'Apple vérifie les URLs, les mentions GitHub, les grossièretés, les marques déposées Apple, le langage de tarification et les mots-clés bêta. Result: true → PASS ; toute ligne de violation → FAIL. Les achats intégrés sont déjà couverts par la Phase 1, donc include_in_app_purchases:false évite la limitation d’achats intégrés liée à la clé API.

Phase 3 : Revue contradictoire (la plus importante)

Envoyez un sous-agent qui incarne Pierre, un examinateur sceptique de l’App Store avec le palais exigeant d’un critique français. Utilisez cette invite textuellement, en remplissant les spécificités de l’application :

Vous êtes Pierre, un examinateur vétéran de l’App Store qui critique comme un critique français. Vous avez vu dix mille rejets et aucun ne vous impressionne. Une nouvelle soumission vient d’atterrir sur votre bureau. Votre travail est de tenter de la rejeter de manière réaliste, sans aucun biais d’approbation. Choisissez 5 éléments aléatoires des directives répartis sur les sections (un 2.x, deux 3.x avec un poids sur le paywall, un 4.x, un 5.x) ; choisissez une combinaison différente à chaque exécution (incluez une ligne de graine pour que les relances varient). Pour chaque élément : (Pass A) grep les fichiers pertinents pour au moins 2 preuves concrètes : métadonnées pour 2.3.x ; la vue paywall + le catalogue de chaînes pour 3.1.x ; Core/navigation pour 4.x ; Info.plist + PrivacyInfo pour 5.1.x. (Pass B) demandez-vous « en tant qu’examinateur, sur quelle base signalerais-je cela ? » (Pass C) rédigez un brouillon de rejet dans la vraie voix d’Apple (Directive X.Y.Z – Catégorie / Nous avons remarqué… / Spécifiquement… / Prochaines étapes… / Ressources…). Attribuez à chaque élément un risque : REJET-CERTAIN / RISQUE-DE-REJET / AVERTISSEMENT / PASS. Terminez par une recommandation de soumission (SUSPENDRE / SOUMETTRE AVEC AVERTISSEMENTS / OK). Restez sous les 500 mots. Incluez au moins un PASS et au moins un élément comportant un risque, pour donner une distribution réaliste.

Phase 4 : Consolidation + jeton

La décision VERT/JAUNE/ROUGE et l’action sur le jeton sont déterministes, dérivées uniquement des nombres de FAIL/WARN. scripts/verdict.sh les calcule pour que le verdict soit testable par machine, et pas seulement un jugement d’agent ; pipez la sortie de l’analyse dedans :

bash skills/appstore-precheck/scripts/verdict.sh < scan-output.txt   # affiche VERDICT / COUNTS / TOKEN

Il se termine avec 0 VERT / 1 ROUGE / 2 JAUNE, et avec --apply écrit ou supprime .precheck-pass en conséquence (JAUNE conserve le jeton pour confirmation humaine explicite). Les phases 0 à 3 produisent toujours la narration ; verdict.sh fige le calcul des seuils.

  1. Rassemblez la sortie des phases 0 à 3 ; comptez les FAIL + WARN + PASS dans le tableau du contrat de sortie.
  2. Pour chaque FAIL, donnez une référence fichier:ligne et un correctif suggéré.
  3. Ouvrez le verdict avec une ligne dans la voix de Pierre (variez le libellé à chaque exécution ; restez concis et dans son registre de critique français impassible), puis passez au détail brut. Décidez :
    • VERT : Pierre, à contrecœur : « Hmf. Je ne trouve rien. Acceptable. Ne me fais pas regretter ça. » puis date +%s > .precheck-pass && echo "token written" (valide 60 min).
    • JAUNE : Pierre : « Quelques petites laideurs. Je ne rejette pas, mais j’ai remarqué. » Listez les WARN simplement, demandez à l’utilisateur « confirmer et soumettre quand même ? », écrivez le jeton seulement sur confirmation.
    • ROUGE : Pierre : « Non. {n} fautes. Apple en aurait trouvé moins. Suivant. » Pas de jeton ; puis la liste brute des FAIL avec fichier:ligne + correctifs, et dites clairement que la soumission est BLOQUÉE. La ligne de Pierre n’est qu’une touche. La liste FAIL/WARN, les fichier:ligne et les correctifs en dessous restent simples et chirurgicaux, jamais paraphrasés.
  4. Affichez la liste de contrôle manuelle finale (voir references/methodology.md).

Règles

  • LECTURE SEULE : ne modifiez jamais le code ou les ressources. Rapportez uniquement et écrivez le jeton.
  • Vitesse > exhaustivité : scan.sh utilise des grep/jq parallèles et se termine en quelques secondes.
  • Pas d’erreur ignorée : si une commande d’analyse échoue, cette ligne est rapportée comme FAIL et l’analyse continue.
  • Emplacement du jeton : .precheck-pass à la racine du dépôt ; la garde le teste avec un filtre mmin -60.
  • Local uniquement : conçu pour des exécutions manuelles locales ; gardez-le hors de l’intégration continue pour éviter de faux signaux.

Limites connues

  • Aucun test de crash à l’exécution ; ce rôle revient à TestFlight et à un rapporteur de crash. Analyse statique uniquement.
  • Plusieurs vérifications sont des WARN consultatifs déclenchés par des signaux détectés (Connexion avec Apple 4.8, achats externes 3.1.1(a), suivi/IDFA sans ATT, analytics vs manifeste de confidentialité, URLs de métadonnées et contenu factice). La clé de conformité à l’exportation est signalée lorsqu’elle est absente, mais la réponse réelle sur le chiffrement appartient toujours à App Store Connect.
  • La revue contradictoire est une simulation heuristique, pas une garantie de la décision d’Apple.
  • Plus précise pour du Swift / SwiftUI natif. Les vérifications de métadonnées, manifeste de confidentialité, captures d’écran et conformité à l’exportation s’appliquent à toute application iOS, mais les vérifications au niveau du code lisent le code source Swift ; donc sur React Native (JavaScript) ou Flutter (Dart), elles sous-détectent plutôt que de produire de faux positifs.
  • iOS uniquement.
  • La Phase 0 détecte uniquement les dérives structurelles (numéros de section ajoutés/supprimés) ; consultez la référence pour savoir pourquoi.

Optionnel : hook de garde d’envoi

hooks/fastlane-guard.sh bloque fastlane deliver/pilot/release sauf si un jeton .precheck-pass récent existe. Dans Claude Code, il s’active automatiquement via hooks/hooks.json. Dans d’autres environnements, branchez-le vous-même comme vérification pré-commande, ou traitez le jeton comme un signal manuel go/no-go.

Skills associés