Files

60 lines
4.6 KiB
Markdown
Raw Permalink Normal View History

2026-08-26 06:41:07 +08:00
# 私有数据导出开发说明
## 1. 功能边界
私有数据导出用于将某一长者在当前租户和家庭边界内的资料生成独立JSON文件。它与`ACCESS`数据盘点分离:盘点只返回分类数量,导出文件才包含用户被授权获取的正文。
可导出分类包括长者档案、授权记录、设备绑定、通话元数据、最终话轮、摘要、故事与来源、已确认记忆。未显式指定分类时生成全量导出。
## 2. 功能设计
1. 家庭所有者使用`Idempotency-Key`提交导出任务。
2. API在事务中验证`privacy.manage`、长者归属和请求摘要,写入`QUEUED`任务及Outbox事件。
3. Worker将任务转为`RUNNING`,按固定分类SQL查询数据,生成`subject-export-v1`文档。
4. Worker计算SHA-256,将文件写入MinIO私有桶,再把文件大小、摘要和过期时间提交到PostgreSQL。
5. 用户读取`READY`任务时,API使用公网端点现场生成短期预签名URL,不在数据库和页面持久化URL。
6. 到期扫描器删除对象,清空内部对象引用,把任务置为`EXPIRED`并记录最小审计。
## 3. 安全设计
- MinIO桶`private-exports`保持私有,未签名的对象请求被拒绝。
- 对象路径为`tenants/{tenant-hash}/exports/{export-id}/v1.json`,不把租户主键直接写入路径。
- API不返回`object_ref`、对象存储凭据或长期URL。导出详情和列表使用`Cache-Control: no-store`。
- 下载URL有效期取“配置的短期下载TTL”与“对象剩余有效期”的较小值。
- 导出文件包含私密正文,仅能使用合成数据进行本地测试,生产密钥必须由密钥管理系统注入。
## 4. 接口设计
| 接口 | 权限 | 说明 |
|---|---|---|
| `POST /api/v1/subjects/{id}/exports` | `privacy.manage` | 幂等创建导出,返回`202`;重放返回`200` |
| `GET /api/v1/subjects/{id}/exports` | `privacy.read` | 返回当前长者导出列表,不签发下载URL |
| `GET /api/v1/exports/{id}` | `privacy.read` | 返回任务详情;仅就绪且未过期时包含短期URL |
## 5. 数据库设计
`export_task`保存租户、长者、申请人、冻结范围、任务状态、对象引用、大小、内容摘要、过期时间、尝试次数和幂等摘要。状态为`QUEUED/RUNNING/READY/FAILED/EXPIRED`。`READY`数据库约束要求对象引用、大小、摘要、过期时间和完成时间全部存在。
## 6. 配置
| 变量 | 用途 |
|---|---|
| `OBJECT_STORE_ENDPOINT` | API/Worker访问对象存储的内网端点 |
| `OBJECT_STORE_PUBLIC_ENDPOINT` | 用于生成用户可访问签名URL的端点 |
| `OBJECT_STORE_REGION` | 签名Region,避免使用公网地址执行内部探测 |
| `OBJECT_STORE_EXPORT_BUCKET` | 私有导出桶 |
| `EXPORT_DOWNLOAD_TTL` | 单次预签名下载地址有效期 |
| `EXPORT_OBJECT_TTL` | 导出对象总保留期 |
## 7. 验证
`scripts/smoke-export.ps1`使用本地真实OIDC令牌、PostgreSQL、Worker和MinIO验证所有者/编辑者权限、幂等重放、分类范围、私有桶拒绝直连、预签名下载、SHA-256校验、长者边界和过期后对象删除。
家庭工作台的“生成私有导出”现先打开页面内受控操作区。表单固定当前长者公开编号和八类导出范围,并明确后台将生成包含个人正文的私有JSON文件、对象与短期下载地址均有有效期、文件下载后应受控保存和销毁且操作会进入申请与导出审计。用户必须勾选私密数据影响确认后才能提交;取消或切换业务上下文会清除草稿,不创建任务,也不提前签发下载地址。
READY任务的“获取短期下载”同样不再单击即读取任务详情并触发下载。确认区固定长者、导出任务公开编号、任务冻结的分类范围、文件大小和对象过期时间,明确短期地址只会在提交时现场生成,JSON包含个人正文且离开平台后需要限制转交并按需销毁。只有显式确认后才重新读取任务;任务仍为READY、对象仍未过期且返回短期地址时才触发浏览器下载。取消或切换长者、家庭、工作台会清除草稿,不调用会签发地址的任务详情接口。
日常页面验证采用真实OIDC无提交冒烟,只检查对象/范围绑定、确认门禁、取消关闭、零导出创建请求、零任务详情地址签发请求、任务数量不变及页面布局。完整对象生成、私有桶、摘要、下载和过期清理由本节既有定向脚本承担,避免在普通前端改动中重复执行高强度全链路测试。
V10迁移已在独立临时空库完成`up 1—10 → down -all → up 1—10`,最终状态为`10|dirty=false`,验证库已删除。