公开手帐:确认、冻结与撤回的事务边界

双方确认、范围审批、解除配对冻结 30 天,以及撤回后的缓存与清理路径。

我们的小星球专栏 · 03 / 03 目录 ↗

src/lib/publicSpace.ts 用一个总开关 spaces.public_enabled_at,七个栏目范围放在 settings 的 guestHome…guestScreenings,待确认的提案放在 public_proposal_*。发起人提交后,另一个人调用 acceptPublicProposal() 确认;这个函数 SELECT ... FOR UPDATE,禁止自己确认自己,确认时一次写入七个范围标记。disablePublic() 是单方面的,任何一方都能立刻关闭。

范围不是一次性授权。改范围要重新走确认;未公开时 /s/<门牌号> 只显示一页合着的本子。访客记录只保留 IP、设备、页面和时间。媒体不暴露公网直链,统一经 /api/media/[id] 鉴权代理;SVG/HTML 等主动内容拒收。

解除配对

解除配对留 30 天冻结(UNPAIR_KEEP_DAYS=30)。unpair() 写 space_snapshots(space_id, frozen_at, expires_at, member_ids),同时给两个人各建新空间和配对码;重新配对时 restoreSnapshot() 只有 member_ids 排序后完全一致才恢复。恢复会搬 entries、media、milestones、eggs、screenings、coin 表,合并标签和设置,删墓碑;spaces 行本身不恢复。

撤回之后

撤回公开后,旧链接、媒体代理和浏览器缓存不会自动失效。媒体响应是 private, max-age=31536000, immutable;如果 URL 不变,访客手里的副本会留一年。更稳的做法是媒体 URL 带版本/签名,撤回时换 key,或者让代理在每次请求重新校验范围。

清理

purgeExpiredSnapshots() 只在 /settings/share 加载、/api/admin/purge 和管理员动作里触发,没有启动钩子或 cron;过期快照和对象可能超过 30 天还在。删除媒体是逐条 S3 best-effort,数据库行先删、对象后删,失败会留下孤儿。备份每天 04:00,KEEP_COUNT=1,要求至少 5GB,停应用后 mysqldump + 打包 Garage data/meta,恢复是季度人工演练。

公开、撤回、冻结、清理是四条独立路径;隐藏页面不会删除数据,也不会让已有缓存和旧 URL 失效。

← 全部文章 阅读时长: 2分钟 写邮件