Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: privacy manifest files #677

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CustomerIODataPipelines.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ Pod::Spec.new do |spec|
# spec.osx.deployment_target = "10.15"
# spec.tvos.deployment_target = '13.0'

spec.source_files = "Sources/DataPipeline/**/*"
spec.exclude_files = "Sources/**/*{.md}"
path_to_source_for_module = "Sources/DataPipeline"
spec.source_files = "#{path_to_source_for_module}/**/*{.swift}"
spec.resource_bundle = {
"#{spec.module_name}_Privacy" => "#{path_to_source_for_module}/Resources/PrivacyInfo.xcprivacy"
}
spec.module_name = "CioDataPipelines" # the `import X` name when using SDK in Swift files

spec.dependency "CustomerIOCommon", "= #{spec.version.to_s}"
Expand Down
8 changes: 6 additions & 2 deletions CustomerIOMessagingInApp.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ Pod::Spec.new do |spec|
# spec.osx.deployment_target = "10.15"
# spec.tvos.deployment_target = '13.0'

spec.source_files = "Sources/MessagingInApp/**/*"
spec.exclude_files = "Sources/**/*{.md}"
path_to_source_for_module = "Sources/MessagingInApp"
spec.source_files = "#{path_to_source_for_module}/**/*{.swift}"
spec.resource_bundle = {
"#{spec.module_name}_Privacy" => "#{path_to_source_for_module}/Resources/PrivacyInfo.xcprivacy"
}

spec.module_name = "CioMessagingInApp" # the `import X` name when using SDK in Swift files

spec.dependency "CustomerIOCommon", "= #{spec.version.to_s}"
Expand Down
8 changes: 6 additions & 2 deletions CustomerIOMessagingPushAPN.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ Pod::Spec.new do |spec|
# spec.osx.deployment_target = "10.15"
# spec.tvos.deployment_target = '13.0'

spec.source_files = "Sources/MessagingPushAPN/**/*"
spec.exclude_files = "Sources/**/*{.md}"
path_to_source_for_module = "Sources/MessagingPushAPN"
spec.source_files = "#{path_to_source_for_module}/**/*{.swift}"
spec.resource_bundle = {
"#{spec.module_name}_Privacy" => "#{path_to_source_for_module}/Resources/PrivacyInfo.xcprivacy"
}

spec.module_name = "CioMessagingPushAPN" # the `import X` name when using SDK in Swift files

spec.dependency "CustomerIOMessagingPush", "= #{spec.version.to_s}"
Expand Down
8 changes: 6 additions & 2 deletions CustomerIOMessagingPushFCM.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ Pod::Spec.new do |spec|
# spec.osx.deployment_target = "10.15"
# spec.tvos.deployment_target = '13.0'

spec.source_files = "Sources/MessagingPushFCM/**/*"
spec.exclude_files = "Sources/**/*{.md}"
path_to_source_for_module = "Sources/MessagingPushFCM"
spec.source_files = "#{path_to_source_for_module}/**/*{.swift}"
spec.resource_bundle = {
"#{spec.module_name}_Privacy" => "#{path_to_source_for_module}/Resources/PrivacyInfo.xcprivacy"
}

spec.module_name = "CioMessagingPushFCM" # the `import X` name when using SDK in Swift files

spec.dependency "CustomerIOMessagingPush", "= #{spec.version.to_s}"
Expand Down
20 changes: 16 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,30 +82,42 @@ let package = Package(
// Data Pipeline
.target(name: "CioDataPipelines",
dependencies: ["CioInternalCommon", "CioTrackingMigration", .product(name: "Segment", package: "Segment")],
path: "Sources/DataPipeline"),
path: "Sources/DataPipeline",
resources: [
.process("Resources/PrivacyInfo.xcprivacy"),
]),
.testTarget(name: "DataPipelineTests",
dependencies: ["CioDataPipelines", "SharedTests"],
path: "Tests/DataPipeline"),

// APN
.target(name: "CioMessagingPushAPN",
dependencies: ["CioMessagingPush"],
path: "Sources/MessagingPushAPN"),
path: "Sources/MessagingPushAPN",
resources: [
.process("Resources/PrivacyInfo.xcprivacy"),
]),
.testTarget(name: "MessagingPushAPNTests",
dependencies: ["CioMessagingPushAPN", "SharedTests"],
path: "Tests/MessagingPushAPN"),
// FCM
.target(name: "CioMessagingPushFCM",
dependencies: ["CioMessagingPush", .product(name: "FirebaseMessaging", package: "Firebase")],
path: "Sources/MessagingPushFCM"),
path: "Sources/MessagingPushFCM",
resources: [
.process("Resources/PrivacyInfo.xcprivacy"),
]),
.testTarget(name: "MessagingPushFCMTests",
dependencies: ["CioMessagingPushFCM", "SharedTests"],
path: "Tests/MessagingPushFCM"),

