Cloudflare D1(SQLite) · USER_DB(apps/server/wrangler.jsonc) · contexts/users

USER_DB

Berth 的身份、会话、设备、公开资料与偏好;旧关注实现待迁到 SOCIAL_DB 后删表。

不存钱:订单 / 仓位 / 资产 / 交易授权的权威都在 Hyperliquid 链上(ADR-0083);私钥归 wallet,交易授权归 account。

12 张表 88 个字段 5 个聚合 1 个迁移 语义层已对齐 · sha256:13b99b758335e3f9

板块颜色贯穿全文

全库约定

业务流程跟着流程看表怎么变

📱 第一次用手机钱包登录

  1. App 请求登录 → 服务端在 user_login_clock 取号,写一条 login_challenges
    原文由服务端保存,验签不接受客户端自己拼的版本
  2. 用户用钱包签名,App 把签名交回来
  3. 一个 batch 里一次做完:没有这个钱包就建 users(有就复用)→ 发 user_sessions → 删挑战 → 登记 user_login_devices
    要么全成功,要么全不做;同一安装上的旧会话被结束
  4. App 拿到 token(库里只有它的 SHA-256),30 天后到期需重新登录

💻 电脑扫码登录,agent 名额满了要顶掉一台

  1. 电脑出二维码 → 已登录的手机扫码确认
    配对过程在 PairingSession DO,不进 USER_DB
  2. 电脑在本机生成一把 HL agent,手机签 approveAgent
  3. HL 每账户 named agent 名额已知下限是 3;满了默认顶掉最久没活跃的那台电脑,沿用它的 agent 名,同名重批即注销旧 agent
  4. 插入新的 user_sessions,同名旧会话写上 ended_at + agent_revoked_at,那台电脑被当场踢下线
  5. 到期前 7 天起可续期:换新 agent、手机签一次,会话再延 30 天

🏷️ 把用户名从 alice 改成 bob

  1. 检查冷却:当前名用满 14 天了吗?没满 → USERNAME_COOLDOWN
  2. alice 的 held_until 设为「现在 + 30 天」,变成保留名
  3. 插入 bob,held_until = NULL 即当前名
    bob 已被占用 → 整笔回滚,alice 不变(USERNAME_UNAVAILABLE)
  4. 30 天后 cron 删掉 alice,别人才能注册这个名字

设计要点

🔐 token 只存哈希库泄露也拿不到能用的凭证。对外只暴露 session_id。
🕰️ 不删行,用时间戳标状态ended_at / revoked_at / held_until:能展示「待撤销设备」,旧设备上线也能知道记录已被改过。
⚛️ batch 代替事务D1 没有交互式事务;多步写放进一个 db.batch,配合 INSERT … SELECT … WHERE 条件写防并发。
🔢 版本号 + 回执 = 多端同步收藏用 version 做 CAS、每次操作留回执,离线回放不会覆盖新状态。
🎫 login_order 排先后同一安装并发登录或旧挑战晚到,都不能覆盖较新的设备登记。
⛓️ 链上状态不复制agent 是否有效实时查 HL extraAgents;库里只记「我们已知它被撤掉了」。
社交资料扩展外链账号 / 偏好暂无运行时写接口。PublicUserCard 只经 users /server 批量发布,注销时隐藏公开资料。社交图归 SOCIAL_DB,USER_DB 旧关注表待迁出后删表。