隐私与 GDPR 对齐
本页提供:PII 字段标注与加密存储代码示例、用户同意记录数据结构与查询示例、数据主体权利 API endpoint 设计(删除/导出/修正)、可直接使用的 DPIA 检查清单表格,以及 DPA/DPIA 核对清单实验室。
按处理目的、数据类别、留存期、接收方与子处理者列出表格;SKILL 明确模型不得编造法律依据,需引用组织已采纳的政策条款编号或留空待填。
对访问、删除、可携带等请求,输出应映射到现有 API 或工单流程,并标注 SLA 与身份校验要求;默认最小化日志中的个人数据。
合规主流程(ROPA → DPA → DPIA)
[ 盘点:处理活动 / 系统 / 数据流 ]
│
▼
┌─────────────┐ 表格:目的、法律依据(占位)、类别、留存、接收方
│ ROPA 草稿 │──── 缺口标「需法务/DPO」,不自动写「合规通过」
└─────────────┘
│
▼
┌─────────────┐ 处理者:书面 DPA + 附件(标的、期限、子处理者变更)
│ DPA 对齐 │──── 控制者:记录与处理者的指令边界、分包与审计条款占位
└─────────────┘
│
▼
┌─────────────┐ 高风险处理 → 启动 DPIA;必要时咨询监管机构(占位)
│ DPIA 评估 │──── 记录必要性、风险与缓解措施;保留版本与评审人
└─────────────┘
│
▼
┌─────────────┐ 主体请求 → 工单/API 映射;跨境 → SCC/BCR/本地化选项
│ 权利 / 传输 │
└─────────────┘
│
▼
… 重大不确定性 → 升级 DPO / 法务(证据与草稿一并附上)
Agent 输出的是草稿与核对清单,最终法律效力与条款选用必须由 DPO、法务或外部顾问确认。
PII 字段标注、加密存储与用户同意实现
PII 字段标注(数据模型层面)
// Prisma schema — 使用注释标注 PII 字段
model User {
id String @id @default(cuid())
/// @pii:direct email 地址,保留期 3 年
email String @unique
/// @pii:direct 手机号,加密存储
phone String? // 存储前 AES-256-GCM 加密
/// @pii:quasi 生日,与其他字段组合可重识别
birthDate DateTime?
createdAt DateTime @default(now())
}
// PII 加密存储(Node.js — AES-256-GCM)
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
const KEY = Buffer.from(process.env.PII_ENCRYPTION_KEY!, 'base64'); // 32 bytes
export function encryptPII(plaintext: string): string {
const iv = randomBytes(12);
const cipher = createCipheriv('aes-256-gcm', KEY, iv);
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
return Buffer.concat([iv, tag, encrypted]).toString('base64');
}
export function decryptPII(ciphertext: string): string {
const buf = Buffer.from(ciphertext, 'base64');
const iv = buf.subarray(0, 12);
const tag = buf.subarray(12, 28);
const encrypted = buf.subarray(28);
const decipher = createDecipheriv('aes-256-gcm', KEY, iv);
decipher.setAuthTag(tag);
return decipher.update(encrypted) + decipher.final('utf8');
}
// 访问日志:记录谁在何时访问了哪个用户的 PII
await prisma.piiAccessLog.create({
data: {
accessorId: currentUser.id,
targetUserId: targetUser.id,
fields: ['email', 'phone'],
purpose: 'customer_support_ticket_#12345',
timestamp: new Date(),
}
});
用户同意记录数据结构与查询
// 同意记录表结构(SQL)
CREATE TABLE consent_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
purpose VARCHAR(100) NOT NULL, -- 'marketing_email', 'analytics', 'third_party_sharing'
version VARCHAR(20) NOT NULL, -- 隐私政策版本 '2025-01-01'
granted BOOLEAN NOT NULL,
granted_at TIMESTAMPTZ,
withdrawn_at TIMESTAMPTZ,
ip_address INET, -- 记录操作来源(本身为 PII,需处理)
user_agent TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 查询用户当前有效同意(最新版本且未撤回)
SELECT purpose, granted, version, granted_at
FROM consent_records
WHERE user_id = $1
AND withdrawn_at IS NULL
ORDER BY granted_at DESC;
- 默认在示例中使用假名化或哈希,不用真实用户数据。
- 法律依据列只填组织已采纳的条款引用或
<需确认>,勿臆造法条适用结论。
DPA(处理者合同)要点
标准合同模块通常包含:处理标的与期限、性质与目的、个人数据类型与数据主体类别、控制者义务、处理者按书面指令处理、保密、安全措施、分包与子处理者机制、协助响应主体权利、协助事故通知、删除或返还、审计与证明、法律责任等。具体条文以贵司法辖区模板为准。
控制者侧核对
- 处理范围与产品功能一致;变更走变更管理。
- 子处理者清单与通知/反对机制(若适用)有占位链接。
- 传输附件(如 SCC)版本与签署状态占位。
处理者侧核对
- 仅按文档化指令处理;无指令不扩展用途。
- 可应要求提供安全实施说明与审计配合方式(占位)。
- 终止时删除/返还的时限与证明方式。
DPIA 触发与文档结构
当出现系统性大规模监控、自动化决策与画像、敏感数据大规模处理、公共可访问区域系统性监控等情形时,应评估是否必须做 DPIA(以监管指南与内部政策为准)。文档宜包含:处理描述、必要性/合比例性分析、利益相关方咨询记录占位、风险识别、已有与拟增缓解措施、残余风险与是否需报监管。
- 与 ROPA 交叉引用:同一处理活动在 ROPA 行与 DPIA 节之间可互链。
- 重大缺口标记为需 DPO 评审,不输出「已通过 DPIA」之类结论。
数据主体权利 API 设计
// Express.js — 数据主体权利 API endpoints
// 1. 数据访问/导出(Right to Access & Portability)
// GET /api/gdpr/data-export
router.get('/data-export', authenticateUser, async (req, res) => {
const userId = req.user.id;
const userData = await collectUserData(userId); // 聚合所有 PII 字段
const exportData = {
exported_at: new Date().toISOString(),
format_version: '1.0',
user_id: userId,
personal_data: {
profile: userData.profile,
orders: userData.orders,
consents: userData.consents,
}
};
// 加密传输,日志记录导出操作
await auditLog('DATA_EXPORT', userId, req.ip);
res.json(exportData);
// SLA: 30 天内响应(GDPR 要求)
});
// 2. 数据删除(Right to Erasure)
// DELETE /api/gdpr/erasure
router.delete('/erasure', authenticateUser, async (req, res) => {
const userId = req.user.id;
// 检查是否有法定保留义务(如税务记录 7 年)
const legalHold = await checkLegalHold(userId);
if (legalHold.hasHold) {
return res.status(409).json({
error: 'LEGAL_HOLD',
reason: legalHold.reason,
retain_until: legalHold.until,
});
}
// 软删除 + 脱敏(非立即物理删除)
await prisma.user.update({
where: { id: userId },
data: {
email: `deleted-${userId}@erased.invalid`,
phone: null,
deletedAt: new Date(),
erasureRequestedAt: new Date(),
}
});
await auditLog('ERASURE_COMPLETED', userId, req.ip);
res.json({ status: 'erasure_scheduled', completed_within: '30_days' });
});
// 3. 数据修正(Right to Rectification)
// PATCH /api/gdpr/rectification
router.patch('/rectification', authenticateUser, validateBody, async (req, res) => {
const { field, new_value, reason } = req.body;
const ALLOWED_FIELDS = ['phone', 'address', 'name'];
if (!ALLOWED_FIELDS.includes(field)) {
return res.status(400).json({ error: 'FIELD_NOT_RECTIFIABLE' });
}
await prisma.user.update({
where: { id: req.user.id },
data: { [field]: field === 'phone' ? encryptPII(new_value) : new_value }
});
await auditLog('RECTIFICATION', req.user.id, req.ip, { field, reason });
res.json({ status: 'updated' });
});
- 可携带:导出格式与范围以产品能力为准,注明是否包含派生特征。
- 日志与客服工具默认最小化展示个人数据。
跨境传输与本地化占位
列出数据流出目的地、机制(例如 SCC、BCR、充分性认定、本地化部署、其他法定路径),以及生效状态与责任人占位;中国区与欧盟区并行时分别列栏,避免混为一谈。
- 子处理者链路:每一跳接收方与法律依据各一行。
- 模型不得虚构已签署的 SCC 编号或监管机构批复。
个保法与 GDPR 术语对照
并行合规时区分术语:例如「同意」「单独同意」与 GDPR 下 consent 的构成要件并不相同;「合法权益」与个保法下的处理合法性基础需分别引用各自框架,并在文档中注明适用法域。
- 同一段落不要无说明地混用两法域概念。
- 对外隐私声明与对内 ROPA 可使用对照表链接(占位)。
DPA / DPIA 核对清单实验室
勾选常见核对项,生成可粘贴到工单或 Confluence 的 Markdown 清单;未勾选项以 [ ] 列出便于现场补全。
生成内容仅供内部核对;条款选用、签署与监管报送须由法务 / DPO 确认。占位统一使用 <需确认>。
---
name: gdpr-privacy-cn
description: 实现 GDPR 数据主体权利 API,标注 PII 字段,记录同意,维护 ROPA/DPIA
---
# 步骤
1. 在数据模型中标注 PII 字段(@pii:direct / @pii:quasi),注明保留期
2. 实现 PII 加密存储:AES-256-GCM,密钥从 KMS/Secrets Manager 获取
3. 实现访问日志:记录 accessorId、targetUserId、fields、purpose
4. 实现同意记录表:purpose、version、granted、withdrawn_at
5. GET /api/gdpr/data-export:聚合全部 PII,加密传输,审计日志
6. DELETE /api/gdpr/erasure:检查 legal hold → 软删除 + 脱敏 → 审计日志
7. PATCH /api/gdpr/rectification:字段白名单校验 → 更新 → 审计日志
8. DPIA 触发判断:大规模监控 / 自动化决策 / 特殊类别数据 → 启动 DPIA
9. ROPA 草稿:处理目的、法律依据(占位 <需确认>)、数据类别、删除期限
10. DPA 核对:处理者书面 DPA、子处理者清单、指令边界、审计权利
11. 跨境传输:SCC/BCR/充分性认定 — 机制与生效状态列表,由法务确认
12. Agent 禁止编造法律依据,重大不确定性升级 DPO/法务
# 禁止
- 禁止编造法律依据或条款适用结论
- 禁止输出「已通过 DPIA」结论,必须由 DPO 终审
- 禁止日志中记录未脱敏的完整 PII