Files
lionwebsite-backend/docs/SUBSCRIPTION_EVENTS.md

3.0 KiB
Raw Permalink Blame History

备用订阅更新事件

主站 /sub/{client}/{key} 接受网关的签名事件;GET 在客户端类型与缓存路径有效后,同一个主库事务写更新记录和长期收据。签名有效的 HEAD 不写记录。普通请求以及无效签名仍走原来的更新记录逻辑。

POST /internal/subscription-events 有界读取原始请求(最多 256 KiB),批次最多 100 条。签名算法为 HMAC-SHA256,同步密钥来自 SUBSCRIPTION_SYNC_SECRET;签名输入是 v1\n + epoch 秒时间戳 + \n + 原始请求体 SHA256 十六进制。时间偏差最多 300 秒。请求头为 X-Subscription-Timestamp 和 X-Subscription-Signature。主站 GET 将单个事件的原始 JSON 使用无 padding 的 base64url 编码放入 X-Subscription-Event,同样对原始事件 JSON 签名。

事件字段:eventId(规范小写 UUID)、keyHash(公开 key 的小写 SHA256)、client(v2 或 cat)、clientIp(IPv4/IPv6 字面值)、userAgent(最多 2048 字符)、occurredAt(epoch 毫秒)。允许历史事件,事件时间不可超过未来 5 分钟。签名中的 IP 为权威来源,不能由未经签名的 XFF 覆盖。

响应 acknowledged 只在事务已提交后返回,包括已存在的相同事件。冲突事件 ID 返回 400;签名无效返回 403;数据库异常返回 5xx,无确认列表。未知 hash 不确认;历史映射中用户已删除则写终态收据并确认,不猜测用户归属。可见记录按事件时间和 ID 倒序保留每用户最近 10 条,收据独立长期保留。批次任意数据库写入失败会全部回滚。

显式迁移

运行前先执行稳定 user_id 关联迁移。新表不会在启动时创建。

  1. 先在数据库副本上演练:python3 scripts/migrate_subscription_events.py /path/to/copy.db。
  2. 停止生产主站服务,确认没有其他写入者。
  3. 执行 python3 scripts/migrate_subscription_events.py /path/to/main.db --apply --service-stopped。
  4. 检查输出 integrity 为 ok,保留输出中的 SQLite 备份,然后启动新程序。

脚本在写入前使用 SQLite backup API 生成权限 0600 的备份,在单个事务中建表并初始化历史 hash,重复执行保留既有收据和历史。不将公开 key 写入历史表或输出;原数据库备份含既有敏感数据,须保留原有保护措施。

快照构建记住所有现有绑定;重置或删除绑定前也保存历史 hash。用户改名时回传事件按 stable user_id 读取当前名字。合法旧订阅标签的 user_id 可以为 NULL,历史映射保留标签并按原标签写回,不创建用户,也不猜测同名新用户归属。可见日志删除不删除历史映射或收据。

Java 编译与测试必须在部署手册指定的 192.168.5.30 执行:

mvn -Dtest=SubscriptionEventIntegrationTest,SubServiceTest,SubscriptionStandbySnapshotServiceTest,MyBatisNativeConfigurationTest test

Python 迁移验证可本机执行:python3 -m unittest discover -s scripts -p 'test_subscription_events.py' -v。