隐私与 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 清单;未勾选项以 [ ] 列出便于现场补全。

DPA 附件常见条目
DPIA 文档结构

生成内容仅供内部核对;条款选用、签署与监管报送须由法务 / 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

返回技能库 更多技能入口