隐私与声明 是做什么的?
目的
在两个商店中提供真实、一致的隐私答案,并以代码证据为支撑。大多数隐私拒绝源于不一致:政策说一套,应用做另一套,表单又说了第三套。
前提条件
- 源代码访问权限(应用和后端)以及锁定文件(
pubspec.lock、Podfile.lock、Gradle 依赖、package.json)。 - 当前的隐私政策和条款。
- 掌握每个后端端点和接收用户数据的第三方服务。
1. 构建数据清单(基于代码,而非记忆)
在仓库根目录运行 scripts/scan-sdks.mjs。它会从锁定文件中列出已知 SDK 及其通常涉及的数据类别,并 grep 查找必需理由 API 的使用、权限字符串、广告 ID 和跟踪 API。然后通过阅读网络层和后端来完成清单:
| 数据 | 来源(屏幕 / SDK) | 是否发送到设备外?发送给谁? | 是否关联用户? | 目的 | 保留期限 | 可选? |
|---|
规则:
- “仅在设备上处理”意味着从不发送,包括发送到您自己的服务器。如果数据同步到您的后端,则视为已收集。
- 您的处理者(托管服务、按您指示操作的 AI 提供商、支付 SDK)仍属于“已收集”;它们是否算作“已共享”因商店而异(见下文)。
- 匿名的崩溃报告和使用计数仍属于已收集(诊断/使用数据),通常“不关联”。
将清单保存为 docs/privacy-inventory.md。下面的每个答案都引用清单中的一行。
2. Apple 应用隐私(App Store Connect › App隐私)
- 将清单中的每一行映射到 Apple 的类别(联系信息、健康与健身、用户内容、标识符、购买项目、使用数据、诊断……)、目的、关联 vs 不关联,以及跟踪。
- 跟踪 = 将您的数据与第三方数据关联用于定向广告或广告测量,或与数据经纪商共享。没有广告 SDK 且没有数据经纪商通常意味着“无跟踪”且无需 ATT 提示。
- 选择性披露仅在所有 Apple 条件都满足时适用(不频繁、可选、每次用户主动发起、不涉及跟踪/广告)。极少适用于应用功能。
- 文档:App隐私详情。
3. Google Play 数据安全(政策 › 应用内容 › 数据安全)
- 同一份清单,使用 Play 的分类体系(个人信息、健康和健身、照片和视频、消息、应用活动、应用信息和性能、设备或其他 ID、财务信息……)。
- 共享不包括代表您处理的服务器提供商的传输;如果 SDK 构建跨客户广告画像,则属于共享。
- 临时性:仅在内存中处理,不存储,仅用于实时请求(例如,分析后丢弃的照片)。
- 使用导出为 CSV / 从 CSV 导入:将 CSV 保留在仓库中(
store/data-safety.csv),这样更改可以像代码一样被审查。导入会覆盖所有答案。 - 文档:数据安全。
4. 其他 Play 声明
- 健康应用声明:每个应用都必须完成,即使没有健康功能。文档。
- Health Connect:每个权限提供一个理由;仅请求可见功能使用的权限;提供一个理由活动(
ACTION_SHOW_PERMISSIONS_RATIONALE)链接到政策。Play 可能会要求提供流程的屏幕录制。 - 广告 ID:声明是否使用。如果没有广告/归因 SDK,则声明“否”,并确保没有依赖添加
com.google.android.gms.permission.AD_ID(检查合并后的清单;如果已添加,使用tools:node="remove"移除)。 - 目标受众、内容分级(IARC)、广告、应用访问、新闻、金融功能、政府:根据清单回答。如果任何部分需要登录,请在“应用访问”中提供审核者的凭据。
- 账户删除:见第 8 节。
5. 隐私清单(iOS)
- 向应用目标添加
PrivacyInfo.xcprivacy(模板:templates/PrivacyInfo.xcprivacy)。 - 声明
NSPrivacyTracking、NSPrivacyTrackingDomains、NSPrivacyCollectedDataTypes(与 App Privacy 一致)以及针对应用自身代码使用的每个必需理由 API 类别的NSPrivacyAccessedAPITypes:文件时间戳、系统启动时间、磁盘空间、活跃键盘、UserDefaults。从 Apple 的列表中选择经批准的理由代码。Flutter 应用通过shared_preferences等插件使用 UserDefaults——检查每个插件是否自带清单;添加您的代码和不带清单的插件所使用的类别。 - 构建后,检查 App Store Connect 邮件/构建警告中是否有缺失的清单理由。
- 文档:隐私清单文件、必需理由 API。
6. 出口合规(iOS)
- 在 Info.plist 中设置
ITSAppUsesNonExemptEncryption为false:当应用不使用加密或仅使用豁免加密时适用(例如通过 OS 的 HTTPS、仅用于保护用户自身数据且应用主要功能非安全的标准算法)。设置后可跳过每次构建的问卷。 - 如果您实现或捆绑了专有加密,或者加密是主要功能,则需回答相关问题,并检查是否需要文档或年度自分类报告。
- 这是一个法律分类;如有疑问,请咨询贸易合规顾问。文档:遵守加密出口法规。
7. 年龄分级
- 如实回答当前的 Apple 问卷和 Play IARC 问卷,包括涉及健康/保健主题、AI 聊天或生成内容、用户生成内容以及不受限制的 Web 访问的问题。
- 保持分级与您的条款中的最低年龄以及任何应用内年龄门控一致。如果问卷结果低于您条款的最低年龄,请使用商店的设置选项设置为更高分级,而不是留下不一致。
8. 账户删除
- 应用内:如果用户可以创建账户,则应能在应用内开始删除(账户设置)。仅停用是不够的。访客/自动创建的账户也是如此。允许重新认证或确认,但不得设置不必要的障碍。Apple:提供账户删除。
- 网页 URL(Play):一个无需应用或登录即可访问的页面,列出与应用列表相同的名称,说明如何请求删除、哪些数据被删除、哪些被保留(以及原因),以及任何前置步骤(取消订阅)。文档:Play 账户删除。
- 订阅:删除账户不会取消商店订阅。在删除提示中予以警告并链接到商店的订阅管理。
- 通过 Apple 登录:通过 Apple 登录 REST API 在删除时撤销用户的令牌。
- 第三方:也在处理者处删除用户(例如 RevenueCat 客户、分析/崩溃标识符、邮件列表)。
- 重新认证发布:如果您为删除端点添加重新认证要求,请同时发布处理新响应的应用版本和后端更改,或为旧应用版本保留旧行为。
- 在应用、政策、商店表单、网页等所有路径中使用统一的措辞,例如“个人资料 › 删除账户”。
9. AI 功能
- Apple 5.1.2(i):披露个人数据与第三方共享的情况,包括第三方 AI,并事先获得明确许可。
- 首次使用 AI 功能前:提供一个简短的同意表单,注明提供商和角色(“由 <AI 提供商> 处理以生成答案”)、发送的内容、不用于训练模型(仅当提供商针对您的计划如此声明时)、保留期限(提供商和您的)。在设置中提供收回同意的开关。
- 政策措辞:AI 提供商作为处理者/服务提供商按照您的指示行事;列出其位置和保留期限。
- 商店表单:AI 输入(消息、照片、文本)属于已收集数据(用户内容);当提供商是处理者时,在 Play 中通常不算“共享”。
- 考虑:针对健康或财务相关的 AI 答案添加“非专业建议”声明,并为危机主题定义安全的响应。
10. 健康数据
- 切勿将 HealthKit / Health Connect 数据发送给 AI 提供商或其他第三方。 Apple (5.1.3) 限制健康数据的使用和披露;Health Connect 的政策也限制传输。最简单的合规设计:从 Apple Health / Health Connect 读取的数据保留在设备上(或仅存储于用户自己的账户存储中,需披露),调用 AI 的功能仅使用用户在应用中输入的数据。
- 不要将健康数据用于广告或营销;不要将其存储在 iCloud 中。
- Info.plist 使用字符串(
NSHealthShareUsageDescription、NSHealthUpdateUsageDescription)必须说明实际用途。如果字符串写“绝不与第三方共享”,代码必须保证这一点。 - 在代码中强制执行:AI 调用的请求构建器接受一个明确的字段允许列表;添加一个测试,在 AI 载荷中出现来自健康源的数据时失败。
需要人工批准的决策点
每个表单的最终答案(账户持有人需承担法律责任)、出口合规分类、年龄分级、AI 提供商及其数据条款、任何改变健康数据离开设备方式的决策。
验证
- 每个表单答案引用清单中的一行;清单引用代码。
- 差异检查:隐私政策 ↔ App Privacy ↔ Data safety CSV ↔ 应用内同意文本 ↔ Info.plist 字符串。无矛盾。
- 测试:删除一个测试账户;确认后端行、处理者记录和认证用户已消失;网页删除页面在未登录状态下可访问。
- 构建无隐私清单警告。
常见陷阱
- 政策中写“数据绝不离开设备”,但同步或 AI 功能却在发送数据。
- 在表单中遗漏自己的匿名崩溃/使用报告。
- 依赖项静默添加了 AD_ID 权限。
- 健康数据通过包含“我们所知的一切”的“上下文”构建器流入 AI 提示。
- 删除路径在应用、政策和商店表单中命名不同。
- 年龄分级设为 4+,而条款要求 16+。