feat(metadata): support privacy nutrition labels (data usage)#3596
Draft
feat(metadata): support privacy nutrition labels (data usage)#3596
Conversation
Adds a new `privacy.dataUsage` block to the eas-cli metadata schema and a `DataUsageTask` that pushes/pulls App Privacy Nutrition Labels via the @expo/apple-utils AppDataUsage* models. After a successful push the publish state is flipped to published so the changes take effect. Apple has required every new app submission since 2021 to declare what data the app collects, so this closes the biggest remaining gap in `eas metadata`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
❌ It looks like a changelog entry is missing for this PR. Add it manually to CHANGELOG.md. |
|
Subscribed to pull request
Generated by CodeMention |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3596 +/- ##
==========================================
+ Coverage 54.26% 54.40% +0.14%
==========================================
Files 821 822 +1
Lines 35327 35470 +143
Branches 7363 7412 +49
==========================================
+ Hits 19166 19293 +127
- Misses 16074 16090 +16
Partials 87 87 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
privacy.dataUsageblock to the eas-cli metadata schema (schema/metadata-0.json) so users can declare App Privacy Nutrition Labels alongside the rest of their App Store metadata.DataUsageTask(packages/eas-cli/src/metadata/apple/tasks/data-usage.ts) that pulls existingAppDataUsagerows from App Store Connect and pushes the local config back. The task is declarative: rows in ASC that aren't in the local config are deleted, missing rows are created. After a successful push theAppDataUsagesPublishStateenvelope is flipped topublished: trueso the changes take effect on the storefront.createAppleTasks()and theAppleDatacontext type. AddsgetDataUsage()/setDataUsage()to the config reader/writer.Why this matters
Apple has required every new app submission since 2021 to declare what data the app collects, the purposes it's used for, and how it's linked to the user (Privacy Nutrition Labels / App Privacy details). Until now this was the biggest remaining gap in
eas metadata— users had to maintain it by hand in App Store Connect even when everything else was managed declaratively.Schema shape
{ "apple": { "privacy": { "dataUsage": { "dataNotCollected": false, "categories": [ { "category": "CONTACTS", "purposes": ["ANALYTICS", "APP_FUNCTIONALITY"], "protections": ["DATA_LINKED_TO_YOU"] } ] } } } }The category, purpose, and protection enums are pulled directly from
@expo/apple-utils(AppDataUsageCategoryId,AppDataUsagePurposeId,AppDataUsageDataProtectionId). Each category in the local config is expanded into the cartesian product of(category × purpose × protection)rows on push, matching Apple's flat row model.Enum reference
ADVERTISING_DATA,AUDIO,BROWSING_HISTORY,COARSE_LOCATION,CONTACTS,CRASH_DATA,CREDIT_AND_FRAUD,CUSTOMER_SUPPORT,DEVICE_ID,EMAIL_ADDRESS,EMAILS_OR_TEXT_MESSAGES,ENVIRONMENTAL_SCANNING,FITNESS,GAMEPLAY_CONTENT,HANDS,HEAD_MOVEMENT,HEALTH,NAME,OTHER_CONTACT_INFO,OTHER_DATA,OTHER_DIAGNOSTIC_DATA,OTHER_FINANCIAL_INFO,OTHER_USAGE_DATA,OTHER_USER_CONTENT,PAYMENT_INFORMATION,PERFORMANCE_DATA,PHONE_NUMBER,PHOTOS_OR_VIDEOS,PHYSICAL_ADDRESS,PRECISE_LOCATION,PRODUCT_INTERACTION,PURCHASE_HISTORY,SEARCH_HISTORY,SENSITIVE_INFO,USER_IDTHIRD_PARTY_ADVERTISING,DEVELOPERS_ADVERTISING,ANALYTICS,PRODUCT_PERSONALIZATION,APP_FUNCTIONALITY,OTHER_PURPOSESDATA_USED_TO_TRACK_YOU,DATA_LINKED_TO_YOU,DATA_NOT_LINKED_TO_YOU,DATA_NOT_COLLECTEDTest plan
yarn jest src/metadata/apple/tasks/__tests__/data-usage-test.ts— 11 tests covering empty state, single category, multi-category dedupe,dataNotCollectedsentinel, create/delete diff, no-op when matching, and a download → upload round-trip.yarn jest src/metadata/apple— full apple metadata suite, 147 tests pass.yarn typecheckclean for the changed files (the unrelated@expo/eas-build-job/@expo/eas-jsonresolution errors that exist onmainare unaffected).yarn lintclean for the changed files.yarn fmt.metadata:pullagainst an app that already has Privacy Nutrition Labels declared.metadata:pushagainst an app with no labels yet, then verify in App Store Connect.Open questions
@expo/apple-utilsships today. Apple has historically added categories (e.g.ENVIRONMENTAL_SCANNING,HANDS,HEAD_MOVEMENTfor visionOS) without warning, soadditionalProperties: falseon the schema may need to relax over time. If a user's project hits an unknown enum, the schema validator will reject it.DATA_NOT_COLLECTEDsentinel. Apple represents "Data Not Collected" as a single row with no category/purpose andprotection: DATA_NOT_COLLECTED. This PR collapses that into a top-leveldataNotCollected: truetoggle for ergonomics, and re-expands it into the sentinel row on push. I have not been able to verify that this is exactly how the iris endpoint expects it on a brand-new app — there may be a separate "no data" creation flow I'm missing. Worth manual verification before users rely on this.AppDataUsagesPublishState.updateAsync({ published: true })is what asc-cli does, but the iris endpoint is non-standard (it's keyed by app id, not by a publish-state id) and not in the public ASC OpenAPI spec. If Apple changes the contract this is the most likely thing to break.metadata:push/metadata:pullflow. A dedicatedmetadata:privacysubcommand could come later if useful.🤖 Generated with Claude Code