Meadow
Deliverable Review
Incorrect. Try again.
Five-Milestone Roadmap  /  M5  /  M5-003 Apple Compliance Package

Will Apple Let This App Into the Kids Category?

Apple’s Kids Category, privacy and submission rules, answered line by line against the app as it stands on September 17, 2026 — each answer points at the file and line that proves it.
Deliverable M5-003
Updated 2026-09-17
Milestone: M5 · Ship It
Ready for Review
01 The Short Answer

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).

AreaWhere it standsStatus
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 declarationsThe 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 declarationsEncryption 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 pageApple 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 accountThe 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 answersThe 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 addressThe 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.

02 Kids Category Checklist

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 requiresMeadow’s answerEvidenceStatus
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 hits
In-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 hits
Full 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 Apple
Meadow/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 hits
grep 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
03 Privacy Declarations

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 asksMeadow’s answerEvidenceStatus
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 entryWhat the code actually doesEvidenceStatus
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).

04 Build and Platform Declarations

What the app tells Apple about itself when it is uploaded

DeclarationMeadow’s answerEvidenceStatus
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
05 App Review Notes (Draft)

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.

Meadow is an augmentative and alternative communication (AAC) app for pre-verbal children aged 5 and under. A child taps a picture and the iPad speaks the word. Every feature works offline; the app contains no networking code, no account, no sign-in, no purchases and no third-party SDKs. Nothing is transmitted off the device. FIRST LAUNCH 1. Tap an age (in months) and a communication level, then "Start Meadow". Any choice is fine for review; 24 months / Word Combinations is typical. 2. The board appears: a room scene in the centre with picture tiles around the edges. Tap any tile and the word is spoken aloud. Tap the feelings arch at the top to hear a feeling. Tap the house or map to visit other rooms. PARENTAL GATE (Guideline 1.3) Settings are behind a parental gate. Hold TWO FINGERS on the black "Hold with 2 fingers" lock capsule in the top-right corner for THREE SECONDS. (Only if you are testing in Simulator, click-and-hold for three seconds instead.) A PIN is optional and is not set on a fresh install, so the hold opens settings directly. Settings re-lock automatically whenever the app leaves the foreground. INSIDE SETTINGS Privacy Policy and Terms of Service are under Settings > About. Camera and photo library are requested only if a parent adds a personal photo under My Words or My Child; the photo stays on the iPad. ONE SCREEN YOU WILL NOT SEE If the app's local database ever fails to open, a recovery screen replaces the app with a "Save a copy of your child's setup" button. It opens the standard iOS share sheet so a parent can keep a copy of the child's words. It contains no links and no network calls, and it cannot be reached during normal use. The app is landscape only and iPad only by design: the layout places the scene in the centre and words around it, which portrait cannot hold. Contact for review questions: [name, phone, email — Any Funded Need]

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).

06 Positioning Constraints

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.

ConstraintHow Meadow holds itEvidenceStatus
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.

07 Sources

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.