Will Apple Let This App Into the Kids Category?
Yes — the app already meets every rule Apple can check in the code. What remains is paperwork.
Every row on this page was checked by reading the shipped code, not by recalling what we intended to build. Apple’s rules were re-read from developer.apple.com on September 17, 2026 (section 07 lists the pages and the date).
| Area | Where it stands | Status |
|---|---|---|
| Kids Category rules (Guideline 1.3 and 5.1.4) | No links out of the app, no purchases, no third-party analytics or advertising, nothing sent to anyone. The parent gate is a two-finger, three-second hold, which is one of Apple’s own examples of a gate. Eleven rows checked, all met; one judgment call for Ari (section 02). | Met |
| Privacy declarations | The App Store label is Data Not Collected, and that is literally true — the app contains no networking code at all. The privacy manifest inside the app is complete: the only Apple-listed “required reason” API Meadow uses is UserDefaults, and it is declared. | Met |
| Build declarations | Encryption declared exempt, landscape only, iPad only, iPadOS 18 minimum, full screen, camera and photo purpose strings present, no microphone. | Met |
| Public privacy policy and support page | Apple requires both as public web addresses. Written in this deliverable and published at meadow.anyfundedneed.com/support/ and /support/privacy.html. Before this work those addresses returned 404. | Met |
| Developer account | The app is still signed by an individual Apple developer account. It has to be re-created under Any Funded Need before submission. This is the long pole and it is not engineering. | Ari |
| App Store Connect answers | The age-rating questionnaire, the “Made for Kids · Ages 5 and Under” selection, the privacy-label answer and the two URLs are typed into Apple’s website by the account holder. The answers are drafted here (sections 02–05). | Ari |
| A support email address | The support page has no email on it because none exists in the project. Apple asks for a support URL (done) and a contact email (blank). | Ari |
How to read the evidence column
Info.plist:45-49 means “open that file, look at lines 45 to 49.” All paths are inside the app source folder Meadow/Meadow/ unless they start with Meadow/project.yml, which is the build recipe. “grep” rows mean the whole app source was searched for that text and the count is what came back.
Guideline 1.3 (Kids Category) and 5.1.4 (Kids), row by row
Apple’s own words are paraphrased in the first column; the exact text is on the pages cited in section 07. “Met” means the shipped code satisfies the rule today. “Ari” means the code is fine but a human has to type an answer into App Store Connect, or make a call.
| Apple requires | Meadow’s answer | Evidence | Status |
|---|---|---|---|
| Pick an age band: Ages 5 and Under, 6–8, or 9–11. Locked once approved. | Ages 5 and Under. Meadow is built for pre-verbal children from 12 to 48 months; onboarding asks for the child’s age in months and picks a starting level from it. Nothing in the app is aimed at older children. | Views/FirstRunOnboardingView.swift:77-110 (age in months), :185-194 (level from age) AGENTS.md · Project Context |
Met |
| No links out of the app unless behind a parental gate. | There are no links out of the app anywhere — gated or not. No web view, no browser hand-off, no “visit our site,” no mail composer. The only navigation links go to the app’s own settings screens. | grep Link(, openURL, UIApplication.shared.open, WKWebView, SFSafariViewController, MFMail → 0 hitsIn-app only: Views/Settings/SettingsView.swift:73, AboutSettingsView.swift:21,31 |
Met |
| No purchasing opportunities unless behind a parental gate. | Nothing is for sale. The app is free, has no in-app purchases and does not link Apple’s purchasing framework at all. | grep import StoreKit → 0 hitsFull import census: section 03 |
Met |
| A parental gate: an adult-level task that keeps children out of settings and other distractions. | Hold two fingers on the lock for three seconds. Apple’s own examples include “holding a button,” so the gesture alone satisfies the rule. The gate re-locks the instant the app leaves the foreground, so settings never stay open in the app switcher. A PIN layer exists in the code (hashed, in the device Keychain, with lock-out after repeated wrong tries) but the September 16 audit found no shipped screen can set it; that is being fixed in the “18 controls” work and is not something Apple requires. | Views/ParentGate/ParentGateGestureView.swift:46-47 (two fingers, 3.0 s), :23 (spoken hint) Services/MeadowParentGateService.swift:83-94 (attempt limit, SHA-256 hash) Services/MeadowKeychainCredentialStore.swift:5-17 ContentView.swift:119-122 (auto-lock) |
Met |
| No third-party analytics. No third-party advertising. | None. Every framework the app imports is Apple’s. The one outside package in the project (a screenshot-comparison tool) is linked only into the test bundle, which never ships. | grep ^import across app source → Foundation, SwiftUI, SwiftData, UIKit, CoreGraphics, Observation, AVFoundation, PhotosUI, ImageIO, os, UniformTypeIdentifiers, Security, CryptoKit, Charts — all AppleMeadow/project.yml:10-13 (package), :74-77 (test target only) |
Met |
| May not send personally identifiable information or device information to third parties. | The app cannot send anything to anyone. It contains no networking code. This is not a setting that could be flipped; the capability is absent. | grep URLSession, URLRequest, NWConnection, import Network, CloudKit → 0 hitsgrep analytics, telemetry, crashlytics, firebase, sentry → 0 hits in code (only the in-app privacy text saying there are none) |
Met |
| Comply with children’s privacy law (COPPA, GDPR). Apps that handle a minor’s name, photos or other personal data must have a privacy policy. | Nothing is collected, so there is nothing to consent to. A parent may type the child’s name, pick an age, and add photos — all of it stays on the iPad in the app’s protected storage. A privacy policy exists inside the app and, with this deliverable, on the web. | Models/CustomWordTemplate.swift:4 (child’s name is an optional word) Services/PersonalImageStore.swift:159-177 (photos: full file protection, excluded from backup) Views/Settings/AboutSettingsView.swift:113-132 (in-app policy) docs/support/privacy.html (public policy) |
Met |
| Privacy policy reachable inside the app and linked in App Store Connect (5.1.1). | In the app: Settings → About → Privacy Policy, behind the parent gate, as plain text (no tappable link, which is what Kids Category wants). In App Store Connect: the field takes the public URL from this deliverable. | Views/Settings/AboutSettingsView.swift:31-39 Public: meadow.anyfundedneed.com/support/privacy.html |
Met |
| “Made for Kids” is only offered when the calculated age rating is 4+ or 9+. | Every questionnaire answer is “None.” No violence, no mature themes, no gambling, no unrestricted web, no user-generated content shared with others, no contests. The one question a reviewer might pause on is Medical or Treatment Information: Meadow speaks words a child chooses; it gives no medical advice, and its terms say so. Recommended answer: None. | Views/Settings/AboutSettingsView.swift:96-98 (“not a medical device”) Apple: Set an app age rating, section 07 |
Ari |
| Words like “for kids” or “for children” in the name, subtitle or description are reserved for Kids Category apps (2.3.8). | Allowed for Meadow, because it will be in the category. This is a constraint on the store listing (deliverable M5-004): the listing may say “for children,” and if the app were ever moved out of the Kids Category that wording would have to go. | Guideline 2.3.8 via 5.1.4(b), section 07 | Met |
| Once customers expect Kids Category behaviour, every later update must keep meeting it. | Already a standing project rule. “No user data collection” and “no third-party SDKs without explicit approval” are written into the instructions every engineer and every AI agent on the project reads first. | AGENTS.md · Design Constraints, Privacy Boundary | Met |
| Judgment call: the one way anything can leave the iPad. | If the app’s database ever fails to open, a full-screen recovery message offers a “Save a copy of your child’s setup” button that opens Apple’s share sheet. That screen replaces the whole app, a child sees no words on it, and it exists so a parent can rescue the setup instead of reinstalling. It is not a link out and it is not behind the two-finger gate. Recommendation: keep it as is, and say so in the review notes (section 05). Gating a rescue button behind a gesture the parent may never have learned defeats its purpose. Ari can overrule. | Views/StoreRecoveryView.swift:56-64 (ShareLink), :3-12 (why it exists) MeadowApp.swift:171-172 (only shown when the store cannot open) |
Ari |
The App Store privacy label: “Data Not Collected”
Apple defines “collect” as transmitting data off the device. Its guidance says outright that data processed only on the device is not collected and need not be disclosed. Meadow qualifies on every line.
| Apple asks | Meadow’s answer | Evidence | Status |
|---|---|---|---|
| Does the app collect any data? | No. Answer “No, we do not collect data from this app.” The label reads Data Not Collected. | No networking code (section 02) PrivacyInfo.xcprivacy:7-8 (empty collected-data list) |
Met |
| Does the app track users across apps or sites? | No. No advertising identifier, no tracking domains. | PrivacyInfo.xcprivacy:5-6 (NSPrivacyTracking = false) |
Met |
| What about the usage record the app keeps? | Stays on the iPad, in the app’s own database. Each record is a word, a room, a level and a time. It exists so a parent or therapist can see how the child uses the app. No copy leaves the device, which is why it does not count as collection under Apple’s definition. | Engine/MeadowEventLogger.swift:18-33 (writes to local database) Models/EventRecordV3.swift:6-12 (what a record holds) |
Met |
| What about photos and the child’s name? | On the iPad only. Photos are re-encoded without their original metadata, stored with Apple’s strongest file protection, and excluded from device backups. The parent PIN is stored as a one-way hash in the Keychain, marked “this device only.” | Services/PersonalImageStore.swift:159-177 Services/MeadowKeychainCredentialStore.swift:16 ( ThisDeviceOnly) |
Met |
The privacy manifest inside the app
Since May 2024 every app must ship a file called PrivacyInfo.xcprivacy declaring what it collects and which of Apple’s “required reason” APIs it calls — a short list of system calls that could in theory be abused to fingerprint a device. Meadow’s file is 21 lines. Here is every line, checked against the code.
| Manifest entry | What the code actually does | Evidence | Status |
|---|---|---|---|
NSPrivacyTracking = false |
Correct. No tracking, so the companion list of tracking domains is not required. | Resources/PrivacyInfo.xcprivacy:5-6 | Met |
NSPrivacyCollectedDataTypes = empty |
Correct. Matches the “Data Not Collected” label above. | Resources/PrivacyInfo.xcprivacy:7-8 | Met |
User defaults → reason CA92.1 (“read and write information only accessible to the app itself”) |
Declared, and the right reason. The app uses UserDefaults for five one-time upgrade flags so an existing install is migrated exactly once. All keys are the app’s own; none are shared with other apps. | Resources/PrivacyInfo.xcprivacy:11-18 Services/LaunchMigrations.swift:36, SCSEnabledBackfillMigration.swift:39, ShowLabelsDefaultMigration.swift:26, RoutinesBackfillMigration.swift:42, MeadowAppCommunicationServices.swift:285-293 |
Met |
File timestamp APIs (creationDate, modificationDate, stat, getattrlist…) |
Not used, so correctly absent. The app’s file work is: does this file exist, delete it, list a folder, create a folder, set protection. None of those are on Apple’s list. | grep all 13 listed names → 0 hits FileManager calls: MeadowApp.swift:61-64, StoreRecoveryView.swift:27, ChildAvatarImageStore.swift:22,32, PersonalImageStore.swift:70-200 |
Met |
System boot time APIs (systemUptime, mach_absolute_time) |
Not used. The app reads launch arguments from ProcessInfo for test automation only; that is not on the list. |
grep → 0 hits (ProcessInfo hits are .arguments only) |
Met |
Disk space APIs (volumeAvailableCapacity, statfs…) |
Not used. | grep all 13 listed names → 0 hits | Met |
Active keyboard list (activeInputModes) |
Not used. | grep → 0 hits | Met |
Result of the manifest audit
No fix to the manifest was needed. The plan for this deliverable allowed for one code change if a used API turned out to be undeclared. Every category was checked against the source and the only match is the one already declared. The file ships inside the app because the whole Resources folder is bundled (Meadow/project.yml:39-43).
What the app tells Apple about itself when it is uploaded
| Declaration | Meadow’s answer | Evidence | Status |
|---|---|---|---|
Encryption export compliance (ITSAppUsesNonExemptEncryption) |
Declared “No” — the app uses no encryption beyond what iPadOS itself provides. The only cryptography in the code is a one-way hash of the parent PIN and the system Keychain, both Apple-built and exempt. With the key present, App Store Connect skips the export questionnaire on every upload. | Resources/Info.plist:21-22 Services/MeadowParentGateService.swift:90-94 (SHA-256 only) grep AES, ChaCha, HMAC → 0 hits |
Met |
| Orientation | Landscape only, both directions. The compass layout and the scene art are drawn for landscape; portrait is not declared, and the app re-asserts landscape when it becomes active. | Resources/Info.plist:45-49 ContentView.swift:108, 115 ( enforceLandscapeIfNeeded) |
Met |
| Device family | iPad only. Not offered on iPhone, not offered as an iPad app on Vision Pro (Kids Category apps cannot be, so this is also the safe setting). | Meadow/project.yml:18, 47 (TARGETED_DEVICE_FAMILY: "2"), :19 (Vision Pro off) |
Met |
| Minimum system version | iPadOS 18.0. This covers every iPad from the iPad 9 (2021) forward, which is the project’s minimum hardware. | Meadow/project.yml:4-5 | Met |
| Full screen | Requires full screen — no Split View or Slide Over, so a child cannot shrink the board by dragging in another app. | Resources/Info.plist:43-44 | Met |
| Camera and photo library purpose strings | Both present and honest: “photos that stay on this iPad.” Both features live behind the parent gate (they are settings screens). Without these strings Apple rejects the upload outright. | Resources/Info.plist:25-28 Views/Settings/CustomWordPhotoPicker.swift:21,61; ChildAvatarSettingsView.swift:21,50 (inside Settings → parent area) |
Met |
| Microphone / speech recognition | None. The app speaks; it never listens. No microphone purpose string, no recorder, no speech-recognition framework. | grep AVAudioRecorder, SFSpeech, requestRecordPermission, NSMicrophoneUsageDescription → 0 hits |
Met |
| Version and build number | Version 0.2.13; the build number is stamped automatically by Xcode Cloud so every TestFlight upload is unique. | Meadow/project.yml:50-51, 56 Meadow/ci_scripts/ci_pre_xcodebuild.sh |
Met |
| Signing identity / developer account | Still an individual developer account (team SW7V86Y2X5). Submission has to come from Any Funded Need. Because the app has never been published, Apple’s transfer tool is unavailable: the app record is re-created under the new team, Xcode Cloud is re-connected, and TestFlight testers get a fresh invitation. Bundle ID com.anyfundedneed.meadow can stay. |
Meadow/project.yml:23-26 (comment: “Individual Apple Developer account”), :46 (bundle ID) | Ari |
| Support URL and privacy policy URL (App Store Connect metadata) | Pages written in this deliverable and served from the same site as this portal. The two addresses returned 404 on September 17 before this change; they resolve once it is merged and deployed. Ari pastes them into App Store Connect. | docs/support/index.html → meadow.anyfundedneed.com/support/ docs/support/privacy.html → meadow.anyfundedneed.com/support/privacy.html |
Ari |
| Support contact email | Missing. No support address exists anywhere in the project, so the support page names the organisation and the website and nothing else. Apple’s review contact fields also need a phone and email. Recommendation: a dedicated address such as a Meadow mailbox at anyfundedneed.com, added to the support page in a one-line follow-up. | grep mailto:, @anyfundedneed across docs and portal → 0 real addresses |
Ari |
What the Apple reviewer reads before opening the app
This goes into the “Notes” box in App Store Connect. Reviewers spend minutes, not hours; the note tells them where the gate is so they do not fail the app for “could not find settings,” and states up front that there is no account and no network so they do not go looking for a login.
Every claim in that note maps to a row above
Offline and no SDKs: section 02. Gate gesture and PIN default: ParentGateGestureView.swift:46-58 (a fresh install has no PIN, so hasPIN is false and the hold unlocks directly). About screen: AboutSettingsView.swift:21-39. Recovery screen: StoreRecoveryView.swift. The two-finger instruction is the on-device wording; the Simulator wording differs because the Simulator cannot produce two touches (ParentGateGestureView.swift:11-25).
Two audiences read the same app, and both need it to stay a speech device
AbleNet’s funded devices are reimbursed under the HCPCS code E2510, which covers speech-generating devices. Software on a funded device must be defensible as speech generation or language development; anything that reads as entertainment can put the funding at risk. Apple, from the other side, reviews a Kids Category app for the same posture: no distractions, no purchases, nothing that pulls a child away from the app’s purpose. The two constraints point the same way, and the app already satisfies both.
| Constraint | How Meadow holds it | Evidence | Status |
|---|---|---|---|
| Stay speech-focused (E2510) | Every tap speaks. Celebrations and the companion character exist to reward communication, not as a game; there is no scoring, no levels to unlock, no currency. The usage record is framed as a record of utilisation for the family and the therapist, never as analytics. | AGENTS.md · Design Constraints Engine/MeadowEventLogger.swift (usage record) |
Met |
| Do not claim to be a medical device (Apple 1.4, 5.1.1) | The in-app terms say it plainly: an AAC app, not a medical device, not a replacement for a speech-language pathologist. No screen offers diagnosis, a score, or a developmental verdict. The age-rating answer for medical information is therefore “None.” | Views/Settings/AboutSettingsView.swift:93-104 | Met |
| Independent publisher, not the AbleNet brand | AbleNet asked for arm’s-length publishing. The bundle ID, the app name and the support site are all Any Funded Need’s, and the developer account must be too — which is the open item in section 04. | Meadow/project.yml:46 (com.anyfundedneed.meadow)docs/support/ (this deliverable) |
Ari |
What we need from AbleNet and Ari, in order
1. Enrol Any Funded Need in the Apple Developer Program. Already asked for on the gap list; nothing on this page can be submitted until it exists. One to four weeks on Apple’s clock.
2. A support email address. One line on the support page and two fields in App Store Connect.
3. Two decisions: confirm the age-rating answers in section 02 (all “None”), and confirm the recovery-screen share button stays as it is.
4. Type the answers in. Made for Kids · Ages 5 and Under; App Privacy · Data Not Collected; the two URLs; the review notes. Everything is drafted above, nothing needs inventing at the keyboard.
Apple’s rules as read on September 17, 2026
Apple revises these pages without notice. Each was fetched from developer.apple.com on the date shown and the checklist above reflects that text, not memory. If Apple changes a rule after this date, the row that cites it should be re-read before submission.
- App Review Guidelines — sections 1.3 Kids Category, 2.3.8, 5.1.1(i) Privacy Policies, 5.1.4 Kids. developer.apple.com/app-store/review/guidelines/ · fetched 2026-09-17
- Building apps for kids — age bands, parental-gate examples, what must sit behind a gate. developer.apple.com/app-store/kids-apps/ · fetched 2026-09-17
- Set an app age rating (App Store Connect Help) — Made for Kids is offered only at 4+ or 9+, and locks once approved. developer.apple.com/help/app-store-connect/manage-app-information/set-an-app-age-rating · fetched 2026-09-17
- Age ratings reference — the current tiers 4+, 9+, 13+, 16+, 18+. developer.apple.com/help/app-store-connect/reference/age-ratings · fetched 2026-09-17
- App privacy details on the App Store — the definition of “collect” and the on-device exemption. developer.apple.com/app-store/app-privacy-details/ · fetched 2026-09-17
- Privacy manifest files. developer.apple.com/documentation/bundleresources/privacy-manifest-files · fetched 2026-09-17
- Describing use of required reason API — the May 1, 2024 enforcement date. developer.apple.com/documentation/bundleresources/describing-use-of-required-reason-api · fetched 2026-09-17
- NSPrivacyAccessedAPIType — the five categories, every API name in each, and the reason codes. developer.apple.com/documentation/bundleresources/app-privacy-configuration/nsprivacyaccessedapitypes/nsprivacyaccessedapitype · fetched 2026-09-17
- Describing data use in privacy manifests. developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests · fetched 2026-09-17
- ITSAppUsesNonExemptEncryption and Complying with encryption export regulations. developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption · developer.apple.com/documentation/security/complying-with-encryption-export-regulations · fetched 2026-09-17