ITMS-91064: NSPrivacyTracking and NSPrivacyTrackingDomains must agree in every privacy manifest (true needs domains, domains need true); check, scan and privacy-manifest fail on either mismatch with the exact ITMS text; App Privacy tracking no longer demands the app manifest's true: SDK manifests that declare tracking (Pods, frameworks, SwiftPM, Carthage, plugins, the built IPA) are info, known tracking SDKs info, else a warning; privacy-manifest --propose writes true only with appPrivacy.trackingDomains; apple upload checks every manifest in the IPA (XML or binary) before any network call, apple build after the export. Pitfall 29
This commit is contained in:
parent
b7bfe89151
commit
c8213be2b6
19 changed files with 631 additions and 44 deletions
|
|
@ -169,7 +169,7 @@ export function proposeDeclarations(p: ProjectFacts, c: ShipConfig | null, confi
|
|||
if (attStr) items.push({ area: 'att', what: 'NSUserTrackingUsageDescription', value: String(attStr.value).slice(0, 80), status: 'detected', evidence: [{ ...attStr.at, text: 'NSUserTrackingUsageDescription' }] });
|
||||
else if (trackers.length || attReq.length) items.push({ area: 'att', what: 'NSUserTrackingUsageDescription', value: 'needed if anything tracks, e.g. "Your data is used to show ads that fit your interests."', status: 'ask', evidence: [] });
|
||||
if (attReq.length) items.push({ area: 'att', what: 'ATT request', value: 'found', status: 'detected', evidence: attReq });
|
||||
if (trackers.length || attReq.length) items.push({ area: 'appPrivacy', what: 'trackingDomains', value: 'the SDKs\' tracking domains (from each SDK\'s privacy manifest)', status: 'ask', evidence: [] });
|
||||
if (trackers.length || attReq.length) items.push({ area: 'appPrivacy', what: 'trackingDomains', value: 'only the domains the app\'s OWN code sends tracking data to (usually none: SDK domains stay in each SDK\'s manifest)', status: 'ask', evidence: [] });
|
||||
|
||||
// privacy manifest
|
||||
if (p.ios) {
|
||||
|
|
@ -183,7 +183,14 @@ export function proposeDeclarations(p: ProjectFacts, c: ShipConfig | null, confi
|
|||
items.push({ area: 'privacyManifest', what: cat, value: have?.length ? `declared: ${have.join(', ')}` : `add with a reason: ${def.note}`, status: have?.length ? 'detected' : 'ask', evidence: h });
|
||||
}
|
||||
const m = p.privacyManifests[0];
|
||||
if (tracking !== null || m) items.push({ area: 'privacyManifest', what: 'NSPrivacyTracking', value: tracking ? 'true' : m ? String(m.tracking) : '?', status: tracking ? 'detected' : 'ask', evidence: m ? [{ file: m.path, line: 1, text: 'PrivacyInfo.xcprivacy' }] : [] });
|
||||
// the app's own manifest says true only with app-level tracking domains: tracking by an SDK is declared in the SDK's
|
||||
// manifest, and true with an empty NSPrivacyTrackingDomains is refused at upload (ITMS-91064)
|
||||
const appDomains = c?.appPrivacy?.trackingDomains ?? [];
|
||||
if (tracking !== null || m) items.push({ area: 'privacyManifest', what: 'NSPrivacyTracking',
|
||||
value: tracking && appDomains.length ? `true (NSPrivacyTrackingDomains: ${appDomains.join(', ')})`
|
||||
: tracking ? 'false in the app\'s manifest (the tracking SDKs declare it in their own manifests; true needs the app\'s own NSPrivacyTrackingDomains, else ITMS-91064)'
|
||||
: m ? String(m.tracking) : '?',
|
||||
status: tracking ? 'detected' : 'ask', evidence: m ? [{ file: m.path, line: 1, text: 'PrivacyInfo.xcprivacy' }] : [] });
|
||||
if (diff.length) items.push({ area: 'privacyManifest', what: 'NSPrivacyCollectedDataTypes', value: uniq(diff.map(d => d.apple.split(' / ')[1]!)).join(', '), status: 'detected', evidence: diff.flatMap(d => d.evidence).slice(0, 1), note: 'the app\'s own collection; SDKs declare theirs in their manifests' });
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue