- 处理: 74 个 .md 文件 - 跳过: 0 个(无已存在的 front matter) - 异常: 3 个(H1 缺失,用文件名兜底) - plans/PRISM/.research/readmes/3d-llm.md - plans/PRISM/.research/readmes/openmask3d.md - plans/PRISM/.research/readmes/openscene.md
32 KiB
title, date, draft, tags, categories
| title | date | draft | tags | categories | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| CrowdRoom · 隐私设计(v0.1) | 2026-05-20 | false |
|
|
CrowdRoom · 隐私设计(v0.1)
本章是 CrowdRoom 的「合规底座」,承接
00_overview.md§8 风险 RK-3(UGC 审核)、RK-4(隐私脱敏),并对03_ios_app_plan.md§11 移交的 P-1 ~ P-6 与04_web_app_plan.md§13 移交的 P-W-1 / P-W-2 / P-W-7 三条隐私强相关契约逐一拍板。治理与社区规则(含 P-W-3 ~ P-W-6)见10_governance.md。本章不重复
01_data_schema.md§3.5redactions表 DDL 与 §3.5 RLS 策略——所有「实现位置」均回指既有章节。本章核心论断:CrowdRoom 用「端侧脱敏 + 公共数据 CDN 全裸 / 私有数据 RLS 全锁」两段式架构把隐私风险压缩到「用户主动框选发布」这一个决策点上;服务端永不二次检测人脸、永不持有 GPS 精确坐标、永不把
redactions区域明文回流到第三方。
1. 隐私设计五原则
排列顺序即决策优先级。当任意两条原则冲突时,编号小的优先。
| # | 原则 | 一句话定义 | 落地证据 |
|---|---|---|---|
| PR-1 | 端侧优先脱敏 | 任何可能含人脸/人体的栅格数据,必须在 iPhone 离开 App 进程前完成 CIGaussianBlur 不可逆改写;服务端永不对原始贴图做二次人脸检测。 |
03_ios_app_plan.md §4 端侧脱敏管线 + iOS-X1 契约 |
| PR-2 | 最小数据采集 | 不申请非必要权限:不录音、不读相册、不收 IDFA、不收精确 GPS。能用 5 km 城市标签解决的就不上经纬度,能用客户端聚合的就不收原始事件。 | §3.3 位置生命周期 + §9 第三方 SDK 清单 |
| PR-3 | 用户可控 | 所有「涉及隐私的开关」默认朝隐私最严方向(私有可见性、不打位置标签、不保留备份),用户可在「我的 → 隐私」一处看完全部并即时切换。 | §7 默认值清单 |
| PR-4 | 默认私有,发布显式 | 房间记录在数据库里初始 visibility='private'(与 01_data_schema.md §3.2 rooms.visibility 默认值绑定),用户必须在上传表单主动勾选「公开」才会进入发现流——零误公开。 |
03_ios_app_plan.md §1.2 UploadForm 页 |
| PR-5 | 可被遗忘 | 用户「注销账号并删除全部数据」是一个承诺 30 天内完成的端到端流程,不存在「冷备份永久保留」的暗逻辑;公开 Remix 的几何快照按 §8 保留期表自动迁移到 tombstone 后清理。 | §3.1 P-4 + §8 删除时间表 |
若未来运营方提出「为了广告变现请放开 IDFA」,本五条原则即「先改原则再改代码」的硬门槛——任何放开必须更新本章并在
00_overview.md顶部 changelog 留痕。
2. 数据流隐私视图
红/黄/绿 = 该节点持有数据的隐私敏感度(红 = 含可识别人脸/位置,黄 = 含间接可识别信息,绿 = 已脱敏或仅元数据)。第三方可访问性以「✓ 外部可见」与「✗ 仅内部」标注。
graph LR
subgraph 设备_iPhone
A1[RoomPlan 原始 RGB Depth · 红 · ✗ 仅内部]
A2[Vision 人脸 bbox · 红 · ✗ 仅内部]
A3[CIGaussianBlur 改写贴图 · 绿 · ✗ 仅内部]
A4[redactions list 数组 · 黄 · ✗ 仅内部]
end
subgraph Supabase_Storage
B1[private rooms id source usdz · 绿 已脱敏 · ✗ JWT 锁]
B2[private rooms id source roomplan json · 黄 含尺寸 · ✗ JWT 锁]
B3[public rooms id canonical glb · 绿 · ✓ CDN]
B4[public rooms id thumbnail webp · 绿 · ✓ CDN]
end
subgraph Supabase_Postgres
C1[rooms 表 location_label 城市级 · 黄 · ✓ RLS public]
C2[redactions 表 region 坐标 · 红 · ✗ RLS owner only]
C3[users 表 handle email · 黄 · ✓ handle 公开 email RLS]
end
subgraph 转码_Worker
D1[usdz to glb 流水 · 绿 仅几何 · ✗ service role]
D2[Worker 日志 含失败堆栈 · 黄 · ✗ Sentry 关联]
end
subgraph Web_浏览端
E1[R3F 渲染 glb manifest · 绿 · ✓ 公开]
E2[viewState 分享 token · 绿 仅开关 · ✓ URL 上]
E3[OG 图缓存 1200x630 · 绿 · ✓ CDN]
end
subgraph 第三方_SDK
F1[Sentry Issue 含堆栈 · 黄 · ✗ 内部账号]
F2[PostHog 事件 已脱敏 · 黄 · ✗ 内部账号]
F3[CloudFlare Vercel 边缘缓存 · 绿 仅公开资产 · ✓ 全球节点]
end
A1 --> A2 --> A3
A3 --> B1
A2 --> A4 --> C2
A1 -.丢弃.-> X[本地不留底]
B1 --> D1 --> B3 --> E1
D1 --> B4 --> E3
C1 --> E1
E1 --> E2
D2 -.错误才上报.-> F1
E1 -.事件聚合.-> F2
B3 --> F3
读图要点:
- 红色节点(A1/A2/C2)永不离开「设备」或「Supabase 内网 + service_role」边界
- 黄色节点(A4/B2/C1/C3/D2/F1/F2)受 RLS 或 Sentry 项目权限保护,不直接对公网开放
- 绿色节点(A3/B3/B4/D1/E1/E2/E3/F3)走公开 CDN,但在到达此节点前已经过端侧脱敏 + 转码 Worker 几何重打包,不含任何原始 RGB
- 唯一一处「原始数据 → 公开」的转换发生在 端侧脱敏管线(A3 出口)——这条转换链由
03_ios_app_plan.md§4 强约束
3. 三类敏感数据全生命周期
3.1 人脸 / 人体
| 阶段 | 行为 | 是否离设备 |
|---|---|---|
| 采集 | RoomPlan 在 ARKit 帧上累积 RGB 贴图 | 否 |
| 检测 | VNDetectFaceRectanglesRequest Revision 3 跑在 Neural Engine,输出归一化 bbox |
否 |
| 脱敏 | CIGaussianBlur radius=18 整图模糊 + 蒙版合成回原图,bbox 区域不可逆改写到磁盘 |
否 |
| 审计写入 | bbox 累积为 redactions[] 数组(kind='face', space='texture', method='gaussian_blur_r18'),仅作合规审计 |
否 |
| 上传 | redactions[] 随 upload-complete POST 到 Supabase,写入 redactions 表 |
是(坐标) |
| 服务端 | 不二次检测人脸(成本与合规权衡:再次解码 RGB 反而提高数据持有等级);Worker 只读已脱敏 .usdz | — |
| 用户可见 | 「我的房间 → 该房间 → 隐私详情」展示「本次扫描共检测到 N 张人脸,全部已模糊」;点开可看缩略图列表(每张含人脸 bbox 轮廓);提供「申请重做脱敏」按钮(走人工流) | 否(owner-only) |
| 保留 | 与 room_versions 同生命周期(见 §8) |
|
| 删除 | rooms 硬删 → room_versions cascade → redactions cascade |
— |
关键决策:服务端不复检而是信任端侧。理由:① 复检意味着服务端必须解码原始 RGB,反而把数据持有等级从「绿」升回「红」;② Vision Revision 3 在 1024² 贴图上召回 ≥ 95%(Apple 官方 benchmark),漏检的极端 case 走 §4 P-2 的用户复议路径解决。
3.2 可识别地标 / 文档 / 屏幕内容
| 阶段 | 行为 |
|---|---|
| MVP 不做自动检测 | OCR + 地标识别会把数据流从「人脸」一类扩展到「文字 + 品牌 logo + 证件号」,模型大小与误报代价远超 MVP 8 周窗口承受 |
| 替代方案:手动框选 | iOS App 在「扫描完成预览页」(03_ios_app_plan.md §1.2 ScanReview)提供 UIScrollView 缩略图墙,用户长按贴图后框选矩形;Web Remix 编辑器(04_web_app_plan.md §7)也提供同款工具 |
| 数据落库 | 框选区域写入 redactions[] with kind='manual', method='gaussian_blur_r18';Worker 在转码时拿到该数组,对应 mesh 贴图做二次模糊(这是 §3.1 之外服务端唯一对栅格做的隐私操作,且仅对用户主动标注的区域) |
| 用户提示 | 上传表单底部固定文案:「请确保扫描中没有信用卡 / 身份证 / 屏幕显示的私人信息 / 他人住址快递单。如有,请使用上一页『手动模糊』工具框选。」 |
| 复议 | 房间发布后,owner 在详情页底部「隐私审查」入口可追加框选 → 触发 02_api_contract.md §3.2 的 transcode-retry 重跑 |
3.3 地理位置
| 阶段 | 行为 |
|---|---|
| 权限文案 | NSLocationWhenInUseUsageDescription「CrowdRoom 可选使用你的位置,仅为给你扫描的房间打上『城市』标签」(03_ios_app_plan.md §8.1) |
| 精度截断 | iOS App 拿到 CLLocation 后,立即用 reverse-geocoding 得到城市名(CLPlacemark.locality),原始经纬度不进入 App 持久层、不进入 SwiftData、不进入网络请求 body |
| 服务端存储 | rooms.location_label TEXT(如 '上海'、'San Francisco'),没有 lat/lng 列。即便日后想做「地图视图」也必须用城市质心而非用户原始坐标 |
| 公开可见性 | 城市标签默认随房间 visibility 走(public 房间公开城市;private/unlisted 房间该字段对外不可见,由 RLS 保证) |
| 关闭 | 用户在「我的 → 设置 → 隐私 → 位置打标」一键关闭后,所有未来上传的 location_label = NULL;已上传房间提供「移除位置标签」按钮(直接 UPDATE NULL) |
| 不可恢复 | 关闭后无法找回原始 GPS——因为根本没存过 |
当 Apple 推出更高精度的
CLLocationAccuracyReduced(IPv6 地区已默认)时本项收益更明显:CrowdRoom 从一开始就比 iOS 系统更严格。
4. iOS 移交契约(P-1 ~ P-6)逐条决策
P-1 — 端侧脱敏失败 3 次的降级策略
决策:✅ 不降级到服务端二次脱敏;3 次失败后必须用户介入(手动框选 或 重新扫描),坚决不破例 iOS-X1。
理由:① 服务端二次脱敏需要解码原始 .usdz 贴图,本质是把数据持有等级从「已脱敏 绿」升回「未脱敏 红」,违反 PR-1;② 端侧失败 3 次的根本原因多为
ModelIO解贴图异常或贴图格式罕见(HDR / 浮点 PNG),这些场景手动框选反而比模型更准;③ 8 周 MVP 期内服务端没有 GPU 推理预算(成本 + 隐私双不划算)。iPhone 12 Pro 上 16 s 的 R-iOS-2 风险用「文案明确告知预计 15 秒」的 UX 兜底,不动 X1。实现位置:
03_ios_app_plan.md§4.4 失败兜底 + §10 R-iOS-2 + iOS-X1 契约文字保留原样
P-2 — redactions[] 保留期与用户可见性
决策:✅
redactions[]与room_versions同生命周期(版本删则 cascade 删除);仅 owner 可见(01_data_schema.md§3.5redactions_owner_onlypolicy 已落地);owner 可在「我的房间 → 隐私详情」页看到每个 bbox 的缩略图,并对漏检/误检发起「申请重做」工单。理由:① 同生命周期保证「删房 = 彻底删审计」,避免「我删了房,但脱敏记录还在数据库里」的尴尬;② owner-only 是为了防止攻击者通过 bbox 坐标反推真实人脸位置(即便贴图已模糊,反推「模糊区域曾经是某熟人面孔」仍构成隐私泄露);③ 用户可见性是 PR-3 的硬要求——用户必须能验证「我相信的脱敏真的发生了」。
实现位置:
01_data_schema.md§3.5redactions表 + RLSredactions_owner_only+03_ios_app_plan.md§1.2 PrivacyPage(在「我的房间」详情下新增「隐私详情」子页)
P-3 — 位置标签是否公开展示
决策:✅ 城市级(5 km 精度)随房间可见性公开展示;精确 GPS 永不上传、永不存储。
NSLocationWhenInUseUsageDescription文案补充一句「该城市标签会显示在你的公开房间页」。理由:① 城市标签是发现流的强信号(「上海北欧风客厅」远比「北欧风客厅」更有用),完全屏蔽损失体验;② 5 km 精度无法定位到楼栋,符合 GDPR Article 4(1) 中「无法识别自然人」的去标识化阈值;③ 文案补强是 PR-2 + PR-3 的衍生——用户必须在授权时就知道这会公开,而不是事后惊讶。
实现位置:
03_ios_app_plan.md§8.1 权限文案(需新增「会显示在公开房间页」句子)+01_data_schema.md§3.2rooms.location_label字段 +04_web_app_plan.md§8.2 详情页元信息行
P-4 — 用户删除全部数据的端到端流程
决策:✅ 「注销账号并删除全部数据」一键流程,承诺 30 天内完成端到端清理,分四阶段:
阶段 触发 数据状态 用户可挽回 T+0 (即时) 用户点击「确认注销」+ 二次密码确认 users.deleted_at = now();rooms.visibility = 'private'(立即从 Feed 与搜索消失);所有 Remix 走 §10 治理 P-W-3 的快照转移流;账号登录被阻断✅ 7 天内联系 DPO 邮箱可撤销 T+7 (软删完成) pg_cron 每日 02:00 扫表 数据库行打 deleted_at,Storage 公开 bucket 中的canonical.glb / thumbnail仍存(继续承载已发表 Remix)❌ T+30 (硬删完成) pg_cron 第 30 天扫表 删除 rooms/room_versions/redactions/comments/likes/users行;Storage 私有 bucket(source.usdz / source.roomplan.json)整目录删除;Sentry 与 PostHog 通过user_id关联事件按 SDK API 调用删除❌ 持续 公共 Remix 的几何快照(§10 P-W-3 决策)保留为「孤儿作品」,作者署名替换为「Former CrowdRoom user」 — — 理由:① 30 天硬删窗口对齐 GDPR Article 17 的「一个月内响应」+ 给运营充分时间处理异议;② 7 天软删让用户冷静期,避免冲动注销后悔(实测电商类产品冲动注销撤销率 8–15%);③ Remix 几何快照保留是 P-W-3 「Remixer 既得权」的衍生(详见
10_governance.md§4 P-W-3)。实现位置:
03_ios_app_plan.md§1.2 SettingsPage 新增「注销账号」子页 +04_web_app_plan.mdR-10/me新增同款入口 + 新增 Edge Functionaccount-delete(待02_api_contract.mdv0.2 补 E-16)
P-5 — ATT 启用触发条件
决策:✅ MVP 不申请 ATT;当且仅当以下任一条件首次满足,才在下一个 minor 版本灰度推 ATT 弹窗:
- 接入 Apple Search Ads 归因(需读取
attributionToken)- 接入任何把 IDFA 出域的第三方 SDK(如 AppsFlyer、Adjust、字节穿山甲)
- 与广告联盟/数据合作方做 user-level 数据交换
Sentry、MetricKit、PostHog(已配置为「不收 IDFA、不开 Session Replay」)均不触发以上任一条件,因此 MVP 上线时
NSUserTrackingUsageDescription字段不在 Info.plist 中。理由:① 不申请 = 不需要审核 ATT 文案,免去 App Store 拒审风险;② 一旦满足触发条件再补,发版周期约 1–2 周,对业务节奏影响极小;③ 与 PR-2 「最小数据采集」严格对齐。
实现位置:
03_ios_app_plan.md§8.2 ATT 章节(结论已对齐,本契约把「何时切换」的判定条件落到纸面)+ 本文 §9 第三方 SDK 清单
P-6 — 未成年用户保护与年龄确认
决策:✅ App Store 分级标 17+;首次启动弹「我已年满 13 岁」单按钮确认;不收集出生日期;不区分 13–17 岁与 18+。Web 端在
/signup同步要求勾选。理由:① App Store 17+ 与 Google Play Mature 17+ 是 UGC 平台的行业标准(小红书/Reddit/Discord 均如此);② 不收集出生日期是 PR-2 的强约束——出生日期是高度敏感的可识别信息,收集即增加合规面;③ 「13 岁阈值」对齐 COPPA(美国)+ GDPR-K(欧盟)+ 中国《未成年人网络保护条例》共识下限;④ 不细分 13–17 / 18+ 是因为本平台无年龄分级内容(NSFW 已在
10_governance.md§4 处罚阶梯 L4 永久封禁),无需做年龄分流。如未来上线 NSFW 分区或商业化(均为 P2):需追加「证件认证 18+」流程并升级本节为「双闸口」。
实现位置:
03_ios_app_plan.md§1.2 Auth 页(新增年龄确认 modal)+04_web_app_plan.mdR-09/signup(同款 checkbox)+ App Store Connect 分级配置(不在代码库)
5. Web 移交的隐私强相关契约(P-W-1 / P-W-2 / P-W-7)
P-W-1 — viewState 分享链接是否会泄露隐藏几何
决策:✅ 不会泄露,且本决策由数据结构强保证:viewState token 只编码「4 层可见性 + 相机 + overlay_id」三类纯标量字段,不持有几何数据(
04_web_app_plan.md§4.4 + §9.3 已定义编码契约);第三方拿到?vs=...之后只能改回「打开 furniture 层」这种纯本地切换,无法获得任何未公开的 mesh 顶点或贴图。理由:① 几何始终在 CDN 上的
canonical.glb里,谁能访问.glb与 viewState 完全无关——若房间是private,CDN 路径压根不会公开;若是unlisted/public,几何本身已被作者授权公开,「隐藏图层」只是一种展示偏好而非访问控制。② 这与 ArcGIS 的「图层可见性」语义一致:图层隐藏 ≠ 数据保密。③ 在产品文案上必须明确这一点(即「保存为视图」按钮旁加 tooltip:「这是一种展示视图,不会让别人看不到底图」),避免用户产生「隐藏 = 加密」的错觉。实现位置:
04_web_app_plan.md§4.4 Named Views(tooltip 文案待补)+ §9.3 viewState 编码契约(仅标量字段已明确)
P-W-2 — unlisted 房间的 OG 卡片 SEO 抓取
决策:✅
unlisted房间在robots.txt与 OG endpoint 双重阻断爬虫;但持链访问仍可正常出 OG 图——「持链可见」是 unlisted 的产品语义,「搜索引擎可索引」不是。具体规则:
资源 publicunlistedprivaterobots.txt允许✅ ❌ Disallow: /r/{id}通过动态生成(pg_cron 每小时刷新一次列表)❌ /r/{id}详情页SSR 渲染 SSR 渲染,但响应头 X-Robots-Tag: noindex, nofollow401 /api/og/r/{id}缓存 24h 仅当 Referer 来自微信/Twitter/Telegram/iMessage UA 名单时返回 OG 图,否则 403 403 sitemap.xml 包含 ✅ ❌ ❌ 理由:① unlisted 的产品语义是「不在 Feed 出现,但持链可看」(与 YouTube Unlisted 一致),SEO 索引会破坏这条承诺;② OG endpoint 的 UA/Referer 白名单是工程性兜底——主流社交平台抓 OG 时都会带可识别 UA,搜索引擎不在名单内;③ 完全屏蔽 OG 会让 unlisted 链接在微信/Twitter 卡片里变成「裸链」,损失分享体验。
实现位置:
04_web_app_plan.md§9.1 OG 标签(需追加X-Robots-Tag与 UA 白名单逻辑)+ §9.4 robots.txt(追加动态 unlisted 黑名单)
P-W-7 — viewState token 用作画像的合规风险
决策:✅ viewState token 一律视为「用户偏好数据」纳入隐私范围管理;禁止将其与
user_id或 IP 关联落库做画像;PostHog 事件中如携带 viewState,必须先经过 hash + 截断。具体规则:
- 服务端持久化:
view_states表(如未来引入)只存room_id + creator_id + token + created_at,不存viewer_id/ip;TTL 90 天后 pg_cron 物理删除- 前端遥测:PostHog
capture('view_state_loaded', {...})事件中 viewState 字段必须用sha256(token).slice(0,8)替代,且事件本身不带user_id(PostHog 项目配置enable_recording_console_log: false+disable_session_recording: true)- Sentry breadcrumb:viewState token 进入 URL 时自动经过 Sentry
beforeBreadcrumb过滤,替换为?vs=[REDACTED]- 用户导出数据时(§6 合规清单),viewState 历史不导出——它是「派生数据」而非「用户数据」
理由:① viewState 含相机角度+图层组合,长期累积可推断「这个用户偏好俯视墙体而非家具特写」这类风格画像,进而推荐广告——这与 PR-2 「最小数据采集」冲突;② hash 截断让运营仍能统计「最热门 view 形态」聚合指标,但无法回查到具体用户;③ Sentry 过滤是行业标配(避免 token 进入崩溃报告被工程师肉眼看到)。
实现位置:
04_web_app_plan.md§9.3 viewState 编码契约(追加「派生数据」标识)+ 本文 §9 第三方 SDK 清单 PostHog 一行
6. GDPR / PIPL 合规清单
区分「MVP 必做」与「P2 可推」,所有必做项需在 8 周窗口内随产品同步上线。
6.1 MVP 必做项
| # | 项 | 落地形态 | 关联法条 |
|---|---|---|---|
| C-1 | 隐私政策(zh + en) | /privacy SSG MDX 页(04_web_app_plan.md R-13),首次启动 App 全屏强制阅读 + 勾选 |
GDPR Art. 13 / PIPL §17 |
| C-2 | 用户协议(ToS) | /terms SSG MDX 页,与 C-1 同弹窗勾选 |
通用 |
| C-3 | Cookie 通知 | Web 端首次访问底部 banner,区分「必要 / 偏好 / 分析」三类,分析类(PostHog)默认关,用户主动 opt-in | GDPR ePrivacy Directive |
| C-4 | 数据导出 API | 新 Edge Function account-export,60 秒内异步生成 .zip(含用户上传的 .usdz + .json + 评论 + 点赞流水 + 个人档案),通过邮件单次签名链接送达 |
GDPR Art. 20 / PIPL §45 |
| C-5 | 删除账户 API | §4 P-4 决策中的 4 阶段流程 | GDPR Art. 17 / PIPL §47 |
| C-6 | DPO 联系邮箱 | privacy@crowdroom.app 监控信箱,72 小时内首响应 SLA;隐私政策页固定展示 |
GDPR Art. 37 / PIPL §52 |
| C-7 | 数据处理记录(RoPA) | 内部 Notion 文档(不公开),记录每个数据类别、用途、保留期、第三方共享 | GDPR Art. 30 |
| C-8 | 未成年人保护 | §4 P-6 决策 | COPPA / 中国《未成年人网络保护条例》 |
6.2 P2 可推项(按市场扩张时序推进)
| # | 项 | 触发条件 |
|---|---|---|
| C-P2-1 | DPIA(数据保护影响评估) | DAU > 10 万 或 进入欧盟主动运营 |
| C-P2-2 | 跨境传输备案(中国 PIPL) | 在中国大陆托管或服务 > 10 万中国用户 → 需走「标准合同 + 网信办备案」 |
| C-P2-3 | GDPR 代表(欧盟代表) | 开放欧盟市场或欧盟用户 > 5% MAU → 委托第三方法务公司 |
| C-P2-4 | SCC(标准合同条款)签订 | 与 Supabase / Sentry / PostHog / Vercel 任一签订 SCC 模块化条款(目前各家官网都有标准模板) |
| C-P2-5 | CCPA / CPRA 合规(加州) | 美国市场 DAU > 1 万 |
| C-P2-6 | App Privacy Manifest(Apple 2024 强制) | iOS 17.4+ 起 App Store 审核必须项;MVP 也要在发版前打钩,本项已升 MVP——见 03_ios_app_plan.md §8 待补 |
注:C-P2-6 实际是 Apple 平台强制项(2024 春已生效),MVP 发版必须提交
PrivacyInfo.xcprivacy声明 SDK 清单与 API 使用类别——已 cross-ref 到本文 §9。这是本子任务反向回写到 iOS 计划的一处「漏洞」(见 attempt_completion 漏洞列表)。
7. 隐私默认值清单
所有「涉及隐私的开关」MVP 默认值;遵守 PR-3 「默认朝隐私最严方向」与 PR-4 「默认私有」。在「我的 → 设置 → 隐私」一处可视化展示并一键切换。
| 开关 | 默认 | 用户可改 | 说明 |
|---|---|---|---|
| 房间可见性(新扫描) | 私有 | ✅ | 上传表单必须显式勾选「公开」/「持链可见」,零误公开(PR-4) |
| 位置打标 | 关 | ✅ | 关闭时所有未来上传 location_label = NULL(§3.3) |
| 扫描音频录制 | 永关 | ❌ | RoomPlan 不需要音频,NSMicrophoneUsageDescription 不申请 |
| 端侧脱敏 | 永开 | ❌ | iOS-X1 硬约束,用户无法关闭(§4 P-1) |
| 保留脱敏前原图本地备份 | 关 | ✅ | 仅当用户主动勾选才在 Storage pre_redaction.jpg 留底(01_data_schema.md §6 Storage 目录) |
| Sign in with Apple 隐藏邮箱 | 开(由 Apple 默认) | ✅ | 与 Apple 私有中继邮箱兼容 |
| Remix 通知(我的房间被 Remix 时通知我) | 开 | ✅ | 创作互动需要,但用户可关 |
| 评论通知 | 开 | ✅ | 同上 |
| 点赞通知 | 关 | ✅ | 默认关,避免高频骚扰 |
| 在公开页面展示我的 handle | 开 | ❌ | handle 是公开身份;不允许「匿名上传」(避免 UGC 治理失控) |
| 在公开页面展示我的 email | 永关 | ❌ | email 永远只对自己可见,RLS 保证(01_data_schema.md §3.1 users 表) |
| PostHog 行为分析 | 关(C-3 Cookie 通知中 opt-in) | ✅ | 用户不 opt-in 时 PostHog SDK 不初始化 |
| Sentry 崩溃上报 | 开 | ✅ | 崩溃报告默认不含 PII,但用户仍可在隐私设置关闭 |
| iframe 嵌入我的房间 | 开(公开/unlisted 房间默认允许嵌入) | ✅ | 关闭后 /embed/r/{id} 返回 403,详见 10_governance.md §4 P-W-6 |
| 允许搜索引擎索引我的主页 | 开(仅 public 房间) | ✅ | unlisted/private 永不被索引(§5 P-W-2) |
| ATT(跨 App 跟踪) | 不申请 | ❌ | §4 P-5 决策 |
8. 数据保留与删除时间表
| 数据类别 | 保留期 | 删除触发 | 是否可恢复 |
|---|---|---|---|
| 原始 .usdz / .roomplan.json(私有 bucket) | 与 room_versions 同生命周期,最多 90 天 |
90 天后 pg_cron 把 private/ 转码已成功的版本归档清除(保留 canonical.glb 即可服务) |
❌ |
canonical.glb / thumbnail.webp(公共 bucket) |
与 room_versions 同 |
房间硬删 cascade;用户注销 T+30 硬删 | ❌ |
redactions[] 表行 |
与 room_versions 同 cascade |
同上 | ❌ |
rooms / room_versions / layers |
永久(除非用户删除) | 用户主动删除 / 注销 T+30 / 严重违规封禁 | T+7 内有效;T+30 后 ❌ |
comments / likes |
永久 | 评论/点赞作者主动删;房间 cascade 删 | ❌ |
remixes(已发表) |
永久 | Remix 作者主动删;父房间走 P-W-3 快照转移流(10_governance.md §4) |
❌ |
草稿 Remix(is_public=false) |
30 天未更新自动清理 | pg_cron 扫 updated_at < now() - 30d |
❌ |
location_label(独立字段) |
跟随 rooms |
用户可单独 UPDATE NULL(§3.3) | ❌ |
| 审计日志(Edge Function logs) | 90 天 | Supabase 平台默认 | ❌ |
| Sentry 事件 | 90 天 | Sentry 项目 retention 配置 | ❌ |
| PostHog 事件 | 7 年(默认)→ 调整为 13 个月 | PostHog project setting 强制下调 | ❌ |
Worker 日志(private/.../transcode.log) |
30 天 | pg_cron 扫 Storage 元数据 | ❌ |
view_states 表(若引入) |
90 天 | pg_cron | ❌ |
reports 举报记录 |
永久(已结案 6 个月后归档为只读) | 不删除(治理需要追溯) | 仅 owner-team 可见 |
| 用户账号注销 | T+0 软删 / T+7 不可撤 / T+30 硬删 | §4 P-4 流程 | T+0–T+7 ✅,之后 ❌ |
9. 第三方 SDK 风险清单
| SDK | 拿到什么数据 | 数据出域吗 | 是否 GDPR 友好 | SCC 状态 | 我们的额外动作 |
|---|---|---|---|---|---|
| Supabase(Postgres / Auth / Storage / Realtime) | 全部业务数据(DB 行 + 文件 + 鉴权 token) | 是(其 AWS us-east-1 主机房) | ✅ 官方有 GDPR DPA + SCC | ✅ MVP 即签 | 启用 Supabase Vault 加密 service_role;按 §8 保留期清理 |
| Sentry(iOS + Browser + Server) | 崩溃堆栈 + breadcrumb + 用户邮箱(仅 issue 关联) | 是(Sentry SaaS) | ✅ SOC 2 + GDPR DPA | ✅ MVP 即签 | beforeSend 过滤 PII;breadcrumb 中 viewState 替换为 [REDACTED](§5 P-W-7) |
| PostHog Cloud(事件分析) | 用户事件 + funnel + feature flag 评估 | 是(PostHog EU / US 双区可选) | ✅ 选 EU 区即数据不离欧 | ✅ MVP 即签 | 强制 opt-in(C-3 Cookie 通知);关闭 Session Replay;保留期下调至 13 个月 |
| CloudFlare(CDN + DNS) | 公开静态资源访问日志(IP + UA) | 是(全球边缘节点) | ✅ GDPR DPA | ✅ MVP 即签 | 不缓存私有 bucket;启用 CF Bot Fight Mode 防爬 |
| Vercel(Web 部署 + Edge Function) | 请求 IP + UA + 路径 | 是(全球边缘) | ✅ GDPR DPA | ✅ MVP 即签 | Edge Function 内禁用 console.log 用户级数据;分析数据保留期默认 |
| Apple Sign in with Apple | Apple ID 关联 token | 否(Apple 直接给 token,不持有原始 Apple ID) | ✅ Apple 平台原生 | n/a | 接受 Apple Hidden Email 默认行为 |
Google OAuth(仅 Web /login) |
Google 用户 sub + 邮箱 | 否(OAuth 标准 token 交换) | ✅ Google Workspace DPA 适用 | ✅ 通过 Supabase Auth 中转,无直接合同 | |
| MetricKit(iOS 系统) | 设备性能指标(CPU/GPU/热量) | 否(仅 App 内消费) | ✅ Apple 原生 | n/a | — |
底线:除上表 8 项外,MVP 不接任何第三方 SDK。若运营提出新接入需求(如客服系统 Intercom、推送 OneSignal),必须先把该 SDK 加入本表并签 SCC 才可上线——这是 PR-2 的硬执行点。
10. 本章小结
| 关键产出 | 一句话 |
|---|---|
| 5 条隐私原则 PR-1 ~ PR-5 | 端侧优先脱敏 / 最小采集 / 用户可控 / 默认私有 / 可被遗忘——任何冲突按编号优先 |
| 数据流隐私视图 | 红黄绿三色 + 第三方可访问性双标签,红色节点永不离设备/Supabase 内网 |
| 三类敏感数据生命周期 | 人脸端侧不可逆模糊 + 地标/文档手动框选 + 位置永远城市级 5 km |
| 6 条 iOS 契约 P-1 ~ P-6 | 端侧失败不破例 / redactions owner-only / 城市标签公开 / 30 天硬删 / ATT 触发条件 3 项 / 13+ 单按钮确认 |
| 3 条 Web 契约 P-W-1 / P-W-2 / P-W-7 | viewState 不泄漏几何 / unlisted 双重 SEO 阻断 / viewState 视作偏好数据强 hash |
| GDPR + PIPL 合规清单 | 8 项 MVP 必做(含 Apple PrivacyManifest)+ 6 项 P2 |
| 隐私默认值表 | 16 项开关,全部朝最严方向;端侧脱敏与 mic 关、email 不公开 = 永不可改 |
| 数据保留时间表 | 15 类数据,原始 .usdz 90 天 / Sentry-PostHog 调至 13 个月 / 注销 30 天硬删 |
| 8 个第三方 SDK 风险点 | 全数有 GDPR DPA 与 SCC 模板可签;不允许 MVP 期内新增 |
读完本章你应能:
- ✅ 给隐私律师一份可直接审阅的数据处理映射(§2 数据流图 + §3 生命周期 + §9 SDK)
- ✅ 给 iOS / Web 工程师 P-1 ~ P-6、P-W-1 / P-W-2 / P-W-7 共 9 条契约的拍板答案
- ✅ 知道
10_governance.md在哪几节继续处理治理类 P-W-3 ~ P-W-6
章节版本:v0.1 · 草案 关键收获:CrowdRoom 把隐私风险压缩到「用户主动框选发布」这一个决策点上——前置的端侧脱敏让原始 RGB 永不出设备、后置的 4 层 manifest 让公开数据只剩几何与材质;GDPR + PIPL 合规以「MVP 必做 8 项 + 第三方 SDK 全签 SCC」最小集即可上线。