同意のライフサイクル:年齢確認の先に何が出荷されるか
2025年11月4日、AppleはApp Store Server Notificationsに、支払いではなく保護者の判断で発火する通知タイプを追加しました。RESCIND_CONSENTです。「親または保護者が、子どものアプリ利用に対する同意を撤回した」ことを示します。12
このサービスが公開する23種類の通知タイプのうち、ペイロードに取引情報ではなくappDataオブジェクトを積むのはこれだけです。そしてappDataには、「顧客がApp内課金を一切行わなくても」存在する署名済みapp transactionが入っています。319 つまり、何も販売したことのないアプリが、通知エンドポイントを運用する最初の理由を手にすることになります。
ソーシャルメディア申告の記事では、利用者の年齢レンジを読み取る話を扱いました。エンタイトルメント、年齢ゲート、返される境界値の意味です。そこは片付いたものとして、その一歩先から始めます。年齢確認が答えるのは「何歳か」です。ここで扱う3つのAPIが答えるのは、誰が承認するのか、いったん得た承認はアプリの変更を越えて生き延びるのか、そして保護者がそれを取り消したときに何が起きるのか、です。21012
要点
- 年齢確認の下流には3つのAPIがあり、Appleはそれらをひと組として出荷しています。PermissionKit配下のSignificant Change API、StoreKitの
AppStore.ageRatingCode、そしてサーバー通知RESCIND_CONSENTです。45 - Appleはこの4点セットをテキサス州だけでなく、ユタ州とルイジアナ州にも結びつけています。3州について示された日付はすべて過ぎており、義務の範囲は「法的に必要とされる特定の地域」とだけ書かれています。5815
- そもそも実行するかどうかを決める関門は、26.4で追加された
AgeRangeService.requiredRegulatoryFeaturesです。そしてその先のフローを完全に書くにはiOS 26.5が要ります。736 - Appleは「重要な変更」を定義することを拒み、4か所でそう述べたうえで弁護士に相談せよと促します。唯一公開されている具体例も、Apple自身ではなく法律に帰属させています。テキサス州法はアプリの年齢制限の変更を重要な変更とみなす、というのがそれです。48
- 年齢制限は、自分がビルドを出さなくても変わります。2026年6月18日、Appleはオーストラリアの15+区分を廃止し、ベトナムに4段階の新方式を導入しました。どちらも開発者に何かを提出させることなく適用されています。937
- 同意の撤回は誰も作らない分岐であり、Appleのドキュメントもほとんど作っていません。サーバー担当者が実際に読むページのライフサイクル表に、
RESCIND_CONSENTは1つも載っていないのです。2
付与、再付与、撤回。最初の2つについて、Appleはサンプルプロジェクトとサンドボックスのテスト表まで用意しています。3つ目に与えられているのは、列挙型の値ひとつと4つのフィールドだけ。そしてそれは結局のところ、私自身のコードがこの分岐に払っていた注意の量とほぼ同じでした。
Appleが4回公開したカレンダー
以下の日付はすべてApple自身の開発者ニュースに由来します。そして個々の項目よりも、その並び順のほうが重要です。
Appleがテキサス州のSB2420について告知したのは2025年10月8日で、「2026年1月1日から」という日付が添えられていました。そこで説明されたのは法律の条文ではなく、Apple自身の対応です。18歳未満のユーザーが新規に作成するApple Accountはファミリー共有グループに参加することになり、「App Storeでのダウンロード、アプリの購入、AppleのApp内課金システムを使った未成年者による取引のすべてについて、親または保護者が同意を与える必要がある」とされました。13 11月4日、Appleはツールの名前を挙げ、26.2のベータで出荷します。4 12月23日、計画は止まりました。「地方裁判所が最近発出した差止命令により、テキサス州法SB2420の執行が停止された(中略)Appleは先に発表した実装計画を一時停止する」14 そして2026年6月3日、再開します。「テキサス州法SB 2420に対する差止命令を解除する最近の裁判所の判断により(中略)これらの変更は2026年6月4日から有効になります」5
一つの州法をめぐって8か月の揺さぶりが続いたわけですが、APIのほうは一度も動いていません。26.2で出荷され、差止命令の期間中もサンドボックスでのテストは可能なまま、命令が解除された瞬間にはもう待機していました。14 12月の一時停止を「先送りしてよい」という許可と読んだ人は、5か月の助走を失ったことになります。
地図の残りは2026年2月24日に届き、その範囲はテキサス州を越えています。
| 法域 | Appleが示す適用日 | Appleが示す適用内容 |
|---|---|---|
| オーストラリア、ブラジル、シンガポール | 2026年2月24日 | 「合理的な手段で成人であると確認されない限り」、18+指定アプリのダウンロードをAppleがブロック15 |
| ユタ州 | 2026年5月6日 | 新規Apple Accountについて、要求に応じて年齢カテゴリを共有15 |
| テキサス州 | 2026年6月4日 | 新規Apple Accountが「同法の対象となる」。18歳未満の未成年者に代わってのダウンロード、App内課金、重要な変更への同意が必要となり、保護者は同意を撤回できる5 |
| ルイジアナ州 | 2026年7月1日 | 新規Apple Accountについて、要求に応じて年齢カテゴリを共有15 |
テキサス州が特異なのは基準のほうで、道具立てではありません。Appleはテキサス州について「18歳未満の未成年者に代わって」の同意と説明し、カテゴリを「13歳未満、13〜15歳、16〜17歳、18歳超」と公開しています。これはAPIが生成するものとぴったり一致します。「年齢ゲートは最大3つまで指定でき、そこから最大4つの年齢レンジが作られます」4529 ユタ州とルイジアナ州についてAppleは、要求に応じた年齢カテゴリの共有を挙げたうえで、4つのツールすべてが「ルイジアナ州とユタ州のコンプライアンス義務に対応するために拡張された」と述べ、その中にSignificant Change APIを名指ししています。15 道具立てはテキサス州専用ではありません。では義務のほうはどうかというと、Appleは答えません。義務の範囲を「法的に必要とされる特定の地域」とだけ書き、あとは弁護士に聞いてほしい、と投げます。8
上の表を法律の説明やコンプライアンス上の判断として読まないでください。記録しているのは、Appleが何を発表し、そこにどの日付を付けたか、それだけです。私はエンジニアであって弁護士ではありません。以下の話はすべてAPIの境界で止まります。
コンプライアンスの質問を弁護士に振るそのQ&Aには、リリース計画にとっては朗報も載っています。この件で審査が変わるのかという問いに、Appleは「いいえ、App Reviewのプロセスに変更はありません」と答えています。8 義務が発生するのは提出時ではなく、名指しされた法域における実行時です。
切り分けは明快です。自分のアプリがテキサス州、ユタ州、ルイジアナ州で同意を必要とするかどうかは、その州の資格を持つ弁護士に聞く話。どのSDKでビルドするかは、そうではありません。フレームワークに手が届くには「iOS 26.2およびiPadOS 26.2以降のSDKを使い、Xcode 26.2 (17C52) 以降でアプリをビルドする必要がある」とAppleは明記しており、iOS 18以前で動く既存アカウントは「影響を受けません」とも書いています。8
Appleは「重要」の意味を教えてくれない
この機能の中心には定義の空洞があり、Appleの4つの窓口はそれを埋めるどころか、こちらに投げ返してきます。シンボルのページは「何が重要なアップデートに当たるかは、適用される規制に基づいて開発者が判断します」12、2本のニュース記事はどちらも「アプリに重要な変更があったかどうかを判断する責任は開発者にあります」45、そしてQ&Aは、利用規約やプライバシーの変更は該当するのかと直接問われて「場合によります。何が重要なアプリのアップデートに当たるかは、適用される法律に基づいて開発者が判断します」と答えます。8
Appleが示す具体例はちょうど1つ、しかもその出どころはApple自身ではなく法律です。「テキサス州法は、アプリの年齢制限の変更を重要な変更とみなします。開発者はApp Store Connectの年齢制限の選択を常に最新に保つべきです」4
一方でAppleがきちんと定義しているのは、開発者が書く文字列のほうです。SignificantAppUpdateTopicのページには良い例と悪い例が並べて置かれています。シンボルのページとしては珍しいほど率直です。
// Specific
let topic = SignificantAppUpdateTopic(
description: "This update adds video calling and location sharing features."
)
// Vague
let topic = SignificantAppUpdateTopic(
description: "We've made improvements to the app."
)
このコードに添えられた指示は容赦がありません。「アプリの何が変わったのかを明確に説明する、簡潔で分かりやすい言葉を使ってください。親や保護者は、許可を与えるかどうかを判断するときにこの説明を読みます」12 つまり、リリースノートの決まり文句が、子どもがアプリを使い続けられるかどうかを決める親の目の前に置かれるわけです。多くのアプリにとって、これは今後書くことになる最も重大な変更履歴の文字列でしょう。
引き金の定義は曖昧にされていますが、答えに紐づく義務のほうは少しも曖昧ではありません。Appleは「必要な場合にアプリや機能へのアクセスを遮断する責任」を開発者に負わせたうえで、こう言い切ります。「親が同意を与えるまで、子どもは重要なアップデートにアクセスできないようにしなければなりません。その対象には、アプリとアカウントのデータ全体、あるいは特定の機能が含まれ得ます」8 ここでの「アプリとアカウントのデータ全体」という一言は、かなり働いています。影響範囲の決定を開発者に委ねたうえで、その上限としてアカウント全体を名指ししているのです。
状態機械と、Apple自身のサンプルが漏らしているところ
Appleは「Implementing age assurance and permissions」というサンプルプロジェクトを公開しており、これがフロー全体を端から端まで説明した唯一の資料です。6 これを状態機械として読むと、4つの分岐と、書き換えるべきコードが1か所浮かび上がります。
最初の分岐は安上がりです。AgeRangeService.requiredRegulatoryFeaturesはSet<AgeRangeService.RegulatoryFeature>を返し、要素はdeclaredAgeRangeRequired、significantAppChangeRequiresParentalConsent、significantAppChangeRequiresAdultNotificationの3つ。7 Appleのサンプルはまずこれを確認し、「どちらの機能も存在しない場合、アプリはフロー全体をスキップします」6 Appleはこのプロパティを、利用者の「地域とアカウント設定」を反映するものと説明しています。名指しされた法域の外にいる利用者は空の結果で返ってくる、という約束のように私には読めますが、Appleはその種の保証は一切していません。7
残りの分岐は、年齢と、その年齢がどう確立されたかで分かれます。
| 対象者 | 必要となる規制機能 | Appleのサンプルの挙動 |
|---|---|---|
| 未成年 | significantAppChangeRequiresParentalConsent |
保護者にPermissionQuestionを送信6 |
| 成人、確認済みの手段あり | significantAppChangeRequiresAdultNotification |
システムの確認シートを表示6 |
| 成人、確認済みの手段なし | どちらでも | 「設定でアカウントを確認するまで」アクセスを遮断6 |
| 共有を拒否 | どちらでも | ケースは解析するが、そのための分岐は示さない6 |
立ち止まるべきは3行目です。Apple Accountに支払い方法を一度も登録していない成人が、子どもを守るために作られたフローの中で、Appleのリファレンス実装によって遮断されます。代替の分岐も、それを回避する手段も、Appleは用意していません。
公開されている宣言に沿って組み立てると、分岐は次のようになります。成人と未成年の切り分けは、Appleのサンプルとサンドボックスのテスト表に従っています。18歳以上のアカウントはlowerBoundが18、上限なしで返り、ageRangeDeclarationはconfirmedまたはselfDeclaredになります。利用可能バージョンの下限に注意してください。.confirmedを読むにはiOS 26.5が必要で、これはフロー内の他のどれよりも1リリース後です。61136
import DeclaredAgeRange
import PermissionKit
import SwiftUI
@available(iOS 26.5, *)
struct SignificantChangeGate: View {
enum Phase {
case checking
case clear
case awaitingGuardian(PermissionQuestion<SignificantAppUpdateTopic>)
case blocked
}
let changeDescription: String
@Environment(\.requestAgeRange) private var requestAgeRange
@Environment(\.showSignificantUpdateAcknowledgment) private var acknowledge
@State private var phase: Phase = .checking
var body: some View {
switch phase {
case .checking:
ProgressView().task { await resolve() }
case .clear:
ChangedFeatureView()
case .awaitingGuardian(let question):
PermissionButton(question: question) { Text("Ask a parent to approve") }
case .blocked:
AccountVerificationPrompt()
}
}
private func resolve() async {
let features = (try? await AgeRangeService.shared.requiredRegulatoryFeatures) ?? []
guard !features.isEmpty else {
phase = .clear // nothing applies to this person
return
}
guard let response = try? await requestAgeRange(ageGates: 18),
case let .sharing(range) = response else {
phase = .blocked // declined or unavailable: Apple documents no branch
return
}
let isAdult = range.lowerBound == 18
let isConfirmed = range.ageRangeDeclaration == .confirmed
switch (isAdult, isConfirmed) {
case (true, true) where features.contains(.significantAppChangeRequiresAdultNotification):
try? await acknowledge(updateDescription: changeDescription)
phase = .clear
case (true, false):
phase = .blocked // adult with no confirmed method
case (true, true):
phase = .clear
case (false, _):
guard features.contains(.significantAppChangeRequiresParentalConsent) else {
phase = .clear
return
}
let topic = SignificantAppUpdateTopic(description: changeDescription)
phase = .awaitingGuardian(PermissionQuestion(significantAppUpdateTopic: topic))
}
}
}
質問を送るのは簡単なほうの半分です。答えを受け取るところでAppleのサンプルは漏れており、しかもコードは短いので、じっくり読めます。6
for await response in AskCenter.shared.responses(for: SignificantAppUpdateTopic.self) {
guard response.choice.answer == .approval else {
return
}
versionManager.handleAllChanges()
}
for awaitの中のreturnは、そのシーケンスを捨てます。一度拒否されただけで、アプリは次回起動までそのトピックの監視をやめてしまう。つまり、いったん「拒否」をタップした保護者が1分後に考え直して承認しても、その承認は誰も読んでいないストリームに流れ込むわけです。ここはcontinueと書き、拒否のほうを記録しておくべきところでしょう。このコードを意図ではなく欠陥として読むのは私の推測ですが、いずれにせよ修正コストはキーワード1つです。リスナーは、バックグラウンド起動は起きないものとして設計してください。それを約束していたのは、置き換えられた非推奨のシーケンスのほうだけなのですから。2021
保留は状態であり、そのタイムアウトは手元にない
設計の仕事が実際に宿るのはライフサイクルの真ん中で、そこを形づくるのは文書化された5つの挙動です。まずはAppleが半分しか答えていないものから。PermissionQuestion.expirationDateはOptional<Date>で、その日時を過ぎると「質問を受け取った人はもう回答できません」。ただし既定値は公開されていません。16
保護者が質問を目にする前に、子ども側が取り消すこともできます。「送信リクエストのフローの途中であればいつでも、子どもはリクエストを取り消すことができます(中略)この場合、システムはその質問に対する応答を呼び出し元のアプリに届けません」17 応答もエラーもコールバックもありません。自分でタイムアウトを設けない限り、保留状態は永遠に保留のままです。
成人に尋ねると例外が飛びます。サンドボックスの記事は、シンボルのページが空欄のままにしているケースを説明しています。「成人ユーザーに対してAskCenter.ask(_:)を呼ぶと、保護者による許可リクエストの要件を満たさないため、このエラーがスローされます」11 AskError.notAvailableは、この列挙型のうち自分のページに概要を持たない2つのケースの一方で、成人が引き当てるのはこちらです。18 例外を捕まえて振り分けるのではなく、尋ねる前に年齢で振り分けてください。
承認の状態は、アプリのコンテナではなくiCloudに置くべきものです。Appleのサンプルは、承認済みの変更をそれぞれNSUbiquitousKeyValueStoreに書き込み、「他のデバイスで同じフローを再び表示しないように」didChangeExternallyNotificationを監視しています。6 iPhoneで親が承認したなら、iPadで二度目のリクエストが出るべきではありません。そしてPermissionKitはその面倒を一切見てくれません。
サンプルの中で最も出来がよい部分は、多くのチームが取り違えたまま出荷しそうな問題を解いています。新規インストールの利用者が、経験してすらいない変更に同意する必要はありません。そこでAppleはAppTransaction.originalAppVersionを読み、「そのバージョン以前にアプリが導入した変更を、自動的に処理済みとして記録します」619 したがって同意の追跡は、変更ごと・人ごとに行うことになります。真偽値ひとつではなく、導入バージョンを添えた変更の識別子が必要なのです。
年齢制限は、ビルドなしで変わる
AppStore.ageRatingCodeはInt?を非同期で返すstatic varで、iOS、iPadOS、macOS、tvOS、visionOS、watchOSのいずれも26.2から利用できます。10 Appleが示す使い道は、解釈ではなく比較です。「このプロパティでアプリの年齢制限を取得し、最後に把握していた年齢制限と比較して、変更されたかどうかを確認してください」10 できるのは比較だけです。整数から年齢区分へのマッピングは、ドキュメントのどこにも公開されていないからです。自分が13+かどうかは問えず、前回と同じかどうかしか問えません。つまり実際の契約は、前の値を永続化し、初回実行の面倒は自分で見る、というものです。
アプリが自分の年齢制限を監視する理由は、区分がリリースなしに動くと気づいた瞬間に明らかになります。2026年5月21日、Appleは6月18日から「オーストラリアのApp Storeでは15+の年齢制限が利用できなくなります」と告知し、ベトナムには既存のアンケート回答から導かれる地域固有の4段階方式を導入しました。9 どちらも実際に着地しています。App Store Connectヘルプのオーストラリアの表には現在16+とR 18+だけが並び、15+の行はありません。ベトナムには専用の表ができました。37 どちらの変更も、提出もビルドも開発者の作業も要求していません。そしてAppleは、テキサス州法が年齢制限の変更を重要な変更とみなす、と書いています。4
自分から起こす変更と比べてみてください。「開発者がアプリの年齢制限を更新した場合、そのバージョンが公開された時点で、すべてのユーザーのデバイス上で年齢制限が更新されます」4 自分の変更は、自分で計測を仕込めるリリースに乗ってきます。Appleの変更は乗ってきません。このプロパティが埋めているのは、その隙間です。
テストの問題は、隙間よりたちが悪いものです。Developer ForumsのApple Staffによる返信が、はっきりこう述べています。「Xcodeおよびサンドボックス環境(TestFlightを含む)からビルドして実行している開発中は、値0が返るのが想定どおりです」22 ゼロはnilではありません。したがってApple自身が載せている例のコードはguard letを素通りし、0を有効な年齢制限として返します。あのスレッドを立てた開発者が実機で見たのは、まさにこれでした。1022
そのまま辿ってみましょう。0を基準値として保存すれば、App Storeでの初回起動時に本物のコードを読み、変更があったと判断し、中身のない同意を親に求めることになります。0を番兵とみなして基準値には決して書き込まない、という扱いはAppleの2つの記述からの私の推測ですが、これだけは入れずに出荷したくない防御コードです。
Appleの利用可能バージョンのメタデータには、どの説明ページにも書かれていない発見がもう一つ潜んでいます。ここまでの4つの機能について、プラットフォームの行は別々の場所に穴を空けているのです。
| 機能 | iOS / iPadOS | macOS | Mac Catalyst | visionOS | tvOS / watchOS |
|---|---|---|---|---|---|
AppStore.ageRatingCode10 |
26.2 | 26.2 | 行なし | 26.2 | 26.2 |
requiredRegulatoryFeatures7 |
26.4 | 26.4 | 26.4 | 行なし | 行なし |
SignificantAppUpdateTopic、PermissionButton1226 |
26.2 | 26.2 | 26.2 | 26.2 | 行なし |
showSignificantUpdateAcknowledgment27 |
26.4 | 行なし | 26.4 | 行なし | 行なし |
ここから非対称が2つ落ちてきます。ネイティブのmacOSアプリは、ある利用者にsignificantAppChangeRequiresAdultNotificationが適用されることを知ることはできても、それを満たすAPIを持ちません。showSignificantUpdateAcknowledgment(in:updateDescription:)はUIWindowSceneを受け取り、macOSの行を公開していません。SwiftUIのSignificantUpdateActionも同じ3プラットフォームで止まっています。27 隣接するrequestAgeRangeの呼び出しにはAppleがNSWindow版を用意しているので、この欠落は方針ではなく漏れだと読めます。これは私の推測です。28
2つ目に、検知は対処よりも遠くまで届きます。ageRatingCodeはtvOSとwatchOSの行を公開していますが、同意を求める側はどれも公開していません。10 これらのターゲットは、年齢制限の変更を観測できても、文書化された応答手段を持たないわけです。そしてReturnは両方を出荷しています。tvOS 1.0.1はApp Store ConnectでREADY_FOR_DISTRIBUTIONにあり、配信中のiOSアプリはwatchアプリを内包しています。30 どちらの読みも、Appleのメタデータが完全であることを前提にしていますが、その前提は同じメタデータ自身が掘り崩します。隣接するシンボルがすべてMac Catalystの行を持つ中で、ageRatingCodeだけがそれを公開していないのです。10
Appleが起動を止めたあと、サーバーは何のためにあるのか
撤回時の挙動を、Appleは一文で述べています。「親または保護者が、子どものアプリ利用に対する同意を撤回した場合、Appleはそのアプリの起動を阻止します。同意の撤回を処理するには、notificationTypeのRESCIND_CONSENTの値を使ってください」8
節の順序に注目してください。アクセスの遮断はすでにシステムが済ませています。つまりRESCIND_CONSENTは執行のための仕掛けではなく、そのつもりで作ると無駄になります。これは、自分のコードがもう動けなくなったデバイスの利用者について得られる唯一の信号です。このイベントをどう扱うべきかについてAppleは何も書いていないので、私が見つけた一番近い類例はアカウント削除リクエストでした。整合を取るべきサブスクリプションがあり、凍結すべき状態があり、そして戻ってくるかもしれない家族がいます。
ペイロードは異例なほど薄いものです。appDataが運ぶのはappAppleId、bundleId、environment、signedAppTransactionInfoの4フィールド。3 取引もサブスクリプションも更新情報もなく、こちら側のアカウント識別子もありません。人物への線は署名済みapp transactionを経由します。そのappTransactionIDをApp Storeは「アプリをダウンロードしたApple Accountごとに、そしてファミリー共有に対応するアプリではファミリーグループのメンバーごとに」生成します。19 つまり無料アプリでも、突き合わせに使える永続的なアカウント単位のキーは存在します。逆に、それを一度も保存してこなかったアプリは、誰のものか特定できない通知を受け取ることになります。
転送まわりに驚きはありません。App Store Connectで環境ごとにバージョン2のURLを設定し、TLS 1.2以降で受け、17.0.0.0/8を許可リストに入れ、成功は200から206、40xまたは50xを返せば再送を買えます。再送は1、12、24、48、72時間後の5回で、本番環境限定です。2324
RESCIND_CONSENTにはサブタイプもありません。公開されている19個のサブタイプ値はいずれも特定の通知タイプに紐づいており、RESCIND_CONSENTという文字列はそのページのどこにも現れません。25 さらに示唆的なのは、AppleのnotificationTypeページが「Handle use cases for In-App Purchase life-cycle events」の下に8つの表で40件のイベントを整理していながら、そのどれにもRESCIND_CONSENTが載っていないことです。この値はページ内の可能な値の一覧に存在するだけで、他のどこにも出てきません。2 Appleはこの通知を年齢確認まわりの資料で説明し、サーバー担当者が実際に読むリファレンスには最後まで結線しなかったわけです。
自分のプロジェクトがすでに間違えていること
他人のコードについて書く前に、自分のコードを検索しました。選定ルールは機械的で、そしてそのルールこそがバグでした。自分のCLAUDE.mdにあるActive Projectsの表のうち、背後にXcodeプロジェクトがある行すべて。これで7プロジェクト、Swiftファイル、entitlementsファイル、プロパティリスト、project.pbxprojを合わせて508ファイルになります。31 PermissionKit、AskCenter、SignificantAppUpdateTopic、FamilyControls、ManagedSettings、DeviceActivity、CKShare、sharedCloudDatabase、ageRatingCodeのいずれも一致ゼロ。7つのうち5つはApp Store Connectに記録があります。WaterとYawaraには記録がなく、出荷されたこともないので、この2つは誰かの手に届いたアプリではなくコードとして読んでください。31 未成年の利用者が最もいそうに見えたAce Citizenshipは、実は最もいそうにない一本でした。併設サイトはN-400の受給資格を「18歳以上」と明記しており、アプリはどこでも生年月日を尋ねていません。31
次に、同じパターンを~/Projects配下のすべてのリポジトリに対して走らせました。本来これを最初にやるべきでした。同じパターンが21ファイルに一致し、うち7つがコード、さらにその7つのうち6つは、表に行を持たなかった1つのiOSプロジェクトの中にありました。32
Randoriは柔術の練習記録アプリで、パターン一覧が捕まえるために存在する、まさにその同意の接点を抱えています。CKShareとsharedCloudDatabaseがConnectionStore.swift、RandoriApp.swift、CKPostTransport.swift、ProfileCardView.swift、CloudShareSheet.swift、SocialContracts.swiftにまたがって20件一致し、共有の受諾はアプリが起動中ならuserDidAcceptCloudKitShareWithを、コールドスタートならconnectionOptions.cloudKitShareMetadataを通ります。32 さらにRandoriは、他人の名前を背負うことについて独自の同意の仕組みも積んでいます。TagConsentStoreはフェイルクローズドで、タグ付けのポリシーをまだ公開していないクライアントを持つ選手には、そもそもタグを付けられません。32
つまり、本物の同意の接点を持つ唯一のプロジェクトは、自前の台帳を書き、Appleのものは何ひとつ採用していませんでした。そこには私がまだ作っていない宿題が3つあります。契約が眠らせている人対人の機能を有効にすることは、教科書どおりのSignificantAppUpdateTopicの事例です。ageRatingCodeの基準値は保存されておらず、未リリースの1.0はXcode、サンドボックス、TestFlightからしか動いたことがありません。まさにAppleが0を返すと言っている場所です。22 撤回通知には着地する先すらありません。Randoriは何も販売しておらず、自前のサーバーも持っていないからです。32
もっと面白い発見は、保護者による同意が、最初の7つのうち3つですでに別の名前で出荷されていたことです。
「承認と購入のリクエスト(Ask to Buy)」は、形も仕組みも同じで、Appleの説明もほとんど同じ言葉です。「子どもが対象となる購入やダウンロードを行おうとすると、システムはその購入リクエストを親または保護者に送ります」34 これはProduct.PurchaseResult.pendingとして表に出てきます。承認は呼び出し箇所ではなくTransaction.updatesから届きます。このシーケンスが「Ask to Buyの取引など、アプリの外で発生する取引」を運ぶからです。35 拒否のときは何も届きません。「Ask to Buyを拒否したため、アプリは取引を受け取りません」34
7つのうち3つは何かを販売しており、保留状態の扱いはそれぞれ違いました。33
| アプリ | 商品 | .pendingの扱い |
|---|---|---|
| ResumeGeni | 月額サブスクリプション | 名前の付いた.pendingの結果と、文書化された整合手順 |
| Reps | サブスクリプション、2段階 | case .userCancelled, .pending:として1つの分岐に潰されている |
| Ace Citizenship | 非消耗型 | 独立したcase .pending:がfalseを返す。キャンセルと同一 |
3つのうち2つは、保護者が検討している最中であることを、利用者が拒否したこととして報告します。しかも画面に現れる結果は、ラベルの取り違えよりたちが悪いものです。Repsはpurchaseがtrueを返したときにだけペイウォールを閉じ、Aceは自前の呼び出しが成功を返したときにだけペイウォールの先へ進みます。.pendingではどちらの呼び出しも行動につながる値を返さないので、ペイウォールはエラーもトーストもスピナーもないまま開き続けます。要するに、押しても何も起きないタップです。33 親は数分後に承認し、その取引は、リクエストが起きたことを一度も認めなかったインターフェースの裏でリスナーに着地します。
潰された分岐は、PermissionKitがもっと大きな賭け金で誘発するのとまったく同じ失敗であり、Appleがこのパターンに2つ目のAPIを与える前に、私はそれを2回出荷していました。保留は珍しい分岐ではありません。保留とは、同意のフローをアプリの内側から見たときの姿そのものです。既定の設計としては、返す値ではなく、描画する状態として扱うのが正解です。
1本のアプリはすでにサーバー側の下流にいて、そのおかげで欠けている分岐が具体的になります。ResumeGeniのバージョン2エンドポイントは、2026年6月26日以降で少なくとも56件の通知を記録しています。うち55件がサンドボックス、1件が本番で、だからこそ片方ではなく両方の環境URLが登録済みだと分かります。ハンドラは13の通知タイプを名前で挙げ、そのうち8つを実際に振り分けています。残り5つはコメントの中にしか出てきません。RESCIND_CONSENTはそのどちらにも入っておらず、リポジトリの他のどこにもありません。33
よくある質問
保護者に同意を求めるAPIと、成人に確認を求めるAPIはどちらですか
別々のフレームワークで、しかも取り違えやすい分かれ方をしています。保護者の同意はPermissionKitを通ります。SignificantAppUpdateTopicをPermissionQuestion(significantAppUpdateTopic:)で包み、PermissionButtonで送信し、AskCenter.shared.responses(for:)で答えを受け取る流れです。12162126 成人の確認はDeclared Age Rangeのほうで、showSignificantUpdateAcknowledgment(in:updateDescription:)を使います。27 まずrequiredRegulatoryFeaturesを確認してください。PermissionKitで成人に尋ねるとAskError.notAvailableがスローされます。711
実際のファミリーアカウントなしで同意の撤回をテストするには
デベロッパモードを有効にし、設定、デベロッパ、サンドボックスApple Accountと開いてサインインし、アカウントを選んで「管理」をタップ、「アプリの同意を取り消す」を選びます。バンドル識別子を入力して「同意を取り消す」をタップすると、「Notification Triggered」と表示されます。11 バージョン2のURLを設定してあれば、サーバーはRESCIND_CONSENTを受け取ります。appDataオブジェクトに入ったbundleIdとenvironmentのフィールドで、通知が正しいアプリのものだと確認できます。311 サンドボックスは各通知を再送なしで1回だけ送るので、テストの途中で50xを返したエンドポイントに二度目はありません。24
なぜアプリが実行時に自分の年齢制限を監視するのですか
Appleが、こちらの提出なしにストアフロント上の年齢制限を変えてしまうからです。しかもAppleは、テキサス州法が年齢制限の変更を重要な変更とみなすと書き、保護者の同意を求めるためにSignificant Change APIを使うよう案内しています。4 その実例が2026年6月18日です。オーストラリアは15+区分を失い、ベトナムは4段階の方式を得ました。どちらも既存のアンケート回答から、既存のアプリに適用されています。937 このプロパティが返す整数から年齢区分へのマッピングをAppleは公開していないので、保存しておいた値との比較だけが、唯一使える操作です。10
RESCIND_CONSENTは、代わりに利用者を遮断してくれますか
遮断はすでにシステムが済ませています。多くの実装が取り違えるのがここです。保護者が同意を撤回すると「Appleはそのアプリの起動を阻止します」とAppleは述べ、そのうえで、執行のためではなくイベントを処理するために通知を使えと案内しています。8 つまり残る仕事はサーバー側の形をしています。アカウントの状態を凍結し、サブスクリプションの整合を取り、自分のアプリを開けなくなったデバイスへのプッシュを止めること。失敗した認可チェックとしてではなく、アカウント削除として扱ってください。
要点のまとめ
iOS開発者へ:
- 今あるProduct.PurchaseResultのswitchを、今日のうちに点検してください。Ask to Buyはすでに出荷されている保護者の同意そのもので、.pendingはその現れ方であり、このケースを.userCancelledに潰すことは、PermissionKitがより大きな賭け金で誘発する欠陥です。3435
- 確認済みの成人と自己申告の成人を区別するフローなら、26.4ではなくiOS 26.5を見込んでください。36
- Appleのサンプルのリスナーにあるreturnは、コピーする前に直すこと。そして保存するageRatingCodeの基準値に0を決して到達させないこと。622
複数のAppleプラットフォームに出荷するチームへ:
- 作業を計画する前に、利用可能バージョンの行を確認してください。ネイティブのmacOSアプリは成人向けの確認が必要だと検知できても、それを提示するAPIを持ちません。tvOSとwatchOSはageRatingCodeを読めても、その裏に同意を得るAPIがありません。71027
- 承認の記録は変更ごとのキーでNSUbiquitousKeyValueStoreに保存し、AppTransaction.originalAppVersionを使って、新規インストールをそれ以前の変更から免除してください。619
バックエンドとリリースの担当者へ:
- 必要になる前に、アカウントごとのappTransactionIDを記録しておいてください。そのうえで、無料アプリであってもバージョン2のエンドポイントを立てること。後から作ったエンドポイントは、誰のものとも紐づけられない撤回イベントを受け取ることになります。319
- 重要な変更の説明文は、プロダクトの文章を預かっている人の目を必ず通してください。保護者が、あなたのアプリを子どもの手元に残すかどうかを決めながら読む、唯一の文字列です。12
このサイクルにある4つの強制ポイントのうち3つは、自分で制御できる何かをきっかけに発火します。SDKに対する起動画面のキー、ツールチェーンに対する@Stateマクロ、提出に対するソーシャルメディア申告です。保護者の同意だけは、裁判所の訴訟記録と、ストアフロントの年齢制限の表をきっかけに発火します。シリーズ全体のハブはAppleエコシステムシリーズです。
参考文献
-
Apple、App Store Server Notifications changelog。2025年11月4日の見出しの下、New featuresに「新しいペイロードオブジェクト
appDataを含めるようresponseBodyV2DecodedPayloadを更新」および「notificationTypeに通知タイプRESCIND_CONSENTを追加」とあります。変更履歴の次の2件は2025年12月10日と2026年4月27日で、いずれも同意には触れていません。HTMLのページはJavaScript経由で描画されるため、2026年7月26日にAppleのドキュメントJSONから読み取りました。 ↩ -
Apple、notificationType、App Store Server Notifications。
RESCIND_CONSENTの定義(「親または保護者が、子どものアプリ利用に対する同意を撤回したことを示す通知タイプ」)と、ここで用いた件数の出典です。このページは23個の可能な値を公開しています(CONSUMPTION_REQUEST, DID_CHANGE_RENEWAL_PREF, DID_CHANGE_RENEWAL_STATUS, DID_FAIL_TO_RENEW, DID_RENEW, EXPIRED, EXTERNAL_PURCHASE_TOKEN, GRACE_PERIOD_EXPIRED, METADATA_UPDATE, MIGRATION, OFFER_REDEEMED, ONE_TIME_CHARGE, PRICE_CHANGE, PRICE_INCREASE, REFUND, REFUND_DECLINED, REFUND_REVERSED, RENEWAL_EXTENDED, RENEWAL_EXTENSION, RESCIND_CONSENT, REVOKE, SUBSCRIBED, TEST)。RESCIND_CONSENTという文字列はページのペイロード中にちょうど1回、可能な値の一覧の中にだけ現れます。「Handle use cases for In-App Purchase life-cycle events」の下にある8つの表は、合計で40件のイベント行を持ちますが(各見出しを含めて4、6、7、7、8、6、6、4行)、そのいずれにもこの値は登場しません。なおREVOKEはファミリー共有によるエンタイトルメントの喪失であって、同意の撤回ではありません。「顧客がファミリー共有を通じて権利を得ていたApp内課金が、共有を通じて利用できなくなった」ことを指します。2026年7月26日にAppleのドキュメントJSONから読み取りました。 ↩↩↩↩ -
Apple、appData、App Store Server Notifications、バージョン2.19で導入。「
appDataオブジェクトはresponseBodyV2DecodedPayloadの一部です。このオブジェクトは、notificationTypeがRESCIND_CONSENTのときにペイロードに含まれます」という記述と、4つのプロパティ、すなわちappAppleId(「ユーザーがApp Storeからダウンロードするアプリで利用できます。サンドボックス環境には含まれません」)、bundleId、environment、signedAppTransactionInfo(JWSAppTransaction)の出典です。responseBodyV2DecodedPayloadのページも独立して排他性を述べており、appDataを「notificationTypeがRESCIND_CONSENTのときに現れる」フィールドと説明したうえで、「data、appData、summary、externalPurchaseTokenの各フィールドは相互排他です。ペイロードにはこのうち1つだけが含まれます」と付け加えています。この2ページが、RESCIND_CONSENTをペイロードにappDataを積む唯一の通知タイプと呼ぶ根拠です。なおnotificationTypeのページにはappDataという文字列がどこにも現れません。 ↩↩↩↩ -
Apple、Next steps for apps distributed in Texas、Apple Developer News、2025年11月4日。テキサス州の年齢カテゴリ(「13歳未満、13〜15歳、16〜17歳、18歳超」)、Appleが用いるフレームワーク名(「PermissionKitフレームワーク配下のSignificant Change API」)、開発者責任の一文(「アプリに重要な変更があったかどうかを判断する責任は開発者にあります」)、年齢制限の例(「テキサス州法は、アプリの年齢制限の変更を重要な変更とみなします。開発者はApp Store Connectの年齢制限の選択を常に最新に保つべきです。開発者がアプリの年齢制限を更新した場合、そのバージョンが公開された時点で、すべてのユーザーのデバイス上で年齢制限が更新されます」)、StoreKitの位置づけ(「開発者はStoreKitの新しいプロパティタイプを使って、ユーザーのデバイス上でアプリの年齢制限が変更されたかどうかを自動的に確認し、Significant Change APIを使って保護者の同意を求めることができます」)、撤回時の挙動(「テキサス州の親または保護者は、任意のアプリについて同意を撤回でき、それにより子どもや10代のデバイス上でそのアプリの起動がブロックされます」)、そして4項目の「Next steps」実装リストの出典です。ベータでの提供開始をiOS 26.2およびiPadOS 26.2と特定する根拠でもあります。2026年7月26日に取得。 ↩↩↩↩↩↩↩↩↩
-
Apple、Update for Apps Distributed in Texas、Apple Developer News、2026年6月3日。差止命令の解除(「テキサス州法SB 2420に対する差止命令を解除する最近の裁判所の判断により、テキサス州の新規Apple Accountは同法の対象となります」)、適用範囲(「ダウンロード、AppleのApp内課金、アプリに関連する重要な変更について、18歳未満の未成年者に代わって行う年齢確認と親または保護者の同意。また親または保護者は、以前に子どものために承認したアプリについて、同意を撤回できるようになります」)、発効日(「これらの変更は2026年6月4日から有効になります」)、繰り返される開発者責任の注意書き、そして同じ4項目の実装リストの出典です。2026年7月26日に取得。 ↩↩↩↩↩↩
-
Apple、Implementing age assurance and permissions、Declared Age Rangeのサンプルコード。対応バージョンはiOS 26.5、iPadOS 26.5、Mac Catalyst 26.5、Xcode 27.0 beta。記事本文は、実行前に「iOS 26.4以降のデバイス」でiCloudにサインインするよう指示しています。空集合のときの挙動(「どちらの機能も存在しない場合、アプリはフロー全体をスキップします」)、18という年齢ゲート、解析される4つのカテゴリ(
.minor、「確認済みの支払い方法を持つ成人」と説明される.verifiedAdult、「アカウントの確認を行っていない成人」である.unverifiedAdult、.declinedSharing)、未確認の成人に対する結果(「アプリはフェーズを.blockedに設定し、その人が設定でアカウントを確認するまでアクセスを遮断します」)、SignificantAppUpdateTopicとPermissionQuestionを組み立てる未成年の経路、PermissionButtonによる送信、本文にそのまま引用したAskCenter.shared.responses(for:)のリスナーのコード、拒否時の挙動(「親がリクエストを拒否した場合、アプリは未成年者による利用を遮断します」)、didChangeExternallyNotificationを用いたNSUbiquitousKeyValueStoreでの承認記録(「他のデバイスで同じフローを再び表示しないように」)、そしてoriginalAppVersionによる免除(「重要な変更がすでに存在する状態でアプリをインストールした人は、それを承認する必要はありません」)の出典です。このプロジェクトはDeclared Age Rangeのケイパビリティと、iCloudのkey-valueストレージも必要とします。2026年7月26日にAppleのドキュメントJSONから読み取りました。 ↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple、AgeRangeService.requiredRegulatoryFeaturesおよびAgeRangeService.RegulatoryFeature、Declared Age Range。いずれもiOS 26.4、iPadOS 26.4、Mac Catalyst 26.4、macOS 26.4から利用可能で、visionOS、tvOS、watchOSの行はありません。宣言は
var requiredRegulatoryFeatures: Set<AgeRangeService.RegulatoryFeature> { get async throws }で、「規制機能のサービスが利用できない場合」にnotAvailableをスローします。列挙型が公開するのは厳密に3ケース、declaredAgeRangeRequired(「その人がアプリに年齢レンジを共有することを求められていることを示します」)、significantAppChangeRequiresAdultNotification(「成人ユーザーがアプリの重要な変更を確認する必要があることを示します」)、significantAppChangeRequiresParentalConsent(「親または保護者が、アプリの重要な変更を確認し同意する必要があることを示します」)です。 ↩↩↩↩↩↩ -
Apple、Age assurance frameworks Q&A、Apple Developer Support。SDKの下限(「iOS 26.2およびiPadOS 26.2以降のSDKを使い、Xcode 26.2 (17C52) 以降でアプリをビルドする必要があります」)、既存アカウントの除外(「iOS 18およびiPadOS 18以前で動作する既存のApple Account(中略)は影響を受けません」。省略部分は「子どもと10代向けの成人アカウントおよび子どもアカウントを含む」と特定しています)、責任についての回答(「はい、開発者は自身の年齢制限について責任を負います」および「コンプライアンス義務に関する質問は、法律顧問にご相談ください」)、本文で二度引用した地域の限定(「法的に必要とされる特定の地域において、AppleはApple Accountの保有者の年齢を確認する年齢確認手段を用い、Declared Age Range APIを通じて年齢カテゴリを共有します。それらの地域では、アプリを使う人々の年齢を確認する必要があります」。後段では「法的に必要とされる地域では、Declared Age Range APIでアプリを使う人々の年齢を確認する必要があります」と言い換えられています)、アクセスに関する義務(「重要なアプリのアップデートについては、必要な場合にアプリや機能へのアクセスを遮断し、親または保護者からの応答を処理する責任があります。親が同意を与えるまで、子どもは重要なアップデートにアクセスできないようにしなければならず、その対象にはアプリとアカウントのデータ全体、あるいは特定の機能が含まれ得ます」)、撤回時の挙動(「親または保護者が、子どものアプリ利用に対する同意を撤回した場合、Appleはそのアプリの起動を阻止します。同意の撤回を処理するには、
notificationTypeのRESCIND_CONSENTの値を使ってください」)、App Reviewについての回答(「いいえ、App Reviewのプロセスに変更はありません」)、利用規約とプライバシーについての回答(「場合によります。何が重要なアプリのアップデートに当たるかは、適用される法律に基づいて開発者が判断します」)の出典です。2026年7月26日に閲覧。 ↩↩↩↩↩↩↩↩↩ -
Apple、Upcoming changes to age ratings in Australia and Vietnam、Apple Developer News、2026年5月21日。「2026年6月18日から、オーストラリアとベトナムのApp Storeにおける年齢制限が更新されます」、オーストラリアの変更(「オーストラリアのApp Storeでは15+の年齢制限が利用できなくなります。現在15+で、以下のコンテンツ記述子を持つアプリは16+に更新されます」)とその3つの記述子(無制限のWebアクセス、頻繁な医療または治療情報、ルートボックス)、そしてベトナムの変更(「ベトナム政令147号第38条に合わせるため、ベトナムのApp Storeで提供されるアプリには地域固有の年齢制限が必要になります。App Store Connectの年齢制限アンケートの回答に基づき、アプリは4つの区分(00+(全年齢)、12+、16+、18+)のいずれかを受け取ります」)の出典です。どちらの変更も開発者にビルドの提出を求めていません。2026年7月26日に取得。 ↩↩↩
-
Apple、AppStore.ageRatingCode、StoreKit。宣言は
static var ageRatingCode: Int? { get async }で、iOS 26.2、iPadOS 26.2、macOS 26.2、tvOS 26.2、visionOS 26.2、watchOS 26.2から利用可能。Mac Catalystの行はありません。戻り値は「現在の年齢制限コードを表す整数。年齢制限が利用できない場合はnil」。比較という位置づけ(「このプロパティでアプリの年齢制限を取得し、最後に把握していた年齢制限と比較して、変更されたかどうかを確認してください」)と、PermissionKitへの導線(「アプリの年齢制限が変更された場合、Significant Change APIを使って親または保護者に知らせることを検討してください」)の出典です。後者の文では「Significant Change API」がリンクテキストで、リンク先はAppleのSignificantAppUpdateTopicのページです。ページ上のAppleの例は、このプロパティをguard letで包み、値が利用できない場合に出力するというものです。2026年7月26日に、これらの整数から年齢区分(4+、9+、13+、16+、18+)へのマッピングをAppleのドキュメントで検索しましたが、このページにもAppStore型のページにも、App Store Connectヘルプの年齢制限のリファレンスにも見つかりませんでした。 ↩↩↩↩↩↩↩↩↩ -
Apple、Testing age assurance in sandbox、StoreKit。デバイス上の操作手順(設定、デベロッパ、Sandbox Apple Account、管理、そして「Age Assurance」または「Revoke App Consent」)、18歳以上の行が下限18・上限なしを返し年齢申告が
selfDeclaredまたはconfirmedとなる6行のテスト表、成人に尋ねたときの挙動(「18+のテストケースでは、PermissionKitはPermissionChoiceを返さずAskError.notAvailableをスローします。成人ユーザーに対してAskCenter.ask(_:)を呼ぶと、保護者による許可リクエストの要件を満たさないため、このエラーがスローされます」)、「Notification Triggered」という確認表示と「まもなく開発者のサーバーに通知が送信されます」で終わる撤回の手順、そしてペイロードについての注記(「サーバーはRESCIND_CONSENTのnotificationTypeを受け取ります。通知のペイロードには、bundleIdとenvironmentのフィールドを含むアプリのメタデータを持つappDataオブジェクトが含まれます」)の出典です。表の未成年3行は、13歳未満で承認、13〜15歳で承認、16〜17歳で拒否となっており、いずれも年齢申告はguardianDeclaredです。 ↩↩↩↩↩ -
Apple、SignificantAppUpdateTopic、PermissionKit。iOS 26.2、iPadOS 26.2、Mac Catalyst 26.2、macOS 26.2、visionOS 26.2から利用可能。
struct SignificantAppUpdateTopicと宣言され、QuestionTopicに準拠し、init(description: String)を持ちます。定義の先送り(「何が重要なアップデートに当たるかは、適用される規制に基づいて開発者が判断します」)、説明文についての指示(「アプリの何が変わったのかを明確に説明する、簡潔で分かりやすい言葉を使ってください。親や保護者は、許可を与えるかどうかを判断するときにこの説明を読みます」)、そして本文にそのまま再掲したSpecific/Vagueのコード内コメント2件の出典です。 ↩↩↩↩↩↩ -
Apple、New requirements for apps available in Texas、Apple Developer News、2025年10月8日。当初の告知(「2026年1月1日から、テキサス州の新しい州法(中略)がアプリマーケットプレイスと開発者に年齢確認の要件を導入します」。省略部分はSB2420を名指ししています)、ファミリー共有の要件(「18歳未満のユーザー向けの新規Apple Accountはすべてファミリー共有グループへの参加が必要となり、App Storeでのダウンロード、アプリの購入、AppleのApp内課金システムを使った未成年者による取引のすべてについて、親または保護者が同意を与える必要があります」)、そしてユタ州とルイジアナ州の予告(「同様の要件が来年後半に発効します」)の出典です。2026年7月26日に取得。 ↩
-
Apple、Update on age requirements for apps distributed in Texas、Apple Developer News、2025年12月23日。差止命令(「地方裁判所が最近発出した差止命令により、テキサス州法SB2420の執行が停止された(中略)この判断を受け、Appleは先に発表した実装計画を一時停止し、進行中の法的手続きを注視します」)、4つのツールがサンドボックスで引き続き利用可能であること、そしてそれらがユタ州とルイジアナ州へ拡張されることの出典です。2026年7月26日に取得。 ↩↩
-
Apple、Age requirements for apps distributed in Brazil, Australia, Singapore, Utah, and Louisiana、Apple Developer News、2026年2月24日。18+のダウンロード制限(「2026年2月24日から、Appleはオーストラリア、ブラジル、シンガポールのユーザーについて、合理的な手段で成人であると確認されない限り、18+指定のアプリのダウンロードをブロックします。App Storeがこの確認を自動的に行います。ただし開発者には、ユーザーが成人であることを独自に確認する別個の義務がある場合があります」)、ユタ州とルイジアナ州の日付(「2026年5月6日以降のユタ州、および2026年7月1日以降のルイジアナ州の新規Apple Accountを持つユーザーについては、Declared Age Range APIを通じて要求されたときに、年齢カテゴリが開発者のアプリに共有されます」)、本文で引用した拡張の一文とそれに続く4つのリンク(「先に発表したツールは、ルイジアナ州とユタ州のコンプライアンス義務に対応するために拡張されました。内容は次のとおりです」:Declared Age Range API、PermissionKit配下のSignificant Change API、StoreKitの新しい年齢制限プロパティタイプ、App Store Server Notifications)、ブラジルにおけるルートボックスの帰結、そしてSignificant Update Actionが公に初めて名指しされた箇所(「開発者はDeclared Age Range APIを使い、現在ベータのSignificant Update Actionを通じて、これらの州の成人に重要なアップデートの通知を提示できます」)の出典です。2026年7月26日に取得。 ↩↩↩↩↩
-
Apple、PermissionQuestionおよびexpirationDate、PermissionKit。
final class PermissionQuestion<Topic> where Topic : QuestionTopicはiOS 26.0から利用可能で、4つのイニシャライザinit(handle:)、init(handles:)、init(communicationTopic:)、init(significantAppUpdateTopic:)を持ちます。最後のものはiOS 26.2で導入され、「重要なアップデートの後にアプリの利用を続ける許可を、親または保護者に求める許可質問を作成します」と説明されています。expirationDateはfinal var expirationDate: Date?と宣言され、「その日時を過ぎると、質問を受け取った人はもう回答できません」という解説が付いています。Appleはこのプロパティの既定値も、重要なアップデートのトピックにおける設定の指針も公開していません。 ↩↩ -
Apple、Creating a communication experience、PermissionKit。ここで引用した取り消し時の挙動の出典です。「送信リクエストのフローの途中であればいつでも、子どもはリクエストを取り消し、親または保護者に質問を送らないことを選べます。この場合、システムはその質問に対する応答を呼び出し元のアプリに届けません」。またこのフレームワークのiMessage制約の出典でもあります。PermissionKitのトップページはこれをImportantの注記として述べています。「
PermissionKitフレームワークを用いるコミュニケーション体験は、iMessageでのみ利用できます」。なお、この記事が説明しているのはCommunicationTopicのフローだけです。重要なアップデートのフローについて同等の記事をAppleは公開しておらず、記事内のコードサンプルが呼び出しているCommunicationLimits.current.permissionResponsesというシンボルは、2026年7月26日時点でAppleのドキュメント上404を返します。 ↩ -
Apple、AskError、PermissionKit。
enum AskErrorはLocalizedErrorに準拠し、6つのケースを持ちます。4つは概要を持ちiOS 26.1で登場しました。unknown、communicationLimitsNotEnabled(「許可リクエストを送るためのコミュニケーション制限が有効になっていないことを示します」)、contactSyncNotSetup、invalidQuestionです。残る2つは自分のページに概要を公開していません。iOS 26.1のsystemError(underlyingError:)と、SignificantAppUpdateTopicと同時にiOS 26.2で登場したnotAvailableです。notAvailableの意味は、注11で引用したサンドボックスのテスト記事にしか書かれていません。systemErrorは少なくともシグネチャで原因を名指ししています。communicationLimitsNotEnabledやcontactSyncNotSetupが重要なアップデートの問い合わせでも発生し得るのかどうかは、記述がありません。 ↩ -
Apple、
AppTransactionのappTransactionIDおよびoriginalAppVersion、StoreKit。識別子の意味(「App Storeは、アプリをダウンロードしたApple Accountごとに、そしてファミリー共有に対応するアプリではファミリーグループのメンバーごとに、グローバルに一意なappTransactionIDを1つ生成します」)、再ダウンロード、返金、再購入、ストアフロントの変更をまたいだ安定性、App Store Server Notificationsバージョン2のペイロードへの含有、そして無料アプリにとって決定的な一文「appTransactionIDは、顧客がApp内課金を一切行わなくても利用できます」の出典です。originalAppVersionは「顧客が最初にApp Storeから購入したアプリのバージョン」で、macOSではCFBundleShortVersionString、それ以外ではCFBundleVersionを運び、サンドボックス環境では常に1.0になります。サーバー側の対応する型は、App Store Server APIのバージョン1.15で導入されたappTransactionIdです。 ↩↩↩↩↩ -
Apple、CommunicationLimitsおよびupdates、PermissionKit。
updatesはfinal var updates: some AsyncSequence<PermissionResponse<CommunicationTopic>, Never> { get }と宣言され、「コミュニケーションのトピックをシステムに登録し、許可の更新を受け取るためにアプリをバックグラウンドでオンデマンド起動できるようにします」と要約されています。Appleのドキュメントは、updatesと2つのCommunicationLimits.ask(_:in:)のオーバーロードをDeprecatedのAPIの見出しの下にまとめています。クラス自体はisKnownHandle(_:)とknownHandles(in:)のために現行のままです。置き換え後のシーケンスは、その約束を落としています。AskCenter.responses(for:)の要約にも解説にも、バックグラウンド起動への言及は一切ありません。本文が指摘しているドキュメントの欠落は、まさにここです。 ↩ -
Apple、AskCenterおよびresponses(for:)、PermissionKit。いずれもiOS 26.2、iPadOS 26.2、Mac Catalyst 26.2、macOS 26.2、visionOS 26.2から利用可能。
AskCenterはstatic let sharedから到達するfinal classで、「質問を適切なファミリー共有のチャネルへ振り分け」、「親が判断を下したときにアプリへ応答を返す」ものと説明されています。responses(for:)はfinal func responses<Topic>(for topicType: Topic.Type) -> some AsyncSequence<PermissionResponse<Topic>, Never> where Topic : QuestionTopicと宣言され、「トピックの型をシステムに登録し、応答の非同期シーケンスを返します」と要約されるのみで、バックグラウンド起動への言及はありません。ask(_:in:)のオーバーロードは4つあり、iOS、iPadOS、visionOSでUIViewControllerを取るものが2つ、macOSでNSWindowを取るものが2つ、トピック型ごとに1つずつです。PermissionResponseはchoiceとquestionを公開し、PermissionChoice.Answerが公開するのはapprovalとdenialのちょうど2ケースです。 ↩↩ -
Apple Developer ForumsのAppStore.ageRatingCode always returns 0 on real deviceにおけるApple Staffの返信。元の投稿は2026年4月、iOS 26.4の実機でサンドボックスアカウントにサインインし、App Store Connectで年齢制限を設定した状態で
0が返ると報告しています。Apple Staffと表示された投稿者による返信はこう述べています。「ageRatingCodeAPIは、最後に把握していた値と比較して、アプリの年齢制限の変化を時系列で観測するために使うべきものです。アプリの年齢制限コードが変わっていた場合は、Significant Change APIを使って親または保護者に知らせることを検討してください」、そして「Xcodeおよびサンドボックス環境(TestFlightを含む)からビルドして実行している開発中は、値0が返るのが想定どおりです」。2026年7月26日に二度取得し、文面は同一でした。フォーラムはJavaScriptで描画され、返信の古さを日付ではなく「1w」という相対表記で表示するため、ここでは公開日を記していません。フォーラムの返信はドキュメントのページより弱い証拠であり、ageRatingCodeのドキュメントは0という値について一切触れていません。本文で導いた帰結、すなわち0を基準値として保存するとApp Storeでの初回ビルドで偽の変更が作り出されるという点は、この返信とAppleが文書化した比較のパターンからの私の推論です。 ↩↩↩↩ -
Apple、Enabling App Store Server Notifications。TLSの下限(「サーバーはTransport Layer Security (TLS) 1.2以降のプロトコルに対応している必要があります」)、App Store Connectでの環境ごとのURL設定、ポートの制約(443、または1024以上)、許可リストのサブネット(「IPアドレスのサブネット
17.0.0.0/8を追加してください」。これは「サンドボックスと本番の両方の環境に適用されます」)の出典です。対になる記事Receiving App Store Server NotificationsはJWSで署名されたsignedPayloadを説明していますが、2026年7月26日時点ではdataオブジェクトにしか触れておらず、appDataには言及していません。 ↩ -
Apple、Responding to App Store Server Notifications。成功時のコード(「HTTP
200、または200から206の間のHTTPコードを返します」)、再送の引き金(「App Storeに通知を再送させるにはHTTP50xまたは40xを返します」)、バージョン2の再送スケジュール(「前回の試行から1、12、24、48、72時間後の計5回再試行します」)、サンドボックスの制限(「再送通知は本番環境でのみ利用できます。サンドボックス環境では、App Storeのサーバーは通知の送信を1回だけ試みます」)、およびGet-Notification-Historyによる復旧経路の出典です。 ↩↩ -
Apple、subtype、App Store Server Notifications。このページは19個の可能な値(ACCEPTED, ACTIVE_TOKEN_REMINDER, AUTO_RENEW_DISABLED, AUTO_RENEW_ENABLED, BILLING_RECOVERY, BILLING_RETRY, CREATED, DOWNGRADE, FAILURE, GRACE_PERIOD, INITIAL_BUY, PENDING, PRICE_INCREASE, PRODUCT_NOT_FOR_SALE, RESUBSCRIBE, SUMMARY, UPGRADE, UNREPORTED, VOLUNTARY)を公開しており、それぞれが特定の通知タイプに紐づいています。2026年7月26日に閲覧した時点で、
RESCIND_CONSENTという文字列はページのペイロードのどこにも現れません。 ↩ -
Apple、PermissionButton、PermissionKit。
@MainActor @preconcurrency struct PermissionButton<Topic, Label> where Topic : QuestionTopic, Label : Viewは、iOS 26.2、iPadOS 26.2、Mac Catalyst 26.2、macOS 26.2、visionOS 26.2から利用可能で、CommunicationTopicとSignificantAppUpdateTopicにそれぞれ制約されたinit(question:label:)のオーバーロードを2つ持ちます。これはCommunicationLimitsButtonを置き換えるもので、旧APIはフレームワークのページのDeprecatedのAPIに掲載されています。 ↩↩↩ -
Apple、AgeRangeService.showSignificantUpdateAcknowledgment(in:updateDescription:)、SignificantUpdateAction、およびSwiftUIの環境値showSignificantUpdateAcknowledgment。このメソッドは
@MainActor func showSignificantUpdateAcknowledgment(in windowScene: UIWindowScene, updateDescription: String) async throwsと宣言され、iOS 26.4、iPadOS 26.4、Mac Catalyst 26.4を公開していますが、macOSの行はありません。AgeRangeServiceは「Displaying update acknowledgments」の下にこのオーバーロード1つだけを掲載しています。SignificantUpdateActionと環境値も同じ3プラットフォームを公開しています。メソッドに添えられたAppleのImportantの注記はこうです。「この関数を呼ぶ前に、RegulatoryFeatureを確認して、その人がアプリの重要な変更を確認する必要があるかどうかを判断してください」。環境値の解説はさらに、「このアクションはButtonまたはonAppear(perform:)から呼び出してください」と付け加えています。 ↩↩↩↩ -
Apple、requestAgeRange(ageGates:::in:)、Declared Age Range。Appleは2つのオーバーロードを公開しています。iOS 26.0、iPadOS 26.0、Mac Catalyst 26.0で
in viewController: UIViewControllerを取るものと、macOS 26.0でin window: NSWindowを取るものです。年齢レンジのリクエストにはNSWindow版が存在し、注27で挙げた確認シートには存在しない、という対比が、macOSの欠落を方針上の決定ではなく漏れと読む根拠です。Appleはこの点について何も公表していません。 ↩ -
Apple、Requesting people’s age range information in your app、Declared Age Range。本文で引用したゲートの算術(「年齢ゲートは最大3つまで指定でき、そこから最大4つの年齢レンジが作られます」)、間隔の制約(「各レンジは最低2年の幅が必要です」)、そして境界の意味(「
lowerBoundの値がnilのとき、その人は最も低い年齢ゲートを下回っています」および「upperBoundがnilのとき、その人は最も高い年齢ゲート以上です」)の出典です。13、16、18にゲートを置くと、Appleがテキサス州向けに公開している4つのレンジがちょうど返り、有界の2レンジはどちらも2年の最小幅を満たします。13〜15は3年、16〜17は2年です。またこの記事は、その人のアカウントが属する地域が「システムが年齢レンジを返す際に用いる年齢ゲートを決めるため、リクエストで指定した年齢ゲートと異なる場合があります」とも警告しています。2026年7月26日にAppleのドキュメントJSONから読み取りました。 ↩ -
著者による調査、2026年7月26日。プラットフォームに関する主張をどう確立したかについて。プラットフォームの値は、デプロイメントターゲットのキーではなく、各プロジェクトの
SUPPORTED_PLATFORMSビルド設定から読みました。前者はXcodeが配信先に関係なく書き込むためです。Repsはappletvos appletvsimulator iphoneos iphonesimulator macosx xros xrsimulatorに加えて別途watchos watchsimulatorのターゲットを宣言しており、Ace Citizenshipはiphoneos iphonesimulatorのみを宣言しています。この手法はプラットフォームを過少報告し、その証拠がReturnです。ReturnのSUPPORTED_PLATFORMSの値はiphoneos iphonesimulator macosx xros xrsimulatorだけで、TVとwatchのターゲットは代わりにSDKROOT = appletvosとSDKROOT = watchosを持つため、SUPPORTED_PLATFORMSの一括検索ではどちらも見えません。したがって本文の「プラットフォームXに出荷している」という主張はすべて、ビルド設定ではなくApp Store Connectに基づいています。Return:TV_OS 1.0と1.0.1がいずれもREADY_FOR_DISTRIBUTION、IOSとMAC_OSの1.0.1も同様で、iOSターゲットはEmbed Watch Contentフェーズを通じてReturnWatch Watch App(com.941apps.Return.watchkitapp)を内包しています。watchアプリが手首に届くのはこの経路です。Reps:IOS 1.1とMAC_OS 1.1がREADY_FOR_DISTRIBUTION、TV_OSのバージョンがその状態になったことは一度もなく、TV_OS 1.2は2026年6月2日からWAITING_FOR_REVIEWのままです。したがってRepsが出荷しているのはiOSとmacOSです。 ↩ -
著者による調査、2026年7月26日、macOS 26.5.2(ビルド25F84)、Xcode 26.6(ビルド17F113)、Swift 6.3.3。範囲を鵜呑みにせず検証・再現できるよう、選定ルールを明記します。自分のエージェント設定(
~/.claude/CLAUDE.md)にあるActive Projectsの表のうち、背後にXcodeプロジェクトがある行すべて。結果はちょうど7つで、Reps、Return、Banana List(Get Bananasとして出荷)、Ace-Citizenship、Water、ResumeGeniApp、Yawaraです。そしてこのルールこそが調査の欠陥でもありました。Randoriはこの表に行を持たず、しかも最も重要だったのがそのRandoriだったからです。7つのうち5つはApp Store Connectに記録があります(Reps 6776044339、Return 6756242021、Get Bananas 6756241534、Ace Citizenship 6532592671、ResumeGeni 6771154645)。WaterとYawaraはアカウントの18アプリのどこにも現れず、したがって一度も提出されておらず、どちらかをアプリと呼ぶのは言い過ぎです。プロジェクトごとのSwiftファイル数は77、57、55、26、34、71、143。同意に関する検索は*.swift、*.entitlements、*.plist、project.pbxprojを対象とし、それぞれ85、65、63、34、38、74、149ファイル、合計508ファイルでした。この件数を再現するには、除外するディレクトリ名が6つではなく8つ必要です。build、DerivedData、.build、Pods、.git、worktrees、そしてRepsだけに存在する.venv(Reps/.venvとReps/server/.venvにまたがるプロパティリスト142件)と.xcode-state-backups(18件)です。最初の6つだけを除外するとRepsは245、合計は668になるため、この除外リストは結果を左右します。だからこそ依存する名前をすべてここに書いています。検索した16のパターンはすべて大文字小文字を区別します。PermissionKit、CommunicationLimits、AskPermission、AskCenter、SignificantAppUpdateTopic、SignificantUpdateAction、PermissionTopic、com.apple.developer.family-controls、FamilyControls、ManagedSettings、DeviceActivity、AuthorizationCenter、CKShare、sharedCloudDatabase、publicCloudDatabase、ageRatingCode。7プロジェクトすべてで一致ファイルはゼロ、AskCenterも含めてです。まったく同じ手順で走らせた2つの対照パターンは非ゼロを返しました(StoreKitはRepsで3ファイル、CKContainer|NSPersistentCloudKitContainer|SwiftDataはBanana Listで17ファイルに一致)。これにより、この手順がファイルを黙って読み飛ばしていないことが分かります。Ace Citizenshipのオンボーディング(IntroCarouselView、WelcomeView、AddStateView、AddRepresentativeView)には年齢や生年月日の入力欄がなく、PrivacyInfo.xcprivacyは空のNSPrivacyCollectedDataTypesを宣言しています。「18歳以上」という受給資格の記述は~/Projects/acecitizenship.app/content/blog/n400-application-guide.mdに由来します。 ↩↩↩ -
著者による調査、2026年7月26日。より広い検索とRandoriについて。広域の検索は、同じ16のパターンを
~/Projects配下のすべてのリポジトリに対して走らせ、同じ8つの名前にnode_modulesを加えて除外し、gitignore対象のパスも除きました。一致は21ファイル。うち7つがコードで、Randori/Randori/配下のSwiftファイル6つと、_archive/Oishii-AI/Oishii AI/Services/CloudKitManager.swift(アーカイブ済みプロジェクト内のpublicCloudDatabase)です。残る14は文章か機械的な状態ファイルで、Randoriの計画・設計文書9件、このサイト自身のcontent/blog/にある投稿3件(うち1件は本記事の草稿)、Obsidianの引き継ぎメモ1件、そして人ではなくスクリプトが書くobsidian-signals/40-Projects/blakecrosley-com/wwdc-2026/.pulse_state.jsonです。Randoriはcom.wayofyawara.randori、App Store Connectのアプリ6789693294で、バージョン1.0はPREPARE_FOR_SUBMISSIONです。CKShareとsharedCloudDatabaseは6ファイル20行に一致します。ConnectionStore.swift(10)、RandoriApp.swift(5)、ProfileCardView.swift(2)、そしてCKPostTransport.swift、CloudShareSheet.swift、SocialContracts.swiftが各1行です。ConnectionStoreはヘッダーコメントで自らの形を「1ゾーン(ProfileCardZone)、1レコードタイプ(ConnectionCard)、1共有」と説明し、privateCloudDatabaseとsharedCloudDatabaseを並べて保持し、355行目にaccept(_ metadata: CKShare.Metadata)、547行目にensureOutboundShare()、そしてアカウント単位のブロックと解除を実装しています。RandoriApp.swiftはアプリデリゲート(73行目)とウィンドウシーンデリゲート(97行目、「Warm: the app is running when the link is opened」というコメント付き)の両方にuserDidAcceptCloudKitShareWithを実装し、RandoriSceneDelegate.scene(_:willConnectTo:options:)は88行目で「Cold start: the invitation rides the connection options」というコメントの下にconnectionOptions.cloudKitShareMetadataを読んでいます。本文がコールドスタートを受諾コールバックではなくconnection optionsに割り当てているのはこのためです。TagConsentStoreはこのアプリ独自の同意台帳で、iCloudアカウント単位でスコープされ、文書化された既定はフェイルクローズドです。ポリシーのレコードが届いていない相手にはタグを付けられません。Randori/Randori.entitlementsはCloudKit、HealthKit、aps-environmentを要求しています。CloudKit共有まわりの2つを除く同意関連のパターンは、このリポジトリ全体でゼロを返し、StoreKit、signedPayload、notificationTypeも同様です。したがってこのアプリは何も販売しておらず、自前のサーバーも運用していません。docs/asc-metadata.mdは無料の価格と4+の年齢制限を用意しています。 ↩↩↩↩ -
著者による調査、2026年7月26日。StoreKitの呼び出し箇所とサーバー側の証拠について。StoreKitは3つのプロジェクトに現れます。
Reps/Reps/Services/RepsProStore.swift(自動更新、2段階)、Ace Citizenship/StoreKitManager.swift(非消耗型1件)、ResumeGeni/Subscription/(月額サブスクリプション1件、サーバー側でゲート)。表に引用した.pendingの扱いは、RepsProStore.swift:134(case .userCancelled, .pending:)、StoreKitManager.swift:69-73(独立したcase .pending:で、そのreturn falseは73行目)、SubscriptionStore.swift:209-212(名前の付いた保留の結果)にあります。利用者を宙ぶらりんにするのは呼び出し側です。RepsProPaywallView.swift:359-361はif await store.purchase(plan)の内側でのみ画面を閉じ、ContentView.swift:484-485はif successの内側でのみロックを解除するため、保留中の購入に対してfalseが返っても、どちらのアプリでも画面上は何も変わりません。ResumeGeniのほうはPaywallView.swift:526に到達し、そこの.pendingの分岐が「承認をお待ちください。承認され次第、アクセスできるようになります」というトーストを表示します。ResumeGeniのApp Store Server Notificationsのエンドポイントは~/Projects/resumegeni/app/routers/appstore.pyのPOST /api/appstore/notificationsです。{"signedPayload":"probe"}をPOSTするとHTTP 400の{"status":"invalid"}が返ります。これは有効化フラグを越え、Appleの証明書チェーン検証の内側でしか到達しない応答です。GETは405を返します。両方の環境URLが登録済みであり、その証拠は手順書ではなく実際の配信です。941-analyticsのD1データベース、テーブルfunnel_eventsには、platform='ios'かつメタデータにnotification_typeを持つ行が56件あり、2026-06-26T15:48:51Zから2026-07-25T16:40:11Zまでにわたります。うち55件はenvironmentがsandbox、1件がproduction(2026-07-21T18:08:21Z)です。56という数字は下限として扱ってください。このサービスはファネルの行にマッピングするイベント名を5つしか持たないためです。実際に観測された4タイプはDID_RENEW(42)、SUBSCRIBED(6)、EXPIRED(5)、DID_CHANGE_RENEWAL_STATUS(3)です。app/services/app_store_notification_service.pyは13の通知タイプを名前で挙げ、うち8つが_funnel_event_name(75〜89行目)で実行される分岐に到達します。SUBSCRIBED、OFFER_REDEEMED、DID_RENEW、REFUND、REVOKE、EXPIRED、DID_CHANGE_RENEWAL_STATUS、DID_FAIL_TO_RENEWです。残る5つはコメントの中にしか出てきません。73行目のPRICE_INCREASE、RENEWAL_EXTENDED、METADATA_UPDATEと、187行目のEXTERNAL_PURCHASE_TOKEN、TESTです。RESCIND_CONSENT、CONSUMPTION_REQUEST、REFUND_DECLINED、REFUND_REVERSEDは、このリポジトリ全体で一致ゼロです。何が証拠にならないかについても記しておきます。docs/SUBSCRIPTION_GO_LIVE.md:83には確かに「本番とサンドボックスの両方のURLを設定すること」と書かれていますが、この行は当該手順に「再認証が必要」と注記された見出しの下にある手順書の指示であり、登録が完了したことではなく意図を記録しているにすぎません。したがって上記の登録に関する主張は、この記述ではなく実際に配信された通知に依拠しています。 ↩↩↩ -
Apple、Testing Ask to Buy in Xcode、StoreKit。仕組みについてのAppleの説明(「Ask to Buyでは、子どもが対象となる購入やダウンロードを行おうとすると、システムはその購入リクエストを親または保護者に送ります」)と、拒否時の挙動(「Ask to Buyを拒否したため、アプリは取引を受け取りません」)の出典です。この記事はまた、StoreKit構成エディタのPurchase Options配下にあるAsk to Buyのトグルについても説明しており、トランザクションマネージャはPending Ask to Buy、Ask to Buy Approved、Ask to Buy Declinedの各状態を表示します。 ↩↩↩
-
Apple、Product.PurchaseResult.pendingおよびTransaction.updates、StoreKit。どちらもiOS 15.0から利用可能です。ケースの概要(「購入は保留中で、顧客側の操作が必要です」)、解決の経路(「保留中の購入が成功すると、StoreKitは結果の
Transactionをトランザクションのupdatesで届けます」)、そしてこのシーケンスの目的(「このシーケンスは、Ask to Buyの取引、オファーコードの利用、顧客がApp Storeで行う購入など、アプリの外で発生する取引を受け取ります」)の出典です。Product.PurchaseResultの列挙型はsuccess(_:)、pending、userCancelledの3ケースを公開しています。列挙型のページにあるAppleの例は、保留の分岐に「購入には顧客側の操作が必要です。取引が完了した場合はTransaction.updatesから取得できます」というコメントを付けています。 ↩↩ -
上の分岐のコードに登場するすべてのシンボルは、2026年7月26日にAppleのドキュメントJSONに照らして検証しました。
AgeRangeService.sharedはstatic let shared: AgeRangeService(iOS 26.0)です。SwiftUIの環境値はrequestAgeRange、var requestAgeRange: DeclaredAgeRangeAction { get }(iOS 26.0)と、showSignificantUpdateAcknowledgment、var showSignificantUpdateAcknowledgment: SignificantUpdateAction { get }(iOS 26.4)です。コードの@available(iOS 26.5, *)という下限は、そのどちらにも由来しません。AgeRangeService.AgeRangeDeclaration.confirmedがiOS 26.5、iPadOS 26.5、Mac Catalyst 26.5、macOS 26.5を公開しており、確認シートのアクションより1リリース後だからです。確認済みの成人を区別するコードは、この高いほうの下限を引き継ぎます。Apple自身のサンプルプロジェクトも同じ26.5の対応バージョンを公開しています。6AgeRangeService.AgeRangeはlowerBound、upperBound、var ageRangeDeclaration: AgeRangeService.AgeRangeDeclaration?と宣言されたageRangeDeclaration、activeParentalControlsを公開します。このオプショナルに対する== .confirmedの比較が有効なのは、関係セクションのとおりAgeRangeDeclarationがEquatableとHashableに準拠しているためです。PermissionButtonのイニシャライザはinit(question: PermissionQuestion<Topic>, @ViewBuilder label: @escaping () -> Label)で、ここで使ったオーバーロードはSignificantAppUpdateTopicに制約されています。26ChangedFeatureViewとAccountVerificationPromptはAppleのシンボルではなく、各自のビューのプレースホルダです。 ↩↩↩ -
Apple、Age ratings values and definitions、App Store Connect Help、2026年7月26日に閲覧。注9で告知された2026年6月18日の変更が実際に発効したことを裏づける出典です。「Australia age rating values」の表には現在、16+とR 18+の2つの区分だけが並び、15+の行はありません。「Vietnam age rating values」という独立したセクションが新設され、「ベトナム政令147号第38条により必要とされるとおり」という前置きで導入されています。その00+の行は「不快な内容は含まないが、以下のコンテンツを含む場合がある」アプリと定義され、ペアレンタルコントロール、年齢確認、ユーザー生成コンテンツ、メッセージとチャット、広告、頻度の低いコンテストが列挙されています。なお、オーストラリアの移行についてAppleが5月21日に挙げた記述子のリストは、このページの現在の16+の判定条件と一致しません。この食い違いは未解決であり、依拠もしていません。ここで導いている主張は、15+の区分が消えたことと、ベトナムの表が存在することだけだからです。 ↩↩↩