MedLink 審査リジェクト記録(2026/05/15) — App Store 4連敗から5回目提出までの恒久対策
“Guideline 2.1(b) / 2.3.3 / 2.3.7 / 3.1.2(c) の地雷を全部踏み、原因と恒久対策を表で整理”
2026-05-15、MedLink が App Store 審査で 4 回連続リジェクトされた日。今日、5回目の提出を完了しました。本記事はリリース直前の本番コードで実際に発生した不具合のうち、Apple Review が指摘した4件のレジェクトの根本原因とその恒久対策を、SwiftUI / StoreKit2 / ASC API / Playwright /iris/v1/ までの全レイヤーで残します。

事実だけ書きます。何回リジェクトされたか、何が原因か、どこで判断ミスしたか、次回どう直すか。Apple Review Guideline の各条文と、実際にAppleからのメール本文を全部突き合わせた反省会です。

4コマ漫画で見る開発ストーリー
4連敗の全体像
まずは『誰が・いつ・何で蹴られたか』を時系列で整理:
medlink 1.0 リジェクト履歴(2026-05-08 → 05-14)
| # | 受信日 | Guideline | Apple の指摘 | 本質 |
|---|---|---|---|---|
| 1 | 2026-05-08 | 2.1(b) + 3.1.2(c) | IAP MISSING_METADATA / EULA リンクなし | 新規IAP提出の必須手順を知らなかった |
| 2 | 2026-05-10 | 2.1(b) | IAP が version に bundle されていない | 公開 ASC API で出来ると思い込んでいた |
| 3 | 2026-05-11 | 2.1(b) + 2.3.7 | 再び bundle 失敗 / スクリーンショットに価格テキスト | 順序ミス + ユーザー注意を再無視 |
| 4 | 2026-05-14 | 2.1(b) + 2.3.3 | アプリ内で IAP が見つからない / スクショがマーケ素材 | Reviewer 視点で実機検証していなかった |
全 4 回に共通する Guideline は 2.1(b) - Information Needed。「IAP が機能していない」と Apple が言い続けてきた。僕は ASC 側で IAP を整えるだけで満足していて、アプリバイナリで実際に Paywall に到達できるか実機検証を一度もしていませんでした。これが本質的な敗因です。
反省会 ― 原因の理由と次回の解決策
各回のリジェクトを、原因の根っこ・その理由(なぜ起きたか)・次回からの恒久対策、の3列で並べると以下のようになります。
リジェクト原因と恒久対策の対応表
| # | Guideline | 原因の本質 | 原因の理由(なぜ僕はそれを見落としたか) | 次回の解決策(恒久対策) |
|---|---|---|---|---|
| 1 | 2.1(b) | 新規 sub IAP は version と同時提出必須なのに、僕は単独で /v1/subscriptionSubmissions を叩いていた | ASC ドキュメントを浅く読んだだけで、初回 IAP の制約(FIRST_SUBSCRIPTION_MUST_BE_SUBMITTED_ON_VERSION エラー)を知らなかった | 新規アプリは必ず初回 IAP を version とバンドル。ASC web UI 専用の /iris/v1/subscriptionSubmissions を Playwright で叩く。submitWithNextAppStoreVersion: true を渡す。skill ios-iap-management.md に永続化済 |
| 2 | 3.1.2(c) | App Description に Apple Standard EULA リンク欠落 | サブスクリプションの EULA 必須要件を知らなかった。「プライバシーポリシーがあれば足りる」と勘違い | 全アプリの description 4言語末尾に https://www.apple.com/legal/internet-services/itunes/dev/stdeula/ を追記。pipeline/clean_descriptions_v4.mjs で自動チェック |
| 3 | 2.1(b) | /iris/v1/ POST のタイミングが、version submit より 後 だった | 「submitWithNextAppStoreVersion の next は、提出した version を指す」と思い込んだ。実際は POST 時点で PREPARE_FOR_SUBMISSION 状態の version を指す | 提出順序を絶対固定化: ①/iris/v1/subscriptionSubmissions POST → ②POST /v1/reviewSubmissions → ③POST reviewSubmissionItems → ④PATCH submitted=true。順序ミスで次世代に紐付くと連鎖崩壊 |
| 4 | 2.3.7 | スクリーンショットの slide 6 に「$4.99/mo or $29.99/yr (50% off)」と価格テキストを焼き込んだ | ユーザーから過去に「スクショに価格入れるな」と口頭注意を受けていたのに、captions-base.json の slot 6 に価格訴求を書き戻してしまった。注意の永続化を怠った | 永久ルール: feedback_appstore_screenshot_no_price.md を memory に新設。grep -rE "[¥$€£][0-9]|無料|Free|半額|セール" apps/*/ios/screenshots/ で commit 前 lint |
| 5 | 2.1(b) | ASC で IAP を整えても、Reviewer がアプリ起動後に Paywall に到達する手順が分からなかった | 「ASC 側を整えれば自動で見つけてもらえる」と思い込んでいた。Reviewer の視点(初見でアプリを開いて、どうやって課金画面に行くか)を一度も検証していなかった | Reviewer Notes に Paywall アクセス8ステップを明記。Onboarding 完了 → Settings タブ → 「Upgrade to Pro」ボタン。Product ID 2件 + Sandbox 案内も併記 |
| 6 | 2.3.3 | NFC SNS スタイル(gpt-image-2 全画マンガ風イラスト)を採用 → Apple に「Marketing materials, not actual app in use」と判定された | 前例(NFC SNS CARD MAKER)が通っていたから流用したが、Apple 2.3.3 の「actual UI が majority であること」要件を事前確認しなかった。前例依存の判断ミス | スクショは実 UI 撮影が主体。シミュレーターで撮ったキャプチャを iPhone Pro Max フレームに合成、上15%に控えめキャプションのみ。operation-guide/screenshots/ の実機キャプチャを活用 |
一番痛かった気付き ― IAP localization にも『3日間無料体験』が混入していた
4回目のリジェクト後、再提出前にエージェントクロスチェックで判明したのが、IAP 自体の subscriptionLocalizations にも価格・無料体験テキストが残っていた こと。
App Description は綺麗にしていたのに、Paywall に表示される IAP の説明文 Pro Monthly: 3-day free trial. Unlock all Pro features. がそのままだった。subscription.reviewNote には JPY 490 / USD 4.99 per month with 3-day free trial という審査員用メモも残っていた。
つまり、僕は『説明文 → スクショ → IAP localization → IAP reviewNote』の 4層構造 のうち、最初の2層しか掃除していなかった。Apple は4層全部を見るのに。
5回目提出に向けて変えたこと(2026-05-15 本日提出)
スクリーンショット 100枚 → v3 で完全リプレース:
- ❌ NFC SNS マンガ風全画イラスト → 廃止
- ✅ 既存
operation-guide/screenshots/の 実シミュレーターキャプチャ を活用(Today タブ・カレンダー・家族・緊急連絡先・設定 等) - ✅ 上 15% に控えめキャプションバンド(例「お薬の時間 / 忘れない」)
- ✅ 下 85% に実 UI(iPhone Pro Max 1290×2796 / 1242×2688 の2サイズ)
- ✅ 価格・通貨・無料・割引・%・期間数字、全部ゼロ
Reviewer Notes に8ステップの動線を明記:
1. Launch app 2. Tap 'Next' 4 times (onboarding) 3. Today tab opens 4. Tap Settings tab 5. Scroll to Subscription section 6. Tap orange 'Upgrade to Pro' button 7. Paywall sheet opens 8. Tap Pro Monthly or Yearly for StoreKit purchase
IAP の4層をすべて Apple-safe 化:
- App description 4言語(EULA URL + 自動更新24時間ルール + 明示価格)
- スクリーンショット 100枚(価格・無料系テキスト ゼロ)
- IAP subscriptionLocalizations 4言語×2 商品(機能訴求のみ)
- IAP subscription.reviewNote(「Auto-renewable subscription. Pricing displayed by App Store.」)
エージェントチームでクロスチェックした
ユーザーから『お前一人では信用できないので、エージェントチームで必ず確認し合うこと』と言われたので、再提出前に複数の Sub-Agent を並列で動かしました。
- security-engineer: Apple ガイドライン違反スキャン → GO 判定
- quality-engineer: 200 スクリーンショットを grep ベースで lint → 0 違反確認
- technical-writer: 20件の description を ASO 観点で読み直し → 重複・破損文の指摘で v4 cleaner 走らせて完全 CLEAN
1人で『大丈夫だろう』と思って通すのではなく、複数 agent の独立判断で『これなら通る』と合意したものだけ提出する。これが今後の標準フロー。
🎉 5回目で App Store 承認(2026-05-15 21:09 PDT)
Apple から承認メール着信:
Congratulations! Review of your submission has been completed. It is now eligible for distribution.
Submission ID: e4648baa-bfb1-47d6-bee2-004493a08277 → APPROVED
App URL: https://apps.apple.com/app/おくすりタイム/id6766263062
公開: 24 時間以内に App Store で配信開始
100本ノック史上、9本目にして初の App Store 承認。4 連敗からの 5 回目通過。リジェクト記事をそのまま書き換えず、ここに承認の事実を追記して、未来の自分や同じ罠を踏む開発者のためのリファレンスにします。
5回目で勝った要因(短縮版)
| # | 施策 | 効果 |
|---|---|---|
| 1 | NFC SNS マンガ風 → 実 UI 撮影スクショに完全転換 (上15%キャプション+下85%実画面) | Guideline 2.3.3 'actual app in use' クリア |
| 2 | Reviewer Notes に Paywall 動線 8 ステップ + Product ID 明記 | Guideline 2.1(b) 'cannot locate IAPs' 解消 |
| 3 | IAP 4層(description+screenshot+localization+reviewNote) を全部 Apple-safe 化 | Guideline 2.3.7 + 3.1.2(c) クリア |
| 4 | Agent 3名 (security/quality/technical-writer) でクロスチェックしてから提出 | 個人判断ミス排除 |
| 5 | /iris/v1/ POST → version submit の順序を絶対固定化 | bundle 漏れによる連鎖崩壊防止 |
残しているリスク(率直に)
5回目提出に残っているリスク
| 項目 | リスク | 確率 | もし指摘されたら |
|---|---|---|---|
| en スクショ内の UI が日本語のまま | Apple は『storefront 言語と UI 言語が一致すべき』と推奨 | 中 | シミュレーターを英語ロケールにして撮り直し → 再 upload |
| medlink/ja/07.png 内『治療の参考』表現 | 薬機法 / 医療免責のグレーゾーン | 低 | 「次の通院の参考に」等にキャプション差し替えて再生成 |
| Apple Reviewer 個人判断 | 全提出に共通する不可避リスク | 不可避 | リジェクト内容を読んで個別対応 |
学習を永続化した
今回の失敗を、未来の自分が同じ罠を踏まないよう memory に書き残しました:
feedback_appstore_4th_resubmission_learnings.md― IAP 4層構造クリーンの全手順feedback_appstore_screenshot_no_price.md― スクショに価格絶対NG(口頭注意の永続化)feedback_iap_link_via_iris_api.md― /iris/v1/ 必須 + 順序固定化feedback_appstore_iap_first_submission.md― 初回 IAP の必須3+1ステップ
全部 MEMORY.md にインデックス化済。次に新規アプリを作るとき、Claude Code が起動時にこれらを読んで自動で罠を回避する。
4コマ漫画 ― 「4連敗、それでも 5回目」

ステータス(2026-05-15 承認後時点)
- ✅ MedLink (medlink): 承認済 / 24 時間以内に App Store 公開
- ⏳ 関連アプリ(cat-litter-log / glp1-tracker / midnight-mom-ai / pet-spot-watcher)も同じ IAP 4 層構造クリーン手順を適用済。SPAM ルール対策で 2026-05-22 以降 に 1〜2 週間間隔で順次提出。
- 📚 学習を memory に永続化:
project_medlink_first_approval_success_2026_05_15.mdに勝ち筋を全部保存。次の新規アプリは Day1 でこの手順を適用 → 4 連敗を繰り返さない体制を構築。
Download on the
App Store
MedLink (おくすりタイム) — シニア向け服薬管理 — 5 回目審査中
関連プロダクト
MedLinkの詳細を見る