关于 consent-withdrawal
面向产品与隐私团队的 GDPR 同意撤回实施技能,聚焦撤回操作与授予同意同样容易。内容涵盖撤回入口、处理流程、第三方通知及再次同意时的记录要求。
主要功能
- 01衡量撤回与同意的操作难度
- 02设计多种撤回入口
- 03梳理撤回处理流程
- 04通知接收数据的第三方
- 05记录撤回后的再次同意
适用场景
- 01审查网站的同意撤回流程
- 02规划电子邮件退订方式
- 03为第三方共享场景设计撤回通知
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ privacy-data-protection-skills --skill consent-withdrawal安装后在 Claude Code 中输入/consent-withdrawal确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/template.mdreferences/standards.mdworkflows.mdscripts/process.py详细介绍
实现撤回同意
概述
GDPR 第 7(3) 条规定:“数据主体有权随时撤回其同意。撤回同意不影响撤回前基于同意进行处理的合法性。在给予同意之前,数据主体应被告知这一点。撤回同意应与给予同意同样容易。”
“同等便捷”要求是技术上最具挑战性的方面。如果用户在注册时只需勾选一个复选框即可表示同意,那么撤回同意也必须只需相近的操作量即可完成,不能藏在多层导航、设置页面之后,也不能使用暗黑模式。
同等便捷性分析
衡量同意操作的复杂度
量化给予同意所需的操作量,并确保撤回同意达到或超过这一标准:
| 指标 | 衡量方式 | 目标 |
|---|---|---|
| 点击次数 | 从入口到完成所需的点击或轻触次数 | 撤回所需点击次数 <= 给予同意所需点击次数 |
| 页面导航次数 | 从开始到完成之间加载页面的次数 | 撤回所需页面数 <= 给予同意所需页面数 |
| 表单字段数 | 所需输入项的数量 | 撤回所需字段数 <= 给予同意所需字段数 |
| 完成时间 | 在可用性测试中测量 | 撤回所需时间 <= 给予同意所需时间 |
| 认知负荷 | 对说明的理解难度 | 撤回说明同样清晰 |
| 无障碍性 | 仅使用键盘导航所需的步骤 | 键盘操作的无障碍程度相同 |
CloudVault SaaS Inc. 合规性分析
| 操作 | 方式 | 点击次数 | 页面数 | 字段数 |
|---|---|---|---|---|
| 给予同意(注册) | 勾选未选中的复选框 | 1 次点击 | 同一页面 | 0 |
| 撤回同意(偏好中心) | 关闭切换开关并确认 | 2 次点击 | 1 页 | 0 |
| 撤回同意(邮件退订) | 点击退订链接 | 1 次点击 | 1 页 | 0 |
在偏好中心撤回同意需要多点击一次(确认对话框)。这是可以接受的,因为它能防止意外撤回;而且 EDPB 也承认,确认步骤不会违反同等便捷性要求(Guidelines 05/2020,第 116 段)。
单击撤回架构
撤回入口
CloudVault SaaS Inc. 在多个位置提供撤回入口:
- 偏好中心:Settings > Privacy(从任何页面进入需点击 2 次)
- 页脚链接:页面页脚中的“隐私选项”链接(点击 1 次 + 切换开关)
- 邮件退订:每封营销邮件中均提供单击退订链接(点击 1 次,符合 RFC 8058 List-Unsubscribe-Post)
- 账户仪表板:显示当前同意状态的隐私小组件(点击 1 次 + 切换开关)
- API 端点:用于以编程方式撤回同意的 PUT /api/v1/consent/preferences/{subject_id}
撤回处理流水线
TRIGGER: User clicks withdrawal toggle for a specific purpose
│
├─► Step 1: Client-Side
│ ├─ Display confirmation dialog:
│ │ "Withdraw consent for [purpose name]?"
│ │ "This will stop [specific processing description]."
│ │ "You can re-enable this at any time."
│ │ [Cancel] [Withdraw]
│ │
│ └─ User clicks [Withdraw]
│
├─► Step 2: API Call
│ PUT /api/v1/consent/preferences/{subject_id}
│ Body: { decisions: [{ purpose_id: "pur_analytics_01", decision: "withdrawn", mechanism: "toggle_switch" }] }
│
├─► Step 3: Backend Processing (within 100ms)
│ ├─ Create ConsentDecision record (decision: "withdrawn")
│ ├─ Validate request (subject exists, purpose exists, consent was previously granted)
│ ├─ Update consent state cache (Redis/in-memory)
│ └─ Return success response to client
│
├─► Step 4: Cascading Effects (async, within 1 hour)
│ ├─ Dispatch withdrawal events to message queue (Kafka/RabbitMQ/SQS)
│ ├─ Each downstream system receives withdrawal notification:
│ │
│ │ Purpose: "Service Improvement Analytics" (pur_analytics_001)
│ │ ├─ Stop analytics SDK data collection for this user
│ │ ├─ Remove user from analytics cohorts
│ │ └─ Flag existing analytics data for review/deletion
│ │
│ │ Purpose: "Product Update Emails" (pur_marketing_002)
│ │ ├─ Remove user from email marketing lists
│ │ ├─ Add user to suppression list
│ │ ├─ Cancel any scheduled email campaigns for this user
│ │ └─ Confirm with email service provider (ESP)
│ │
│ │ Purpose: "Industry Benchmarking" (pur_benchmarking_003)
│ │ ├─ Stop data sharing with Datalytics Partners Ltd.
│ │ ├─ Notify Datalytics Partners Ltd. via API
│ │ ├─ Request confirmation of processing cessation
│ │ └─ Flag shared data for deletion per DPA terms
│ │
│ └─ Log all propagation events with status tracking
│
├─► Step 5: Downstream Acknowledgment (within 24 hours)
│ ├─ Each downstream system sends acknowledgment
│ ├─ System monitors for missing acknowledgments
│ ├─ Escalation workflow for unacknowledged withdrawals:
│ │ ├─ T+1 hour: Automated retry
│ │ ├─ T+4 hours: Alert to engineering team
│ │ └─ T+24 hours: Escalate to DPO
│ └─ All acknowledgments logged in propagation table
│
└─► Step 6: User Confirmation
├─ UI updates: toggle shows "off" state
├─ Confirmation message: "Consent withdrawn. Processing will stop within 24 hours."
├─ Confirmation email sent to user
└─ Consent receipt updated and available for download
第三方通知协议
如果用户撤回了涉及与第三方共享数据之目的的同意:
-
立即发送 API 通知:通过预先建立的 API 端点向第三方发送结构化通知(在数据处理协议中定义)。
-
通知载荷:
{
"notification_type": "consent_withdrawal",
"subject_reference": "hashed_subject_id",
"purpose_id": "pur_benchmarking_003",
"withdrawal_timestamp": "2026-03-14T10:30:00Z",
"required_action": "cease_processing",
"action_deadline": "2026-03-15T10:30:00Z",
"acknowledgment_required": true,
"controller": "CloudVault SaaS Inc."
}
- 预期响应:
{
"acknowledgment": true,
"received_at": "2026-03-14T10:30:05Z",
"action_status": "processing_cessation_initiated",
"estimated_completion": "2026-03-14T12:00:00Z"
}
- DPA 执行:与 Datalytics Partners Ltd. 签订的数据处理协议(第 8.3 条)要求在 4 小时内确认收到通知,并在 24 小时内停止处理。未能遵守即构成违反 DPA。
撤回后重新征求同意
用户撤回同意后,若想重新给予同意:
- 允许重新给予同意,且应使用与首次征求同意相同的机制
- 同意记录必须显示清晰的审计轨迹:已给予 → 已撤回 → 已给予
- 如果自上次给予同意以来同意文本发生变化,则必须显示新版本
- 不得使用“诱导”或暗黑模式鼓励用户重新给予同意(EDPB Guidelines 05/2020)
- 无需设置合理的冷静期,但可为防止欺诈而实施
主要监管参考
- GDPR 第 7(3) 条——撤回同意的权利;同等便利要求
- GDPR 第 42 段序言——如果撤回同意会造成不利影响,则该同意并非自由作出
- EDPB《05/2020 号同意指南》——第 108–120 段,关于撤回同意
- RFC 8058——为列表邮件标头传递一键操作功能信号(List-Unsubscribe-Post)
- CNIL 执法案例(Google,2022 年 1 月)——因撤回同意流程困难等原因,罚款 1.5 亿欧元
- AEPD 执法案例(CaixaBank,2021 年 1 月)——因撤回机制不足,罚款 600 万欧元
评论
支持 Markdown