// Messaging in-app
.target(name: "CioMessagingInApp",
dependencies: ["CioInternalCommon"],
path: "Sources/MessagingInApp"),
path: "Sources/MessagingInApp",
resources: [
.process("Resources/PrivacyInfo.xcprivacy"),
]),
.testTarget(name: "MessagingInAppTests",
dependencies: ["CioMessagingInApp", "SharedTests"],
path: "Tests/MessagingInApp"),
Expand Down
79 changes: 79 additions & 0 deletions Sources/DataPipeline/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
Docs for this section: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests
This section is describing what information our SDK collects about the app user.

It's my understanding that this section is for what our SDK collects automatically, not the data a customer passes to our SDK. Therefore, if a piece of data is passed to our SDK, use `false`.
Customers must create their own privacy file for what their app collects and provide that to Apple. That's where customers report what data they are passing to our SDK.
-->
<key>NSPrivacyCollectedDataTypes</key>
<array>

<!--
Section for SDKs that capture "Such as screen name, handle, account ID, assigned user ID, customer number, or other user- or account-level ID that can be used to identify a particular user or account."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have to specify the things we capture, like app name etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you do not need to specify what you capture. Instead specify what categories that you capture.

Copy link
Contributor Author

@levibostian levibostian Apr 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have misunderstood your question.

Looking at the docs for NSPrivacyCollectedDataTypes, I do not see anything in there regarding app name, app version.

If you see a category in this apple doc that is missing in this file, please mention the missing category in our notion doc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was based on this where it mentions adding custom data types but maybe we can skip these as I am unsure.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to skipping adding any custom data types for now. Apples documents aren't always the most clear, so it will be tough to determine what qualifies as a custom data type that we might need to declare.

-->
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/> <!-- because of anonymous profiles, linking to a person is optional -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment in notion about it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am keeping this value as-is until we give others on team time to read documentation and give suggestions for this value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since to utilize basically any functionality of Customer.io, we need to link usage data to a user typically email or a device. This is the rational for marking this as true. If we mark this as false, it means that Customer.io does not have any data linked to a user anywhere in our systems.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment on notion too. We only need a profile to function, so even if they use aliases to create profiles, sending push notifications and in-app messages should still be possible based on the data linked to the user, which I believe aligns with Apple's privacy details. For sending email, it's true that linking an actual email is necessary, but we don’t force it and it likely falls under the customer app's privacy? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://developer.apple.com/app-store/app-privacy-details/#linked-data

Additionally, in order for data not to be linked to a particular user’s identity, you must avoid certain activities after collection:
You must not attempt to link the data back to the user’s identity.
You must not tie the data to other datasets that enable it to be linked to a particular user’s identity.

I believe we do both of these activities, which I why I tend to go for true

Copy link
Contributor Author

@levibostian levibostian Apr 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR thread has been discussed in a Notion comment.
I suggest reviewing this updated section in Notion and comment there if you have more feedback.

<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>

<!--
Section for SDKs that capture "Such as app launches, taps, clicks, scrolling information, music listening data, video views, saved place in a game, video, or song, or other information about how the user interacts with the app."
-->
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>
</array>

<!--
Document on this section: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api
Documents if our SDK uses certain system calls and why. Prevents SDK using fingerprinting.
-->
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>

<!-- "third-party SDK uses data for tracking as defined under the App Tracking Transparency framework."
See section "Asking permission to track" in this webpage:
https://developer.apple.com/app-store/user-privacy-and-data-use/
-->
<key>NSPrivacyTracking</key>
<false/>

<!-- Because we use NSPrivacyTracking=false, this section is not required.
<key>NSPrivacyTrackingDomains</key>
-->
</dict>
</plist>
41 changes: 41 additions & 0 deletions Sources/MessagingInApp/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
See DataPipelines module for documentation of this file. Including resources for each section to learn more.
-->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>
</array>

<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>

<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
43 changes: 43 additions & 0 deletions Sources/MessagingPushAPN/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
See DataPipelines module for documentation of this file. Including resources for each section to learn more.

**Important** - Keep this file in sync with other push modules in SDK.
-->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>
</array>

<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>

<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
43 changes: 43 additions & 0 deletions Sources/MessagingPushFCM/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
See DataPipelines module for documentation of this file. Including resources for each section to learn more.

**Important** - Keep this file in sync with other push modules in SDK.
-->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
</array>
</dict>
</array>

<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>

<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>