6.4 KiB
具体资源分享开发说明
实现范围
V17—V18已完成具体资源分享纵向闭环。家庭所有者或管理员可以把单个故事、单段通话文字或单个已验证录音分片分享给同一客户组织内的活动用户,并分别设置接收人、最小权限、用途、失效时间和登录要求。系统同时支持指定接收人登录访问和匿名口令访问;授权撤销或到期后,新的访问立即被拒绝。
EDIT只适用于故事且强制登录。接收人修改故事时必须提交当前版本,成功后形成新的story_revision、复制原话来源、把故事置为IN_REVIEW并递增版本;旧版本写入返回HTTP 412,不会覆盖并发修改。文字分享不会隐式授予录音权限,播放权限也不会隐式包含下载权限。
资源与权限矩阵
| 资源类型 | 资源编号 | 允许权限 | 访问结果 |
|---|---|---|---|
STORY |
story_draft.public_id |
VIEW_TEXT、EDIT |
返回当前标题、正文、版本和修订号;EDIT可写入新修订 |
TRANSCRIPT |
conversation.public_id |
VIEW_TEXT |
返回最多1000条按序排列的最终话轮,不暴露供应商引用 |
RECORDING |
media_segment.public_id |
LISTEN、DOWNLOAD |
当前原录音授权有效且分片已验证时,签发5分钟私有对象地址 |
接口设计
POST /api/v1/sharing-grants:携带Idempotency-Key创建分享;同键同正文重放原结果,同键不同正文返回冲突。GET /api/v1/sharing-grants?subject_id=...:所有者或管理员查看指定长者的分享历史,包括已撤销记录。DELETE /api/v1/sharing-grants/{id}:幂等撤销分享并记录事务审计。GET /api/v1/sharing-grants/{id}/resource:指定接收人使用OIDC身份读取登录分享。PATCH /api/v1/sharing-grants/{id}/resource:持有EDIT权限的指定接收人修订故事;使用If-Match进行强并发控制。GET /api/v1/public/shares/{id}:使用X-Share-Token读取匿名分享;该接口不接受EDIT。
撤销或过期统一返回HTTP 410;不存在的分享或资源返回404;身份、口令、接收人或权限不满足返回403;故事版本冲突返回412。浏览器管理页提供资源、接收人、权限、有效期、用途和登录方式配置,创建后展示可转交的访问地址;匿名口令仅展示一次。
创建操作不会再从配置表单直接提交。点击“创建分享”后,页面内受控操作区冻结长者、具体故事/通话文字/录音分片的业务名称与公开编号、接收成员、单项能力、用途、准确到期时间和登录方式。登录分享必须确认只有指定接收人能以OIDC身份访问,且同一接收人、资源和权限的旧有效分享会被替换;匿名分享必须确认地址和口令组合等同访问凭据,任何持有者都可能访问,口令只显示一次并应与地址分开传递。EDIT仍由表单和服务端共同强制登录。显式确认后才调用创建接口,成功后才清空用途并显示新地址/口令;打开或取消新确认区不会提前清除尚未保存的旧匿名口令。
分享撤销使用页面内受控操作表单,固定展示授权编号、具体资源、权限、登录方式、到期时间和行版本。操作者必须确认撤销后系统会立即拒绝新的访问,但接收人已经离线保存的副本无法由平台追回。取消,或切换页签、家庭、长者,都会清空草稿且不发送撤销请求;服务端角色、租户、授权状态和并发版本校验保持不变。
匿名口令设计
匿名分享的授权编号由服务端签名密钥、操作者、幂等键和请求摘要确定性派生,访问口令再由授权编号确定性派生。这样,同一幂等请求可以返回相同口令,而数据库只保存口令的SHA-256摘要,不保存或记录原始口令。访问时服务端使用常量时间比较摘要,降低时序侧信道风险。
SHARE_TOKEN_SIGNING_SECRET至少32字符。生产环境拒绝占位值,并要求它与游标签名、设备令牌、RTC令牌等API签名密钥互不相同。匿名口令相当于访问凭证,应把地址和口令分开传递;拥有完整地址和口令的人均可访问,因此管理页仍要求选择明确接收人,便于用途说明、追踪和撤销,但匿名模式不把OIDC身份作为访问条件。
数据库与审计
sharing_grant保存客户组织、家庭、长者、具体资源、接收人、单项权限、用途、授予人、登录要求、口令摘要、失效时间和撤销信息。数据库约束再次校验资源与权限组合,并禁止匿名EDIT。创建授权时,服务端从资源反向推导客户组织、家庭和长者,不接受浏览器上报这些安全边界;接收人必须是同一客户组织的活动账号。
sharing_access_log逐次保存成功或拒绝访问的账号、身份摘要、资源、权限、结果、稳定原因、请求关联编号和时间,不保存故事正文、字幕正文、录音地址、Bearer凭证或原始分享口令。拒绝原因包括TOKEN_INVALID、GRANT_INACTIVE、RECIPIENT_MISMATCH、CONSENT_REQUIRED和RESOURCE_UNAVAILABLE。
隐私主体删除会撤销分享并脱敏用途和拒绝原因;主体物理清理时分享及访问日志级联删除。录音分享每次访问都会重新检查当前raw_audio_storage授权和分片VERIFIED状态。撤销后不再签发地址;已经签发的地址最长在当前5分钟对象存储签名窗口后失效,该窗口仍需在家庭试点前结合对象存储能力验证并尽量缩短。
验证
pwsh -NoProfile -File .\scripts\smoke-sharing.ps1
烟测覆盖登录分享、匿名口令、确定性幂等重放、错误口令、接收人隔离、跨租户拒绝、非法资源权限组合、故事编辑及旧版本412、撤销、过期、原始口令不落库和成功/拒绝访问审计,并在结束后清理合成资源。
日常前端改动采用一次真实OIDC无提交轻量冒烟,使用合成故事、通话和已验证录音分片依次打开三种资源的创建确认区,同时覆盖匿名口令和登录接收两种模式。检查固定资源、接收人、能力、用途、有效期、影响确认、取消关闭、零创建POST、授权表数量不变、页面无横向溢出且无非预期浏览器错误;不在每次页面修改后重复执行本节完整访问和并发回归。