Commit Graph

1248 Commits

Author SHA1 Message Date
hailin ae936e8a87 feat(service-party-app): add Kava network switch (mainnet/testnet)
- Add KAVA_TESTNET_TX_CONFIG in kava-tx-service.ts
- Add switchNetwork/getNetwork IPC handlers in main.ts
- Add network toggle UI in Settings page
- Show current network (测试网/主网) badge in Layout status bar
- Default to testnet for development

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 10:31:27 -08:00
hailin 9015888b23 fix(service-party-app): fix participants display in Home page
listShares returned `participants` but Home.tsx expected `metadata.participants`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 10:07:11 -08:00
hailin f849a2a9fd fix(tss-party): increase stdin buffer to 1MB for large TSS messages
Default 64KB buffer was truncating large TSS protocol messages in round 3+

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:57:04 -08:00
hailin 2a49ab771b fix(message-router): 修复 JoinSession 代理未转发 Status 字段
问题: Message Router 代理 Session Coordinator 的 JoinSession 响应时,
没有转发 session_info.status 字段,导致前端方案B无法工作

修复: 添加 Status 字段的转发

这修复了 co-keygen 中最后一个加入者错过 session_started 事件的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:20:15 -08:00
hailin 57b84bb9fa feat: 恢复EVM地址派生和余额显示功能 + 修复0人参与bug
恢复的功能:
1. ee59d1c0 - 方案B修复最后加入者错过session_started事件的竞态条件
   - 修复了显示"0人参与"的bug
   - 使用事件缓存机制解决时序问题

2. a269e4d1 - 支持压缩公钥派生EVM地址并显示KAVA余额
   - Home页面显示钱包的KAVA EVM地址
   - 显示KAVA测试网余额
   - 支持压缩公钥格式

这些功能已经过验证,与转账功能无关。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 08:53:26 -08:00
hailin 290b5ea766 fix(server-party-co-managed): use session_started event for participants list
session_created event only contains initial co-managed parties,
but session_started event contains ALL participants including
external parties that joined dynamically via invite code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:52:28 -08:00
hailin 2164664ca0 feat(server-party): add ExecuteWithSessionInfo for co-managed keygen
Add new ExecuteWithSessionInfo method to ParticipateKeygenUseCase
for server-party-co-managed to skip duplicate JoinSession call.

- server-party-co-managed already calls JoinSession in session_created phase
- ExecuteWithSessionInfo accepts pre-obtained SessionInfo and skips internal JoinSession
- Refactor common execution logic to private executeWithSessionInfo method
- Update server-party-co-managed to use ExecuteWithSessionInfo on session_started

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:43:09 -08:00
hailin fd6f84ce82 fix(server-party-co-managed): 修复死锁问题 - session_created 时立即 JoinSession
问题:
- 原来在 session_created 时只存储 token,等待 session_started
- 但 session_started 需要所有 N 方都 JoinSession 后才触发
- 这导致死锁:co-managed-party 永远收不到 session_started

修复:
- Phase 1 (session_created): 立即调用 JoinSession + 存储 session 信息
- Phase 2 (session_started): 执行 TSS 协议(超时从此时开始计算)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:23:26 -08:00
hailin e114723ab0 feat(mpc-system): add server-party-co-managed for co_managed_keygen sessions
- Create new server-party-co-managed service with two-phase event handling
  - Phase 1 (session_created): Store join token and wait
  - Phase 2 (session_started): Execute TSS protocol (same timing as service-party-app)
- Add PartyRoleCoManagedPersistent role to isolate from normal keygen/sign
- Update docker-compose.yml with 3 co-managed party instances
- Update deploy.sh service lists
- Modify selectPartiesByCompositionForCoManaged to use new role

This ensures co_managed_keygen sessions use dedicated parties that behave
100% compatible with service-party-app, without affecting existing keygen/sign flows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 23:54:45 -08:00
hailin 1c66b55ea1 fix(service-party-app): 动态计算 persistent_count 并修复 keygen 触发时机
1. 动态计算 server-party 数量: persistent = n - t
   - 2-of-3 -> persistent=1, external=2
   - 3-of-5 -> persistent=2, external=3
   - 4-of-7 -> persistent=3, external=4

2. 修复 5 分钟超时与 24 小时会话的冲突
   - 之前: joinSession 后立即启动 5 分钟轮询,导致超时失败
   - 现在: 等待 all_joined 事件后才启动 5 分钟倒计时
   - 用户可以在 24 小时内慢慢邀请其他参与者加入

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 21:28:23 -08:00
hailin 66c3cec9a5 Revert "fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突"
This reverts commit 8c3a299714.
2025-12-29 13:48:14 -08:00
hailin 8c3a299714 fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突
问题:
- 多个参与方同时加入会话时会触发乐观锁冲突
- server-party 有重试逻辑可以成功重试
- service-party-app (Electron) 没有重试逻辑,直接失败
- 导致外部参与方无法成功加入 co_managed_keygen 会话

修复:
- joinSession 方法添加最多 3 次重试
- 支持重试的错误类型:optimistic lock、UNAVAILABLE、DEADLINE_EXCEEDED
- 使用指数退避 + 随机抖动避免重试风暴
- 抽取 doJoinSession 内部方法和 sleep 辅助方法

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:47:51 -08:00
hailin 6de545fcb9 fix(session-coordinator): generate wildcard token for co_managed_keygen external participants 2025-12-29 13:35:05 -08:00
hailin 75a2470233 debug(service-party-app): 添加 keygen 触发流程详细日志
添加 [KEYGEN] 前缀的 console.log 来追踪:
- checkAndTriggerKeygen 是否被调用
- activeKeygenSession 的状态
- 轮询条件是否满足
- handleSessionStart 的执行
- participateKeygen 的参数

帮助诊断 external party 为何不启动 TSS 进程

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:15:47 -08:00
hailin 576679ae30 fix(server-party): heartbeat during waitForAllParticipants
Problem:
- co_managed_keygen server-party waits for external party after joining
- No heartbeat sent during wait period (up to 5 minutes)
- session-coordinator has 120 second inactivity timeout
- Server-party marked as timed_out/failed while waiting

Fix:
- Send heartbeat in waitForAllParticipants polling loop
- Add Heartbeat method to MessageRouterClient interface
- Heartbeat every 2 seconds with poll interval
- Heartbeat failure only logs warning, does not block

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:04:40 -08:00
hailin c0e292535d fix(service-party-app): 修复 handleIncomingMessage 字段名 snake_case 问题
问题:
- gRPC proto-loader 使用 keepCase: true,返回 snake_case 字段名
- tss-handler.ts 的 handleIncomingMessage 期望 camelCase 字段名
- 导致 message_id, from_party, is_broadcast 等字段无法正确读取
- TSS 进程无法收到正确的消息,keygen 无法完成

修复:
- handleIncomingMessage 参数改为 snake_case (message_id, from_party, is_broadcast)
- 内部转换为 camelCase 格式后处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:53:26 -08:00
hailin 674bc9e5cd fix(mpc-system): GetSessionStatus API 返回 threshold_t 和 threshold_n
问题:
- Account 服务的 GetSessionStatus HTTP API 没有返回 threshold 字段
- 导致 service-party-app 获取到的 threshold 始终是 0
- TSS keygen 无法使用正确的阈值参数

修复:
- Account gRPC client 添加 ThresholdT 和 ThresholdN 字段映射
- Account HTTP handler 返回 threshold_t 和 threshold_n
- service-party-app 优先使用后端返回的 threshold 值
- checkAndTriggerKeygen 使用后端 threshold 更新 activeKeygenSession

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:43:59 -08:00
hailin fb1b27e36f fix(service-party-app): 切换 session 时重新订阅消息流
问题:
- prepareForKeygen 只检查 isPrepared 标志
- 当旧 session 失败后 isPrepared 可能仍为 true
- 新 session 调用 prepareForKeygen 时直接跳过,没有重新订阅
- 导致 external party 仍订阅旧 session 的消息流
- server parties 发送的 TSS 消息无法到达 external party

修复:
- 检查 sessionId 是否变化
- 如果是新 session,先取消旧订阅再重新订阅

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:27:01 -08:00
hailin 989364969d fix(service-party-app): 修复 gRPC 响应字段名 snake_case 问题
问题:
- proto-loader 使用 keepCase: true,导致 gRPC 响应字段为 snake_case
- TypeScript 接口使用 camelCase,导致字段不匹配
- joinSession 响应的 session_info.threshold_t 和 threshold_n 无法读取
- 导致 activeKeygenSession.threshold 为 {t: 0, n: 0}
- TSS 进程收到错误的 threshold 参数导致 exit code 1

修复:
- grpc-client.ts 接口改为 snake_case 以匹配 proto 定义
- main.ts 更新为使用 snake_case 字段名
- SessionEvent 处理转换为 camelCase 再传递给 handleSessionStart

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:14:30 -08:00
hailin 1b48c05aa7 fix(mpc-system): GetSessionStatus 返回实际的 threshold_n 和 threshold_t
问题:
- Message Router 的 GetSessionStatus 把 TotalParties 当作 ThresholdN 返回
- 导致 server-party 收到错误的 threshold_n=2 而不是 3
- TSS 协议无法正确启动(参与者数量验证失败)

修复:
- 在 session_coordinator.proto 添加 threshold_n 和 threshold_t 字段
- Session Coordinator 返回实际的 threshold 值
- Message Router 透传 threshold 值而不是参与者数量

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:59:53 -08:00
hailin 422d7007b1 fix(service-party-app): 补全 getSessionStatus 返回的 threshold 和 participants
问题:
- Session.tsx 期望 session 对象有 threshold 和 participants 字段
- 但 grpc:getSessionStatus 只返回了基础字段
- 导致前端显示 参与方 (0 / 0)

修复:
- 从 activeKeygenSession 获取 threshold 信息
- 从 API 返回的 participants 构建完整的参与者列表
- 添加 walletName, currentRound, totalRounds 字段

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:54:14 -08:00
hailin c94f3e4d83 debug(service-party-app): 添加 TSS 进程详细调试日志
- 输出二进制文件路径和存在性检查
- 输出传递给 TSS 的参与者列表 JSON
- 输出完整的命令行参数
- 收集并输出 stderr 内容
- 帮助诊断 TSS 进程 exit code 1 问题

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:47:37 -08:00
hailin aa9171ce2c fix(service-party-app): 修复 threshold 为 undefined 导致的崩溃
问题:
- Session.tsx 直接访问 session.threshold.n 和 session.threshold.t
- 当后端返回的 session 数据中 threshold 为 undefined 时崩溃

修复:
- 添加空值检查 session.threshold?.n || 0
- 阈值信息部分添加条件渲染

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:37:09 -08:00
hailin 30ec0a1c8e fix(service-party-app): 修复 participants 为 undefined 导致的崩溃
问题:
- Session.tsx 和 Home.tsx 直接访问 participants.length
- 当后端返回的 session 数据中 participants 为 undefined 时崩溃
- 导致 TypeError: Cannot read properties of undefined (reading length)

修复:
- 添加空值检查 (session.participants || []).length
- 使用 Math.max(0, ...) 防止负数长度

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:30:30 -08:00
hailin b0a698250d fix(service-party-app): 在 package.json 的 build 配置中添加 afterPack
问题:
- electron-builder 加载的是 package.json 的 build 字段
- 而不是单独的 electron-builder.json 文件
- 导致 afterPack hook 没有被执行

修复:
- 在 package.json 的 build 配置中添加 afterPack 引用

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:20:35 -08:00
hailin 072fbbad2c fix(service-party-app): 使用 afterPack hook 确保 TSS 二进制文件被正确打包
问题:
- extraResources 的 ${platform}-${arch} 宏在 from 路径中可能不可靠
- 参考: https://github.com/electron-userland/electron-builder/issues/7891

解决:
- 创建 afterPack.js hook 手动复制对应平台/架构的二进制文件
- 移除 extraResources 配置,改用 hook 方式
- 确保 tss-party 二进制文件被正确复制到 resources/bin/ 目录

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:14:39 -08:00
hailin 9b9f6f143e fix(service-party-app): 将 tss-party 二进制文件打包进应用
- 添加 extraResources 配置将 bin/${platform}-${arch} 目录包含到打包资源中
- 修复打包后的应用找不到 tss-party.exe 导致 TSS 协议无法执行的问题
- 二进制文件会被复制到 resources/bin/ 目录

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:10:38 -08:00
hailin b48b59d946 fix(service-party-app): 开发模式默认使用真实 TSS Handler
问题:
- 开发模式自动使用 MockTSSHandler
- MockTSSHandler 不发送真正的 TSS 网络消息
- 导致 co_managed_keygen 无法完成

修复:
- 移除 NODE_ENV === 'development' 的自动 mock 逻辑
- 只有显式设置 USE_MOCK_TSS=true 时才使用 Mock Handler
- 开发模式现在默认使用真实的 TSSHandler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:07:27 -08:00
hailin b938722ff6 fix(service-party-app): 保留正确的 partyIndex 不覆盖
问题:
- handleSessionStart 中使用 forEach 的 index 作为 partyIndex
- 这会覆盖 checkAndTriggerKeygen 已经从服务器获取的正确 partyIndex
- 导致 TSS 协议使用错误的 partyIndex

修复:
- 优先使用 existing.partyIndex(从服务器获取的正确值)
- 只有找不到已有信息时才使用 fallback
- 按 partyIndex 排序确保顺序正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:59:33 -08:00
hailin e72f96da10 feat(service-party-app): 验证成功后自动加入会话
- 移除手动输入名称和点击"确认加入"按钮的步骤
- 验证邀请码成功后自动触发 joinSession
- 生成默认参与者名称(参与者-xxxx 格式)
- 保留错误处理和重试功能
- 减少用户操作步骤,提高 co_managed_keygen 可靠性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:48:41 -08:00
hailin bd6537a2cb fix(service-party-app): checkAndTriggerKeygen 改为轮询等待
问题:
- 原来 checkAndTriggerKeygen 只检查一次
- 如果首次检查时会话状态还不是 in_progress,就直接返回
- 导致 external party 永远不触发 keygen

修复:
- 改为与 server-party 的 waitForAllParticipants 一致的轮询逻辑
- 2 秒轮询间隔,最多等待 5 分钟
- 持续检查直到所有参与者加入且状态正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:44:29 -08:00
hailin dfead071ab fix(service-party-app): 修复 co_managed_keygen 消息丢失问题
问题:
- service-party-app 在 joinSession 后有 1 秒延迟才开始 keygen
- server-party 检测到所有参与者后立即发送 TSS Round 0 消息
- service-party-app 此时还没订阅消息流,导致消息丢失
- TSS 协议无法完成

修复:
- TSSHandler 新增 prepareForKeygen() 方法,在 joinSession 后立即订阅消息
- 新增 isPrepared 状态,在预订阅阶段也能缓冲消息
- handleIncomingMessage 支持 isPrepared || isRunning 时缓冲消息
- participateKeygen 保留预订阅阶段缓冲的消息,不重复订阅
- main.ts 在 joinSession 成功后立即调用 prepareForKeygen()
- 移除 1 秒延迟,改用 setImmediate 立即触发 keygen

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:35:39 -08:00
hailin 820a61793c fix(service-party-app): 添加等待所有参与者加入的逻辑
- 在 checkAndTriggerKeygen 中添加参与者数量检查
- 必须等待所有 N 个参与者加入后才能开始 keygen
- 与 server-party 的 waitForAllParticipants 逻辑保持一致
- 修复 co_managed_keygen 场景下 TSS 协议无法完成的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:18:38 -08:00
hailin a22fc16313 fix(session-coordinator): 修复 FindExpired SQL 时区问题
- expires_at 存储为 UTC 时间
- 查询时使用 NOW() AT TIME ZONE 'UTC' 确保时区一致
- 避免因时区差异导致 session 过早被标记为过期

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:07:28 -08:00
hailin e222279d77 fix(server-party): co_managed_keygen 等待所有参与者加入后再开始 keygen
- Message Router GetSessionStatus 透传 participants 列表
- Server Party 新增 GetSessionStatusFull 方法获取完整会话状态
- participate_keygen.go 对 co_managed_keygen 类型轮询等待所有 N 个参与者加入
- 不影响原有 keygen/sign 功能(仅 co_managed_keygen 触发等待逻辑)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:55:52 -08:00
hailin 48c8c071d5 fix(server-party): 支持 co_managed_keygen 会话类型
server-party 的 ParticipateKeygenUseCase 现在同时接受 "keygen" 和
"co_managed_keygen" 两种会话类型,使 persistent party 能够正确参与
共管钱包的密钥生成流程。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:24:44 -08:00
hailin 9bc48d19a9 fix(mpc-system): 修复 co_managed_keygen 参与者 party_index 映射问题
- 在 proto 中添加 ParticipantStatus 消息和 participants 字段
- session-coordinator 返回参与者详细信息(含 party_index)
- account 服务透传 participants 到 HTTP 响应
- service-party-app 使用服务器返回的 party_index 而非数组索引
- 同时返回 join_tokens map 和 join_token 字符串以兼容两种格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:06:13 -08:00
hailin 0ca37ee76a feat(mpc-system): 增强连接可靠性和消息去重机制
后端改进:
- SessionEventBroadcaster: 重连时自动关闭旧 channel 防止内存泄漏
- MessageBroker: 重连时关闭旧的 party/session channel
- SubscribeMessages: 订阅时自动发送数据库中的 pending 消息

客户端改进:
- GrpcClient: 添加自动重连机制(指数退避,最多10次)
- GrpcClient: 断开/重连/失败事件通知前端
- TSSHandler: 消息缓冲机制,进程启动前缓存收到的消息
- TSSHandler: 客户端本地消息去重,防止重连后重复处理
- Database: 添加 processed_messages 表和相关操作方法
- Main: Keygen 幂等性保护,防止重复触发
- Main: 会话事件缓存,解决前端订阅时序问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 07:37:03 -08:00
hailin df8a14211e debug(mpc-system): 添加 joinToken 调试日志
- service-party-app: validateInviteCode 记录 token 长度
- service-party-app: joinSession 记录 token 信息
- service-party-app: 修复 ValidateInviteCodeResult 类型缺少 joinToken 字段
- session-coordinator: JoinSession 记录 token 解析详情

用于调试 "invalid token" 错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:55:46 -08:00
hailin 5f4c7c135f feat(mpc-system): 完善 co_managed_keygen 流程并添加调试控制台
主要改动:
- service-party-app: 发起方创建会话后自动加入并设置 activeKeygenSession
- service-party-app: 添加轮询机制确保 100% 可靠触发 keygen
- service-party-app: 添加 DebugConsole 组件 (Ctrl+Shift+D 打开)
- service-party-app: 主进程添加 debugLog 系统,日志可实时显示到前端
- session-coordinator: JoinSession 加入 messageRouterClient 发布事件
- session-coordinator: 添加 PublishSessionStarted 方法

修复:
- 发起方不设置 activeKeygenSession 导致无法触发 keygen 的问题
- 加入方可能错过 session_started 事件的时序问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:32:40 -08:00
hailin a5ab2e8350 fix(session-coordinator): 支持 co_managed_keygen 动态参与者加入
问题: 通过邀请码加入共管钱包会话时报 "party not invited" 错误
原因: 外部参与者不在 party pool 中,CreateSession 时无法预先选择

修复:
- join_session.go: 对于 co_managed_keygen + wildcard token,允许动态添加参与者
- create_session.go: 新增 selectPartiesByCompositionForCoManaged,跳过 TemporaryCount 选择
- report_completion.go: 使用 IsKeygen() 方法,co_managed_keygen 完成后也创建账户记录

注意: 所有修改仅对 co_managed_keygen 类型生效,不影响现有 keygen/sign 流程

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 04:25:11 -08:00
hailin af08f0f9c6 fix(mpc-system): 修复通过邀请码加入会话时 invalid token 错误
问题: 通过邀请码查询会话后加入时报 "13 INTERNAL: invalid token"
原因: GetSessionByInviteCode API 没有返回 join_token

修复:
- account-service: GetSessionByInviteCode 在查询时生成新的 wildcard join token
- account-service: CoManagedHTTPHandler 添加 jwtService 依赖注入
- service-party-app: validateInviteCode 返回 join_token
- service-party-app: Join.tsx 保存并使用 joinToken 和 partyId
- service-party-app: preload.ts joinSession 使用正确的参数格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:40:36 -08:00
hailin 21985abde5 fix(session-coordinator): 保存 WalletName 和 InviteCode 到数据库
- CreateSessionInput 添加 WalletName 和 InviteCode 字段
- gRPC handler 从请求中读取并传递这些字段
- CreateSession use case 在创建会话时设置这些字段

修复: 通过邀请码查询会话时找不到记录的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:07:44 -08:00
hailin 591dc50eb9 fix(service-party-app): 创建会话时添加 initiator_party_id 参数
- CreateKeygenSessionRequest 添加 initiator_party_id 和 initiator_name 字段
- 创建会话前检查是否已连接到消息路由器
- 自动获取已注册的 partyId 作为发起者

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:54:43 -08:00
hailin 19e366e0d9 fix(service-party-app): 修复 Account 服务 URL 为 rwaapi.szaiai.com
api.szaiai.com 被 OSS/CDN 拦截,改用 rwaapi.szaiai.com 直接访问 Kong 网关

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:45:23 -08:00
hailin 551f3d27d2 feat(api-gateway): 添加 MPC Account Service 路由配置
添加共管钱包 API 路由,将 /api/v1/co-managed/* 请求转发到 account-service (端口 4000)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:31:56 -08:00
hailin b1234bc434 feat(admin-web): 添加 TSS WASM 集成,实现与 Service-Party-App 功能对等
## 功能概述
Admin-Web 现在可以作为独立的 TSS 参与方参与共管钱包创建,
与 Service-Party-App 桌面应用功能完全对等。

## 主要变更

### 1. TSS WASM 模块 (backend/mpc-system/services/tss-wasm/)
- main.go: Go WASM 模块,封装 bnb-chain/tss-lib
- 支持 keygen 和 signing 操作
- 通过 syscall/js 与 JavaScript 通信

### 2. Admin-Web TSS 库 (frontend/admin-web/src/lib/tss/)
- tss-wasm-loader.ts: WASM 加载器
- tss-client.ts: 高级 TSS 客户端 API
- grpc-web-client.ts: gRPC-Web 客户端连接 Message Router

### 3. 本地存储模块 (frontend/admin-web/src/lib/storage/)
- share-storage.ts: IndexedDB 加密存储
- 使用 AES-256-GCM 加密,PBKDF2 密钥派生

### 4. React Hooks
- useTSSClient.ts: TSS 客户端状态管理
- useShareStorage.ts: 存储操作封装

### 5. 组件更新
- CreateWalletModal.tsx: 集成 TSS 客户端
  - 添加密码保护对话框
  - 实现真实 keygen 流程
  - 自动保存 share 到 IndexedDB
- CoManagedWalletSection.tsx: 使用真实 API
- coManagedWalletService.ts: API 服务层

### 6. WASM 文件
- frontend/admin-web/public/wasm/tss.wasm (~19MB)
- frontend/admin-web/public/wasm/wasm_exec.js (Go 运行时)

## 技术栈
- Go 1.21+ (WASM 编译)
- bnb-chain/tss-lib v2.0.2 (TSS 协议)
- Web Crypto API (AES-256-GCM)
- IndexedDB (本地存储)
- gRPC-Web (消息路由)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:39:43 -08:00
hailin be94a6ab18 fix(server-party): session 事件订阅断开后自动重连
Message Router 重启后,server-party 的 gRPC stream 会断开,
之前的实现会直接退出 goroutine 导致无法收到新的 session 事件。

修改内容:
- 添加自动重连逻辑,stream 断开时会尝试重新订阅
- 使用指数退避策略,从 1 秒到最大 30 秒
- 重连成功后重置退避时间

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:25:30 -08:00
hailin 40a257e55c fix(mpc-system): 开发模式添加 message-router gRPC 端口映射
添加 50051:50051 端口映射,使开发模式与生产模式保持一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 00:56:04 -08:00
hailin e78b6e6dcb fix(service-party-app): 延迟加载 proto 定义避免启动时崩溃
将 proto 文件加载改为延迟加载模式,在 connect() 时才加载,
避免模块加载时 app.isPackaged 还未准备好导致的路径错误。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:38:42 -08:00
hailin 4794cafdaa fix(service-party-app): 改为非阻塞方式连接 Message Router
将 connectAndRegisterToMessageRouter() 改为非阻塞调用,
不再使用 await 阻塞应用启动。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:34:10 -08:00
hailin 28da7f6807 feat(service-party-app): 实现启动时自动注册到 Message Router,状态验证真实化
## 主要变更

### 1. 启动时自动连接并注册
- main.ts: 添加 `connectAndRegisterToMessageRouter()` 函数
- 应用启动时自动连接到 Message Router 并注册为 temporary 角色
- 自动生成并持久化 partyId(使用 crypto.randomUUID)
- 自动订阅会话事件

### 2. 状态验证真实化
- appStore.ts: 重写 `checkAllServices()` 消息路由检测逻辑
- 不再只检测连接成功,而是:
  1. 调用 isConnected() 检查连接状态
  2. 调用 getPartyId() 检查是否已注册
  3. 调用 getRegisteredParties() 从 Message Router 获取注册列表
  4. 验证自己的 partyId 是否在列表中
- 状态显示更准确:
  - "未连接到 xxx" - 未连接
  - "已连接但未注册" - 已连接但没注册
  - "已注册 (在线)" - 完全正常
  - "注册验证失败" - 注册了但验证失败

### 3. 新增 IPC API
- grpc:getPartyId - 获取当前 partyId
- grpc:isConnected - 检查连接状态
- grpc:connect - 连接到 Message Router
- grpc:register - 注册为参与方

### 修改的文件
- electron/main.ts
- electron/preload.ts
- src/stores/appStore.ts
- src/types/electron.d.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:29:04 -08:00
hailin 73034c072c feat(service-party-app): 添加获取已注册参与方列表API
新增 grpc.getRegisteredParties() API,用于查询 Message Router 中已注册的参与方:
- grpc-client.ts: 添加 getRegisteredParties() 方法
- main.ts: 添加 IPC 处理器
- preload.ts: 暴露 API 到渲染进程
- electron.d.ts: 添加类型定义

此功能用于测试和调试,确认 Service-Party-App 是否成功注册到 Message Router。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:50:46 -08:00
hailin de29fa4800 feat(co-managed-wallet): 添加签名会话API和Service-Party-App HTTP客户端
## Account Service 新增 API
- GET /api/v1/co-managed/sessions/by-invite-code/:inviteCode - 通过邀请码查询keygen会话
- POST /api/v1/co-managed/sign - 创建签名会话
- GET /api/v1/co-managed/sign/by-invite-code/:inviteCode - 通过邀请码查询签名会话

## Service-Party-App 变更
- 新增 account-client.ts HTTP客户端模块
- 集成Account服务API到Electron主进程
- 添加account相关IPC处理器
- 更新preload.ts暴露account API到渲染进程
- Settings页面添加Account服务URL配置

## 文档更新
- 更新 docs/service-party-app.md 反映实际实现
- 添加Account Service HTTP API说明
- 添加签名流程文档

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:34:35 -08:00
hailin 81c8db9d50 fix(service-party-app): 修复Kava API健康检查逻辑
问题: Kava API检测失败,原因是使用测试地址查询余额的方式不可靠

解决方案:
1. 添加 healthCheck() 方法到 KavaTxService,查询最新区块
2. 添加 kava:healthCheck IPC 处理器
3. 更新 appStore 使用 healthCheck API 而非 getBalance

修改的文件:
- kava-tx-service.ts: 添加 healthCheck() 方法
- main.ts: 添加 kava:healthCheck IPC 处理器
- preload.ts: 暴露 healthCheck API
- appStore.ts: 使用 healthCheck 检测 Kava API
- electron.d.ts: 添加 KavaHealthCheckResult 类型

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 21:01:27 -08:00
hailin a2508ab0fd fix(service-party-app): 修复sql.js在打包后无法加载的问题
问题: Electron打包后sql.js模块报"Cannot find module"错误

解决方案:
1. 使用extraResources将sql-wasm.wasm复制到resources目录
2. 修改database.ts使用wasmBinary方式加载WASM文件
3. 直接读取WASM文件作为ArrayBuffer,避免模块解析问题

修改的文件:
- package.json: 添加extraResources配置复制WASM文件
- database.ts: 使用fs.readFileSync读取WASM并传递给initSqlJs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:50:28 -08:00
hailin 761e03ebb0 fix(service-party-app): 修复sql.js在打包后找不到模块的问题
## 问题
打包后的应用运行时报错 "Cannot find module 'sql.js'"

## 解决方案

### 1. electron-builder 配置
- 添加 `asarUnpack` 配置,将 sql.js 解压到 asar.unpacked 目录
- 将 `node_modules/sql.js/**/*` 添加到 files 列表

### 2. database.ts 修改
- 添加 `getSqlJsWasmPath()` 函数,根据环境返回正确的 WASM 路径
- 开发环境: node_modules/sql.js/dist/sql-wasm.wasm
- 生产环境: app.asar.unpacked/node_modules/sql.js/dist/sql-wasm.wasm
- 使用 locateFile 配置指定 WASM 文件位置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:41:01 -08:00
hailin f5cbc855f6 feat(service-party-app): 添加应用状态检测和启动检查功能
## 新增功能

### 1. 启动检测页面 (StartupCheck)
- 应用启动时显示环境检测界面
- 检测三个核心服务: 本地数据库、消息路由、Kava API
- 检测完成后自动进入主界面 (1.5秒延迟)
- 支持查看详细错误信息
- 即使部分服务异常也可进入应用

### 2. 应用状态管理 (appStore)
- 使用 Zustand 管理全局应用状态
- 跟踪各服务的连接状态: unknown/checking/connected/disconnected/error
- 支持操作进度跟踪 (keygen/sign)
- 提供状态辅助函数: getStatusColor, getStatusText, getOverallStatus

### 3. 侧边栏状态面板
- 实时显示三个服务的连接状态
- 显示当前操作进度 (keygen/sign 时)
- 支持手动刷新检测
- 显示整体就绪状态

## 新增文件
- src/stores/appStore.ts: 应用状态管理
- src/components/StartupCheck.tsx: 启动检测组件
- src/components/StartupCheck.module.css: 启动检测样式

## 修改文件
- src/App.tsx: 集成启动检测流程
- src/components/Layout.tsx: 添加状态面板
- src/components/Layout.module.css: 状态面板样式
- src/types/electron.d.ts: 添加 metadata 字段兼容

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:33:00 -08:00
hailin 6b2b9e821e fix(service-party-app): 更新build-windows.bat支持clean选项
添加命令行参数支持:
- build-windows.bat          正常构建
- build-windows.bat clean    清理构建产物后重建
- build-windows.bat cleanall 完全清理(含node_modules)后重建

在其他电脑上首次编译时,建议使用:
  build-windows.bat cleanall

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:17:27 -08:00
hailin eb283389c4 fix(service-party-app): 添加bech32类型声明和清理脚本
## 变更

### 1. 添加 bech32 类型声明
- 新增 electron/types/bech32.d.ts 手动声明模块类型
- 解决跨机器编译时找不到 bech32 类型的问题

### 2. 添加清理脚本
- npm run clean: 清理构建产物 (dist, dist-electron, release)
- npm run clean:all: 完全清理 (包括 node_modules)
- npm run rebuild: 清理后重新构建
- npm run rebuild:win: 清理后重新构建 Windows 版本

## 跨机器编译说明

在新电脑上编译时,建议执行:
```bash
npm run clean:all
npm install
npm run build:win
```

或使用一键重建:
```bash
npm run rebuild:win
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:14:17 -08:00
hailin 59b0e2bb22 fix(service-party-app): 移除不兼容的@types/bech32
bech32 v2.0.0 自带TypeScript类型定义,不需要单独的
@types/bech32 包(该包是针对v1.x版本的)。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:10:05 -08:00
hailin 3f25424049 fix(service-party-app): 添加bech32类型定义修复编译错误
添加 @types/bech32 开发依赖以解决 TypeScript 编译时
找不到 bech32 模块类型声明的问题。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:07:13 -08:00
hailin c97cd208ab feat(service-party-app): 添加SQLite存储和Kava区块链集成
## 主要变更

### 1. SQLite 本地存储 (sql.js)
- 使用 sql.js (纯 JavaScript SQLite) 替代 better-sqlite3
- 无需本地数据库服务,跨平台兼容
- 表结构: shares, derived_addresses, signing_history, settings
- AES-256-GCM 加密 share 数据,PBKDF2 密钥派生

### 2. Kava 区块链集成
- 新增 kava-tx-service.ts: REST API 交易服务
  - 余额查询 (ukava/KAVA)
  - 交易构建和广播
  - 交易状态查询
- 支持多个备用端点自动切换

### 3. 地址派生
- 新增 address-derivation.ts: 多链地址派生
- 支持 Kava, Cosmos, Osmosis, Ethereum 等链
- 使用 Node.js crypto 替代 @noble/hashes 以解决模块兼容问题
- 手动实现 secp256k1 公钥解压缩

### 4. IPC 处理器
- main.ts: 添加 Kava 相关 IPC 处理器
- preload.ts: 暴露 kava API 给渲染进程
- electron.d.ts: 完整的 TypeScript 类型定义

## 新增文件
- electron/modules/database.ts
- electron/modules/address-derivation.ts
- electron/modules/kava-client.ts
- electron/modules/kava-tx-service.ts
- electron/types/sql.js.d.ts
- src/utils/address.ts
- .gitignore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 19:45:45 -08:00
hailin 76ef8b0a8c fix(service-party-app): 修复gRPC测试连接方法
将testConnection从URL解析改为直接使用host:port格式,
与grpc-client.ts的connect方法保持一致。

地址格式: mpc-grpc.szaiai.com:443 (自动检测TLS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:48:04 -08:00
hailin 2a11392ce2 fix(nginx): 配置文件使用.conf后缀以匹配nginx include规则
nginx.conf 使用 include /etc/nginx/sites-enabled/*.conf
因此配置文件必须以 .conf 结尾才能被加载。

变更:
- 添加 DOMAIN_CONF 变量 (mpc-grpc.szaiai.com.conf)
- 更新所有文件路径使用 .conf 后缀
- 卸载时兼容新旧文件名

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:39:45 -08:00
hailin e268c33fa9 fix(nginx): 集成certbot目录创建到安装脚本
在安装脚本的configure_http步骤中添加:
- 创建完整的webroot目录结构: /var/www/certbot/.well-known/acme-challenge
- 设置正确的权限: chmod -R 755

这确保Let's Encrypt验证能正常工作,解决404错误问题。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:29:59 -08:00
hailin c457d15829 feat(co-managed-wallet): 添加分布式共管钱包 API 和 gRPC 代理
## 功能概述
实现分布式多方共管钱包创建功能的后端 API 和网络基础设施,
支持 Service Party App 通过公网连接参与 TSS 协议。

## 主要变更

### 1. Account Service - 共管钱包 API (新增)
- 新增 co_managed_handler.go - 独立的共管钱包 HTTP handler
- 新增 API 端点:
  - POST /api/v1/co-managed/sessions - 创建共管钱包会话
  - POST /api/v1/co-managed/sessions/:id/join - 加入会话
  - GET /api/v1/co-managed/sessions/:id - 获取会话状态
- 扩展 session_coordinator_client.go:
  - 添加 CreateCoManagedKeygenSession 方法
  - 添加 JoinSession 方法
  - 添加响应类型定义
- 更新 main.go 注册新路由 (SkipPaths 免认证)

### 2. Nginx gRPC 代理 (新增)
- 新增 mpc-grpc.szaiai.com.conf - gRPC over TLS 代理配置
- 新增 install-mpc-grpc.sh - 自动化安装脚本
- 支持 Let's Encrypt SSL 证书
- 代理到后端 Message Router (192.168.1.111:50051)

### 3. Service Party App 更新
- grpc-client.ts: 支持 TLS 连接,自动检测端口 443
- Settings.tsx: 默认地址改为 mpc-grpc.szaiai.com:443
- Home.tsx/Create.tsx: UI 样式优化

## 架构

```
Service Party App (用户电脑)
        │
        │ gRPC over TLS (端口 443)
        ▼
Nginx (mpc-grpc.szaiai.com:443)
        │
        │ grpc_pass
        ▼
Message Router (192.168.1.111:50051)
        │
        ▼
Session Coordinator → Server Parties
```

## 100% 不影响现有功能

- 所有修改均为新增代码,不修改现有逻辑
- 共管钱包 API 完全独立于现有 RWADurian 系统
- Nginx 配置为独立文件,不影响现有 rwaapi.szaiai.com
- 使用现有 proto 定义 (co_managed_keygen, wallet_name, invite_code)

## 部署步骤

1. DNS: 添加 mpc-grpc.szaiai.com A 记录
2. 安装: sudo ./install-mpc-grpc.sh
3. 验证: curl https://mpc-grpc.szaiai.com/health

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:11:57 -08:00
hailin a830a88cc3 feat(service-party-app): 添加签名功能并重命名应用
## 新增功能
- 添加"参与签名"页面 (Sign.tsx)
- 支持选择本地 share 参与 TSS 签名
- 支持导入备份文件参与签名
- 签名进度实时显示

## 应用重命名
- 应用名称改为"榴莲皇后绿积分共管账户服务"
- 更新 package.json productName
- 更新 index.html title
- 更新侧边栏 logo 文字

## 代码完善
- 完善 preload.ts API 定义
- 添加 main.ts IPC 处理器
- 更新 electron.d.ts 类型定义
- 添加 storage.ts saveSettings 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 08:00:00 -08:00
hailin 7cfaacc833 fix(service-party-app): 修改默认阈值为 3-of-5
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:50:15 -08:00
hailin 47328c67d7 fix(service-party-app): 修复路由和启动问题
1. 将 BrowserRouter 改为 HashRouter - Electron 使用 file:// 协议
2. 移除生产环境自动打开浏览器的代码
3. HTTP 服务器仅在开发模式下启动

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:45:43 -08:00
hailin 15cbb2401f fix(service-party-app): 修复 proto 文件打包路径问题
- 复制 message_router.proto 到 service-party-app/proto/
- 修改 grpc-client.ts 使用 process.resourcesPath 加载 proto 文件
- 使用 extraResources 将 proto 文件打包到 resources 目录外

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:39:55 -08:00
hailin e43500fc3f fix(service-party-app): 修复 electron-builder files 配置
- 将 electron/**/* 改为 dist-electron/**/* (编译后的文件)
- 添加 proto/**/* (gRPC proto 文件)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:35:26 -08:00
hailin 7cec5b2b4c fix(service-party-app): 修复 gRPC 客户端 TypeScript 类型错误
添加 ProtoPackage 接口定义 proto 包结构类型,避免类型推断错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:33:10 -08:00
hailin 1f476e8e5a fix(service-party-app): 修复 Electron 主进程编译配置
- 新增 tsconfig.electron.json 单独编译 Electron 主进程到 dist-electron/
- 更新 package.json main 入口为 dist-electron/main.js
- 更新 build 脚本先编译 electron 再 vite build

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:31:26 -08:00
hailin fcaa57605a fix(service-party-app): fix TypeScript compilation errors
- Fix import/export consistency (use default exports)
- Add CSS module type declarations
- Fix ElectronAPI type definitions (ListSharesResult, ExportShareResult)
- Fix null checks for sessionInfo and session
- Change build script to use npx tsc

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:27:12 -08:00
hailin 88370691d1 fix(service-party-app): fix build script and remove icon requirement
- Rewrite build-windows.bat in English to avoid encoding issues
- Remove icon configuration from electron-builder.json (use default)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:19:19 -08:00
hailin 8733e49735 feat(service-party-app): 添加 Windows 一键编译脚本
添加 build-windows.bat 脚本,支持:
- 检查 Node.js 和 Go 环境
- 编译 TSS 子进程 (tss-party.exe)
- 安装 npm 依赖
- 编译 Electron 应用

使用方法: 双击运行 build-windows.bat

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:07:43 -08:00
hailin 9e21d8c8cd feat(api-gateway): 添加移动端系统维护接口的 Kong 路由
添加 /api/v1/mobile/system 路由到 admin-service,
使移动端可以访问 /mobile/system/maintenance-status 接口
检查系统维护状态。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 06:36:02 -08:00
hailin 0781c53101 fix(admin-service): 修复 getCurrentStatus 方法使用旧响应格式的问题
AdminMaintenanceController.getCurrentStatus() 方法仍使用旧的 inMaintenance 字段,
导致构建失败。更新为与 MobileMaintenanceController 一致的新格式:
- 使用 isUnderMaintenance 代替 inMaintenance
- 使用嵌套的 maintenance 对象包含详情
- 添加 remainingMinutes 字段计算

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 06:11:54 -08:00
hailin 6c4a40c42d fix(migration): 使数据库迁移脚本幂等化,支持重复执行
将 008_add_co_managed_wallet_fields.up.sql 改为幂等脚本:
- 使用 DO $$ ... IF NOT EXISTS 检查列是否存在再添加
- 使用 CREATE INDEX IF NOT EXISTS 创建索引
- 使用 DROP CONSTRAINT IF EXISTS 删除约束

这确保迁移脚本可以安全地多次执行,不会因列/索引已存在而失败。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 05:26:38 -08:00
hailin 75a9ffadef fix(admin-service): 修复移动端维护状态API响应格式不匹配问题
移动端期望的格式:
{
  "isUnderMaintenance": true,
  "maintenance": { "title", "message", "startTime", "endTime", "remainingMinutes" }
}

后端之前返回的格式:
{
  "inMaintenance": true,
  "title", "message", "endTime"
}

修改内容:
- 字段名 inMaintenance → isUnderMaintenance
- 嵌套维护详情到 maintenance 对象
- 添加 startTime 和 remainingMinutes 字段

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 05:10:18 -08:00
hailin cc3644de9d feat(mpc-system): 添加单服务管理命令到deploy.sh
新增命令:
- start-svc: 启动单个服务
- stop-svc: 停止单个服务
- restart-svc: 重启单个服务
- rebuild-svc: 重建并重启服务 (支持--no-cache)

支持开发模式和生产模式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 04:23:22 -08:00
hailin 1af5780b19 fix(admin-service): 修复共管钱包 status 类型不匹配问题
使用 Prisma 生成的类型替代手动定义的接口:
- PrismaCoManagedWalletSession -> @prisma/client
- PrismaCoManagedWallet -> @prisma/client
- status 字段使用 PrismaWalletSessionStatus 枚举类型

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 00:02:18 -08:00
hailin e51450d9f9 chore(admin-service): 添加系统维护和共管钱包的数据库迁移
添加缺失的 migration 文件,包含:
- system_maintenances 表 (系统维护公告)
- WalletSessionStatus 枚举
- co_managed_wallet_sessions 表 (共管钱包会话)
- co_managed_wallets 表 (共管钱包记录)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:36:42 -08:00
hailin 1b5bcf3fda fix(co-managed-wallet): 修复向后兼容性问题并完善protobuf定义
## 变更概述
根据用户反馈,将 Session Coordinator 的函数签名改为可选参数模式,
确保新功能 100% 不影响现有的 keygen/sign 功能。

## 主要变更

### 1. Session Coordinator 向后兼容修复
- 保留原有 `ReconstructSession` 函数签名不变
- 新增 `ReconstructSessionOptions` 结构体存放可选参数
- 新增 `ReconstructSessionWithOptions` 函数支持新字段
- 原函数内部调用新函数,传入 nil options

### 2. Protobuf 定义更新
- CreateSessionRequest 新增字段:
  - wallet_name (field 10): 钱包名称
  - invite_code (field 11): 邀请码
- SessionInfo 新增字段:
  - wallet_name (field 8): 钱包名称
  - invite_code (field 9): 邀请码
- session_type 支持 "co_managed_keygen"

### 3. TSS Party 子进程修复
- 修复 tss.NewPartyID 参数类型错误 (big.Int)
- 修复 go.mod 依赖问题 (ed25519 replace)
- 删除未使用的变量

### 4. 清理错误生成的文件
- 删除 api/proto/*.pb.go (错误位置)
- 保留 api/grpc/coordinator/v1/*.pb.go (正确位置)

## 修改的文件

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| mpc_session.go | 修改 | 添加 ReconstructSessionWithOptions |
| session_postgres_repo.go | 修改 | 使用新函数传入 options |
| session_cache_adapter.go | 修改 | 使用新函数传入 options |
| session_coordinator.proto | 修改 | 添加 wallet_name, invite_code 字段 |
| session_coordinator.pb.go | 重新生成 | 包含新 protobuf 字段 |
| tss-party/main.go | 修复 | NewPartyID 参数和未使用变量 |
| tss-party/go.mod | 修复 | ed25519 依赖替换 |

## 向后兼容性保证

- 所有现有代码调用 ReconstructSession 无需任何修改
- 数据库使用 COALESCE 处理 NULL 值
- Protobuf 新字段使用高序号,不影响现有消息解析
- **影响现有功能的风险: 0%**

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:33:40 -08:00
hailin dc16a616a5 fix(identity-service): 修复并发auto-login请求导致的唯一约束冲突
- 在创建新token前先撤销该设备的旧token
- 使用upsert替代create避免并发时refresh_token_hash唯一约束冲突

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:27:21 -08:00
hailin c328d8b59b feat(mobile-app,admin): 添加系统维护功能和通知徽章功能
系统维护功能:
- 后端: 添加系统维护配置实体、仓库和控制器
- 后端: 添加维护模式拦截器,返回503状态码
- admin-web: 添加系统维护管理页面,支持创建/编辑/开关维护配置
- mobile-app: 添加维护状态检查服务和阻断弹窗
- mobile-app: 在启动页、向导页集成维护检查
- mobile-app: 支持App从后台恢复时自动检查维护状态

通知徽章功能:
- 添加通知徽章Provider,监听登录状态自动刷新
- 底部导航栏"我的"标签显示未读通知红点
- 进入通知页面自动刷新徽章状态
- 切换账号、退出登录自动清除徽章

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:26:01 -08:00
hailin fea01642e7 feat(co-managed-wallet): 添加分布式多方共管钱包创建功能
## 功能概述
实现分布式多方共管钱包创建功能,包括 Admin-Web 扩展和 Service-Party 桌面应用。

## 主要变更

### 1. Admin-Web 扩展 (前端)
- 新增 CoManagedWalletSection 组件 (frontend/admin-web/src/components/features/co-managed-wallet/)
- 在授权管理页面添加共管钱包入口卡片
- 实现创建钱包向导: 配置 → 邀请 → 生成 → 完成
- 包含组件: ThresholdConfig, InviteQRCode, ParticipantList, SessionProgress, WalletResult

### 2. Admin-Service 后端 API
- 新增共管钱包领域实体和枚举 (domain/entities/co-managed-wallet.entity.ts)
- 新增 REST 控制器 (api/controllers/co-managed-wallet.controller.ts)
- 新增服务层 (application/services/co-managed-wallet.service.ts)
- 新增 Prisma 模型: CoManagedWalletSession, CoManagedWallet
- 更新 app.module.ts 注册新模块

### 3. Session Coordinator 扩展 (Go)
- 新增会话类型: SessionTypeCoManagedKeygen ("co_managed_keygen")
- 扩展 MPCSession 实体添加 WalletName 和 InviteCode 字段
- 更新 PostgreSQL 和 Redis 适配器支持新字段
- 新增数据库迁移: 008_add_co_managed_wallet_fields

### 4. Service-Party 桌面应用 (新项目)
- 位置: backend/mpc-system/services/service-party-app/
- 技术栈: Electron + React + TypeScript + Vite
- 包含模块:
  - gRPC 客户端 (连接 Message Router)
  - TSS 处理器 (子进程方式运行 Go TSS 协议)
  - 本地加密存储 (AES-256-GCM)
- 页面: Home, Join, Create, Session, Settings

## 修改的现有文件 (便于回滚)

1. backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go
   - 添加 SessionTypeCoManagedKeygen 常量
   - 添加 IsKeygen() 方法
   - 添加 WalletName, InviteCode 字段
   - 更新 ReconstructSession, ToDTO, SessionDTO

2. backend/mpc-system/services/session-coordinator/adapters/output/postgres/session_postgres_repo.go
   - 更新 SQL 查询包含 wallet_name, invite_code
   - 更新 Save, FindByUUID, FindByStatus 等方法
   - 更新 scanSessions, sessionRow

3. backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go
   - 更新 sessionCacheEntry 结构
   - 更新 sessionToCacheEntry, cacheEntryToSession

4. backend/services/admin-service/prisma/schema.prisma
   - 新增 WalletSessionStatus 枚举
   - 新增 CoManagedWalletSession, CoManagedWallet 模型

5. backend/services/admin-service/src/app.module.ts
   - 导入并注册共管钱包相关组件

6. frontend/admin-web/src/app/(dashboard)/authorization/page.tsx
   - 导入并添加 CoManagedWalletSection

7. frontend/admin-web/src/infrastructure/api/endpoints.ts
   - 添加 CO_MANAGED_WALLETS API 端点

## 回滚说明

如需回滚此功能:
1. 回滚数据库迁移: 运行 008_add_co_managed_wallet_fields.down.sql
2. 删除新增文件夹:
   - backend/mpc-system/services/service-party-app/
   - frontend/admin-web/src/components/features/co-managed-wallet/
   - backend/services/admin-service/src/**/co-managed-wallet*
3. 恢复修改的文件到前一个版本
4. 运行 prisma generate 重新生成 Prisma 客户端

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 21:39:07 -08:00
hailin fe593714ae fix(admin-service): 修复上传版本时isForceUpdate始终为true的问题
问题原因:
- ValidationPipe配置了enableImplicitConversion: true
- FormData发送字符串"false"时,Boolean("false")被隐式转换为true
- @Transform装饰器在隐式转换之后执行,收到的value已经是true

解决方案:
- 在@Transform中使用obj参数获取原始未转换的值
- 手动判断字符串"true"/"false"并正确转换为布尔值

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 19:31:47 -08:00
hailin 058849dc2c fix(admin-service): 修复上传版本时isForceUpdate默认为true的问题
- 改进Transform装饰器,正确处理FormData传递的字符串"false"
- 添加调试日志用于排查问题

问题原因:FormData传递的布尔值会被转为字符串,
原来的Transform可能在某些情况下处理不正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 19:21:48 -08:00
hailin 1694f37e91 fix(mobile-app): 修复多账号切换后账号列表只显示一个的问题
- phone_login_page: 登录成功后添加账号到多账号列表
- import_mnemonic_page: 恢复账号后添加到多账号列表
- sms_verify_page: 短信验证登录后添加账号到多账号列表

问题原因:多个登录入口没有调用 addAccount() 将账号添加到列表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 11:12:50 -08:00
hailin 339f95f7ed fix(identity-service): 修复手动重试钱包生成使用错误的事件类型
retryWalletGeneration 方法之前使用 createWalletGenerationEvent()
发布 UserAccountCreatedEvent,但 MPC 服务只监听 MpcKeygenRequestedEvent。

现在改为直接发布 MpcKeygenRequestedEvent,与 wallet-retry.task.ts 保持一致。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 10:15:30 -08:00
hailin 9153ba3625 fix(identity-service): 修复钱包重试发布错误事件类型的问题
问题:
- 重试代码使用 createWalletGenerationEvent() 发布 UserAccountCreatedEvent
- 该事件发布到 identity.UserAccountCreated topic
- 但 MPC 服务监听的是 mpc.KeygenRequested topic
- 导致重试触发成功但钱包不会被生成

修复:
- triggerWalletRetryAsync: 改为发布 MpcKeygenRequestedEvent
- WalletRetryTask.retryWalletGeneration: 改为发布 MpcKeygenRequestedEvent
- 与注册流程使用相同的事件类型和参数格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 10:09:20 -08:00
hailin 6216a1563a fix(identity-service): 修复动态import导致的模块解析错误
将动态 import('@/domain/value-objects') 改为静态 import

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 09:58:23 -08:00
hailin e742a360ec fix(identity-service): 限制定时任务每次最多触发10个重试,防止MPC过载
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 09:42:56 -08:00
hailin 55bb129477 feat(identity-service): 增强钱包生成可靠性,确保100%生成成功
核心改进:
- 基于数据库扫描代替Redis扫描,防止状态丢失后无法重试
- 指数退避策略(1分钟→60分钟),无时间限制持续重试
- 分布式锁保护,防止多实例/并发重复触发
- getWalletStatus API 检测失败状态并自动触发重试

修改内容:
- RedisService: 添加 tryLock/unlock 分布式锁方法
- UserAccountRepository: 添加 findUsersWithIncompleteWallets 查询
- getWalletStatus: 增强状态检测,失败/超时时自动触发重试
- WalletRetryTask: 完全重写,基于数据库驱动+指数退避

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 09:40:51 -08:00
hailin aa180c54bc fix(identity-service): 修复钱包重试逻辑,超时状态允许强制重试
之前手动重试时如果状态是 generating/pending/deriving 会直接跳过,
导致卡住的钱包无法重新生成。现在增加超时检查(60秒),超时后允许强制重试。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 11:43:02 -08:00
hailin abc3b358a7 feat(referral): 将推荐链最大深度从10层提升到1000层
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 10:26:52 -08:00
hailin e9b2917561 fix(pdf-generator): 使用自定义外观流嵌入签名图片
- 恢复使用 widget.setNormalAppearance() 方式
- 创建 XObject Form 作为外观流
- 签名图片按字段尺寸等比例缩放并居中
- 不依赖页面索引,直接设置到widget上

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 07:58:44 -08:00
hailin 91d3e65289 fix(pdf-generator): 使用page.drawImage在按钮位置绘制签名图片
- 从git历史恢复正确的签名嵌入实现
- 获取signature按钮的widget和rectangle位置
- 按字段尺寸等比例缩放签名图片并居中
- 使用page.drawImage()绘制签名,而非setImage()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 07:54:17 -08:00
hailin 0e85c2fd23 fix(wallet-service): 修复社区权益根据 targetId 正确分配
问题:社区权益(COMMUNITY_RIGHT)无论 targetId 是什么,都强制分配到
总部账户 S0000000001,导致社区授权人无法在流水明细中看到社区权益。

修复:
- 将 allocateToHeadquartersCommunity 方法重命名为 allocateCommunityRight
- 根据 targetId 判断分配目标:
  - D 开头(用户账户): 分配到社区授权人账户
  - S 开头或 '1'(系统账户): 分配到总部社区账户
- 更新流水备注以区分用户分配和总部分配

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 07:20:22 -08:00
hailin 954f170bd4 feat(contract-signing): 增强签名功能
前端改进:
- 签名页面添加红色醒目提示"请使用正楷书写您的真实姓名"
- 签名前显示用户真实姓名供参照
- 实现全屏横向签名面板(自动切换横屏/竖屏)
- 记录签名轨迹数据(每个点的坐标和时间戳、笔画顺序)

后端改进:
- 扩展SignContractParams接口支持signatureTrace字段
- 控制器记录签名轨迹日志(笔画数、总时长)
- 签名轨迹数据以JSON格式存储,作为法律凭证

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 06:42:15 -08:00
hailin d4763ea5bf chore(planting-service): 更新合同PDF模板(修复红色文字)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 06:29:08 -08:00
hailin dfecdc06e9 chore(planting-service): 更新合同PDF模板
使用新的榴莲树认种权益协议_发布版_form.pdf替换原模板

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 06:15:49 -08:00
hailin ad5b153fa9 fix(pdf-generator): 签名按字段尺寸等比例缩放并居中
- 计算宽度和高度的缩放比例,取较小值确保签名完全在字段内
- 在字段内居中放置签名图片
- 符合行业标准:签名根据字段尺寸自适应缩放

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:56:38 -08:00
hailin 2e65a92e04 fix(planting-service): 签名图片按比例缩放到合适大小
- 目标宽度 150pt(约 5cm)
- 保持宽高比不变
- 避免签名图片过大

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:53:51 -08:00
hailin 6c017d2086 fix(planting-service): 签名图片保持原始尺寸放置
- 不再缩放签名图片适应按钮大小
- 直接在按钮位置绘制原始尺寸的签名
- 避免签名被压扁变形

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:53:22 -08:00
hailin 666be6ea60 fix(planting-service): 签名后查看合同返回已签名的PDF
- 修改 /tasks/:orderNo/pdf 接口,检查任务状态
- 如果已签名且有 signedPdfUrl,从 MinIO 下载已签名的 PDF
- 添加 downloadSignedPdf 方法到 MinioStorageService
- 在 ContractSigningTaskDto 中添加 signedPdfUrl 字段

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:48:22 -08:00
hailin 86103e4c4d fix(planting-service): 使用自定义外观流嵌入签名图片
- setImage 无法正确渲染签名到按钮字段
- 手动创建 XObject Form 外观流
- 计算图片缩放和居中位置
- 设置 widget 的 NormalAppearance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:35:58 -08:00
hailin bdeff3b372 fix(planting-service): 修复合同签名无法放到指定位置的问题
- 修改 generateSignedContractPdf 在同一个 PDFDocument 实例上完成填充和签名
- 移除 fillFormFields 中的 form.flatten(),保留签名字段供后续使用
- 最后统一扁平化所有表单字段,确保签名放到正确位置
- 控制器改用 generateSignedContractPdf 替代分两步调用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:23:53 -08:00
hailin 09cc696efa Revert "fix(wallet-service): 社区权益按 targetId 分配到正确账户"
This reverts commit 43a0e5f5e1.
2025-12-26 04:52:01 -08:00
hailin 43a0e5f5e1 fix(wallet-service): 社区权益按 targetId 分配到正确账户
修复社区权益分配逻辑:
- 之前所有 COMMUNITY_RIGHT 都直接进入总部账户 S0000000001
- 现在根据 targetId 判断:
  - targetId 为 '1' 或 'S0000000001' → 进入总部社区账户
  - targetId 为用户账户(D开头)→ 进入该用户可结算余额

这样当用户获取社区授权且伞下认种达到10棵后,
社区权益会正确分配到该用户账户,而不是总部。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:49:10 -08:00
hailin 3f3309e62f debug: 添加流水明细 allocationType 调试日志
- 后端 wallet-service: getMyLedger 打印 payloadJson 和 allocationType
- 前端 wallet_service: 打印原始和解析后的流水数据
- 前端 ledger_detail_page: 打印加载的流水数据详情

用于排查权益类型(社区、省市团队/区域)不显示的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:35:46 -08:00
hailin 3d42c3602d fix(reward-service): 权益分配memo显示触发用户ID
所有权益类型的memo现在统一显示"来自用户xxx的认种"格式:
- 省团队权益:来自用户xxx的认种
- 省区域权益:来自用户xxx的认种
- 市团队权益:来自用户xxx的认种
- 市区域权益:来自用户xxx的认种
- 社区权益:来自用户xxx的认种

修改前只显示"xx权益已激活",现在与分享权益格式保持一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:18:35 -08:00
hailin f711d54eed chore(reward-service): 调整系统费用分配 - 成本费+80, 总部基础费-80 2025-12-26 04:07:41 -08:00
hailin 1d6982c73e feat(planting-service): 合同签署超时时间从24小时改为1年 2025-12-26 03:58:56 -08:00
hailin 78d7e0e637 feat(mobile-app): 流水明细支持显示权益类型和详情
- 后端 wallet-service: getMyLedger API 返回 allocationType 字段
- 前端流水明细: 显示权益类型名称(分享权益、省/市区域权益等)
- 新增权益详情弹窗,点击权益记录可查看详细信息
- 兑换页面: "RMB/CNY提现" 改为 "提现"
- 我的团队: "暂无下级成员" 改为 "暂无团队成员"
- 自助申请授权: 隐藏团队链占用区域提示

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 03:57:35 -08:00
hailin f7e2f7f6f2 fix(wallet-service): 添加 WalletAccount 类型导入 2025-12-26 02:23:49 -08:00
hailin 726e3d0fcf fix(wallet-service): 修复区域权益分配时 targetId 为用户账户导致的 BigInt 转换错误
问题:allocateToRegionAccount 假设 targetId 总是纯数字格式的区域账户,
但实际上当权益分配给授权市/省公司用户时,targetId 是 D 开头的用户账户格式。

修复:判断 targetId 格式
- D 开头:用户账户,直接 findByAccountSequence
- 纯数字:区域账户,使用 getOrCreate

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 02:20:05 -08:00
hailin 9addd99710 fix(planting-service): 修正导入路径
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 01:50:37 -08:00
hailin 24a46521f3 fix(planting-service): 修复跨服务调用使用错误标识符导致的500错误
问题根源:
- getBalance 调用使用 userId.toString() (纯数字如 "14")
- wallet-service 按 accountSequence 查找钱包失败后尝试创建新钱包
- 但 userId 已存在,触发唯一约束冲突导致500错误

修复内容:
1. planting-application.service.ts:
   - createOrder: getBalance(userId.toString()) → getBalance(accountSequence)
   - payOrder: getBalance(userId.toString()) → getBalance(walletIdentifier)

2. payment-compensation.service.ts:
   - 注入 IPlantingOrderRepository 获取订单的 accountSequence
   - handleUnfreeze/handleRetryConfirm 添加 accountSequence 参数

3. wallet-service.client.ts:
   - ensureRegionAccounts 接口添加 provinceTeamAccount/cityTeamAccount 字段

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 01:48:22 -08:00
hailin 89a2700fc9 chore(authorization-service): 移除已执行完成的 OTP 修复任务
OTP 修复结果:
- 总计处理: 3 个未激活的社区授权
- 成功修复: 1 (D25122600004)
- 跳过: 2 (未达标)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 23:06:32 -08:00
hailin f2a59b81ee fix(authorization-service): 修复 OTP 编译错误,使用 findByStatus 方法
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 23:03:54 -08:00
hailin 16a6edaf15 feat(authorization-service): 添加社区权益激活一次性修复任务
问题:由于 planting-service 发送的 userId 是订单主键而非用户真实 ID,
导致部分已达标的社区权益未被自动激活。

修复:添加 BenefitActivationFixOTP 一次性任务,在服务启动时:
1. 查找所有状态为 AUTHORIZED 但 benefitActive=false 的社区授权
2. 检查每个社区的 subordinateTeamPlantingCount 是否 >= 10
3. 满足条件则激活权益

使用方式:
1. 部署此代码,服务启动后自动执行修复
2. 确认修复完成后,删除 OTP 文件并重新部署

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 23:00:38 -08:00
hailin 6e84e370ee fix(authorization-service): 使用 accountSequence 替代 userId 查询团队统计
问题:planting-service 发送的 PlantingOrderPaid 事件中的 userId 是
订单表的自增主键(如 15),而不是 referral-service 中的真实 user_id
(如 25122600006)。这导致 handleTreePlanted 方法查询团队统计时
返回 null,社区权益无法被自动激活。

修复:改用事件中的 accountSequence 字段查询团队统计,因为
accountSequence 是跨服务一致的用户标识。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 22:51:32 -08:00
hailin f62a96f3f1 feat(planting): 已付款未KYC用户强制进入实名认证流程
后端 (planting-service):
- 添加 /contract-signing/kyc-requirement 接口检查用户是否需要KYC
- 检查已付款订单但无合同签署任务的情况

前端 (mobile-app):
- ContractCheckService 新增 checkAll() 综合检查方法
- HomeShellPage 综合检查待签署合同和KYC需求
- 需要KYC时弹出强制认证弹窗,不可关闭

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:14:53 -08:00
hailin dbeef0a80b chore(wallet-service): 移除已执行的OTP修复脚本 2025-12-25 20:55:08 -08:00
hailin c2ff11bd6d fix(wallet-service): 添加一次性修复脚本 D25122600004->D25122600006 转账
- 修复因并发修改导致的冻结余额不足问题
- 自动完成内部转账、记录流水、更新订单状态
- 幂等执行,可安全重启
- 部署成功后请删除 otp/ 目录和相关引用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:50:39 -08:00
hailin 305bdf63af fix(wallet-service): 添加钱包乐观锁防止并发修改
- WalletAccount aggregate 添加 version 字段
- WalletAccountRepositoryImpl 使用 updateMany + version 检查实现乐观锁
- requestWithdrawal 添加重试机制处理乐观锁冲突

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:44:55 -08:00
hailin 1e15b820b4 fix(planting-service): 合同PDF显示完整手机号和身份证号
- 移除 PDF 生成时对手机号和身份证号的脱敏处理
- 表单字段模式和坐标定位模式都直接使用原始值
- 删除 maskIdCard() 和 maskPhone() 脱敏方法
- 签订合同需要显示完整信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:55:55 -08:00
hailin 285465827d fix(blockchain-service): 添加 --accept-data-loss 参数
prisma db push 需要此参数来接受精度变更

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:28:23 -08:00
hailin 1d817a5be2 fix(blockchain-service): 扩大充值金额字段精度
- amount 字段从 Decimal(36,18) 改为 Decimal(78,0) 支持超大金额
- amountFormatted 字段从 Decimal(20,8) 改为 Decimal(36,8)

修复问题:100亿 USDT 充值导致 numeric field overflow 错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:19:48 -08:00
hailin e95ac15605 fix(reward-service): 添加奖励分配幂等性检查
- distributeRewards 方法添加幂等性检查,防止同一订单重复分配奖励
- distributeRewardsForExpiredContract 方法同样添加幂等性检查
- 通过 findBySourceOrderNo 检查订单是否已分配过奖励

修复问题:recovery job 重复触发导致同一订单奖励被多次分配

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 10:42:01 -08:00
hailin 68a071cfaa fix(identity-service): 暂时恢复三要素身份验证
二要素 API (Id2MetaStandardVerify) 返回 440 无权限调用错误
暂时恢复使用三要素验证,保留二要素代码待开通权限后使用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 10:12:20 -08:00
hailin 4ec4df14b5 feat(identity-service): KYC 改用二要素验证
- 默认使用阿里云 Id2MetaStandardVerify API(姓名+身份证号)
- 保留三要素验证方法 verifyIdCardThreeFactor 作为备用
- 二要素验证始终调用真实 API,不使用 mock
- 兼容 BizCode 数字和字符串类型

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:46:17 -08:00
hailin 7a1e789f4d fix(contract): 合同签署页面和模板优化
1. 合同模板:身份证号和联系方式显示完整信息,不再使用星号掩码
2. 签署页面:checkbox 默认不选中,用户阅读到底部后才可点击确认

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:31:39 -08:00
hailin fba91ec256 fix(referral-service): 添加 WalletServiceClient 初始化日志
方便排查 WALLET_SERVICE_URL 环境变量是否正确加载

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:22:47 -08:00
hailin 63ac0debf3 feat(planting-service): 添加合同签署后事件恢复定时任务
每2~5分钟随机间隔扫描已签署超过2分钟的合同
重新发布 contract.signed 事件,确保扣款确认和奖励分配完成

幂等性已由 wallet-service 保证

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:08:47 -08:00
hailin f9e2d8483c feat(wallet-service): allocateFunds 添加幂等性检查
防止重复分配奖励,通过检查流水表中的 orderId + accountSequence + allocationType 组合

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:05:44 -08:00
hailin bf7f4af88d fix(docker-compose): 添加 referral-service 的 WALLET_SERVICE_URL 配置
referral-service 需要调用 wallet-service 确认扣款,
但缺少环境变量配置导致使用默认 localhost:3002 无法访问

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:59:53 -08:00
hailin 484cc99636 fix(planting-service): 修复 identity-service 响应解析
identity-service 响应被 TransformInterceptor 包装为 { success, data }
需要从 response.data.data 获取实际用户信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:47:43 -08:00
hailin 48f4ed60a6 fix(planting-service): 修复 identity-service API 调用路径
添加 /api/v1 前缀以匹配 identity-service 的全局路由配置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:39:45 -08:00
hailin c907f44851 feat(planting-service): 订单表添加 accountSequence,实现合同恢复任务
变更内容:
1. 订单表添加 account_sequence 字段
   - 创建订单时保存用户的 accountSequence
   - 避免跨服务调用 identity-service 获取用户信息

2. 新增 ContractSigningRecoveryJob 定时任务
   - 每 3 分钟扫描已支付但未创建合同的订单
   - 使用订单中的 accountSequence 获取 KYC 信息
   - 为已通过 KYC 的用户补创建合同签署任务

3. 修改 PlantingOrder 聚合根
   - create() 方法增加 accountSequence 参数
   - markAsPaid() 不再需要 accountSequence 参数
   - 事件中携带 accountSequence

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:19:36 -08:00
hailin 1c3ddb0f9b fix: 修复internal用户详情接口路由和KYC状态检查
问题1: /internal/users/:accountSequence/detail 返回404
原因: 路由顺序问题,通配路由在前拦截了请求
修复: 将 /detail 路由移到通配路由之前

问题2: planting-service 只接受 kycStatus='VERIFIED'
原因: identity-service 使用 REAL_NAME_VERIFIED 等状态
修复: 接受所有有效的KYC状态

同时:
- identity-service 返回 idCardNumber 用于合同签署
- planting-service 使用 idCardNumber

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 07:51:11 -08:00
hailin b3014744ab fix(identity-service): KYC成功后发布KYCVerified事件
之前实名认证成功后只更新数据库,没有发布事件,
导致planting-service无法收到通知来创建合同签署任务。

修改内容:
- 注入 EventPublisherService
- 查询时增加 accountSequence 字段
- 认证成功后发布 KYCVerifiedEvent 到 identity.KYCVerified topic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 07:38:20 -08:00
hailin 8163804f23 fix(contract-signing): 修复合同签署流程的持仓更新时机
问题:支付后直接更新持仓和开启挖矿,导致款还在冻结中树就种下去了

修复:
- planting-application.service: 支付时不再更新持仓和开启挖矿
- contract-signing.service: signContract 在事务里同时完成合同+持仓+挖矿
- contract-signing.service: handleExpiredTasks 超时也更新持仓+挖矿(钱扣总部)
- KYCVerifiedEvent 添加 accountSequence 字段
- kyc-verified-event.consumer 直接用事件里的 accountSequence

流程变为:支付冻结 → 签署合同 → [事务: 合同+持仓+挖矿] → 发事件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 06:50:03 -08:00
hailin 2e0df30473 fix(migration): 移除 DO $$ 块,Prisma 不支持 PL/pgSQL
Prisma migrate deploy 只支持简单 SQL 语句

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:55:42 -08:00
hailin 7ce71ad27b fix(planting-service): 移除 Dockerfile 中的 db push 回退逻辑
db push 不使用迁移文件,会导致添加必填列时失败

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:47:46 -08:00
hailin 500e4381a6 fix(migration): 使迁移脚本幂等以支持重试
迁移脚本添加 IF NOT EXISTS 检查,避免重复执行时失败

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:39:38 -08:00
hailin 929ae335c5 feat(contract): 增强合同生成功能
- 添加 IdentityServiceClient 从 identity-service 获取用户 KYC 信息
- 只允许已完成实名认证的用户创建合同
- 添加 KycVerifiedEventConsumer 监听 KYC 完成事件
- 用户完成 KYC 后自动为其之前已支付的订单补创建合同
- PDF 生成器支持 AcroForm 表单字段填充(更可靠)
- 保留坐标定位方式作为后备方案
- 更新 PDF 模板为带表单字段版本

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:35:40 -08:00
hailin 0e93d2a343 feat(contract): 使用合同编号代替订单号
合同编号格式: accountSequence-yyyyMMddHHmm
例如: 10001-202512251003

修改内容:
- 数据库: 添加 contract_no 字段
- 后端: 聚合根、Repository、Service、PDF生成器支持 contractNo
- 前端: 显示合同编号代替订单号

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 04:58:39 -08:00
hailin a7206eef2e fix(planting-service): 修复 BigInt userId 比较问题
- 使用 toString() 比较 BigInt 避免类型不匹配
- 添加调试日志帮助排查问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:59:27 -08:00
hailin 2d9e1b2d03 fix(planting-service): 修复合同签署任务创建的并发问题
- 将 upsert 改为 create + 重试机制
- 处理 P2002 唯一约束冲突时使用指数退避重试
- 确保并发创建时能正确返回已存在的记录

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:50:19 -08:00
hailin c657fb5a19 feat(planting-service): 实现合同签名和PDF云存储功能
- 添加 MinIO 存储服务,支持上传签名图片和已签署 PDF
- 添加 signedPdfUrl 字段到数据库模型
- 修改签署流程:生成 PDF、嵌入签名、上传到云存储
- 修复前端签署 API 响应处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:35:15 -08:00
hailin cdd275479e fix(planting-service): 使用楷体 STKAITI.ttf 替换无效字体
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:56:01 -08:00
hailin 65ba75d8d1 fix(planting-service): 修复 fontkit 导入方式
使用 require 替代 ES import 解决 TypeScript 编译后 default export 问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:44:37 -08:00
hailin 6536ff9256 fix(planting-service): Dockerfile 添加 templates 目录复制
PDF 模板和字体文件需要复制到 Docker 容器中

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:41:22 -08:00
hailin c509daa353 feat(contract-signing): 使用 pdf-lib 实现专业 PDF 合同展示
后端改动:
- 添加 pdf-lib 和 @pdf-lib/fontkit 依赖
- 新建 PdfGeneratorService 使用 PDF 模板直接填充用户数据
- 添加中文字体支持 (NotoSansSC-Regular.ttf)
- 新增 GET /tasks/:orderNo/pdf 接口返回 PDF 文件
- 合同模板存放于 templates/contract-template.pdf

前端改动:
- 添加 flutter_pdfview 依赖
- 重写合同签署页面使用 PDFView 组件展示 PDF
- 下载 PDF 到临时目录后展示
- 滑动到最后一页自动标记已阅读

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:27:54 -08:00
hailin e7f2d69def fix(planting-service): 添加 P2002 错误捕获处理并发创建冲突
PostgreSQL 的 upsert 在高并发下仍可能出现唯一约束错误,
添加 try-catch 捕获 P2002 错误,发生冲突时直接查询返回已存在的记录。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:56:53 -08:00
hailin 68e269b602 fix(planting): 使用upsert解决合同签约任务创建的并发冲突
Kafka事件重复消费时,多个消费者同时创建签约任务会导致唯一约束冲突
改用upsert确保幂等性,如果orderNo已存在则返回现有记录

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:52:01 -08:00
hailin c14b87305c feat(kyc): 升级为三要素核验详版API,返回详细错误原因
- 从 Mobile3MetaSimpleVerify 改为 Mobile3MetaDetailVerify
- 新增 SubCode 详细错误码映射:
  - 201: 手机号与姓名、身份证号均不匹配
  - 202: 手机号与身份证号不匹配
  - 203: 手机号与姓名不匹配
  - 204: 其他不一致
  - 301: 查无记录

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:40:48 -08:00
hailin c3b50264cc fix(kyc): 修正阿里云手机号三要素核验的成功判断逻辑
阿里云 Mobile3MetaSimpleVerify 返回的 BizCode:
- 1: 校验一致 (成功)
- 2: 校验不一致 (失败)
- 3: 查无记录 (失败)

之前错误地将 BizCode=0 判断为成功,现改为 BizCode=1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:28:29 -08:00
hailin 4b92fb36a3 debug(kyc): 添加阿里云API返回信息的详细日志
打印完整的response和ResultObject字段以便调试

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:20:45 -08:00
hailin c2e81a6f4e fix(kyc): 使用正确的阿里云手机号三要素核验API
- 从 VerifyMaterial (身份三要素,需要人脸照片) 改为 Mobile3MetaSimpleVerify (手机号三要素)
- 手机号三要素验证:姓名 + 身份证号 + 手机号
- 添加 mapMobile3MetaErrorCode 方法映射错误码

文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/esf1ff158mxowkk6

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 00:05:03 -08:00
hailin de17231f61 fix(kyc): 为 SubmitRealNameDto 添加 class-validator 装饰器
修复 ValidationPipe whitelist 模式下属性被过滤的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 23:58:55 -08:00
hailin 181d11d656 feat(kyc): 升级实名认证为三要素验证(姓名+身份证号+手机号)
- 后端 aliyun-kyc.provider.ts: 改用 ID_CARD_THREE 类型,添加 PhoneNumber 参数
- 后端 kyc-application.service.ts: 从用户账户获取手机号传递给 KYC provider
- 前端 kyc_id_page.dart: 更新文案为"三要素验证"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 23:54:13 -08:00
hailin e4f27b3134 fix(docker): 添加阿里云KYC环境变量到docker-compose
在identity-service中添加:
- ALIYUN_KYC_ENABLED
- ALIYUN_KYC_ENDPOINT
- ALIYUN_KYC_SCENE_ID

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 23:46:12 -08:00
hailin c8396d9152 docs(identity-service): 添加阿里云KYC实人认证环境变量配置说明
在 .env.example 中添加:
- ALIYUN_KYC_ENABLED: 是否启用真实KYC验证
- ALIYUN_KYC_ENDPOINT: API端点
- ALIYUN_KYC_SCENE_ID: 人脸活体检测场景ID

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 22:45:29 -08:00
hailin 94a5c29a09 fix(planting-service): Dockerfile复制tsconfig以支持ts-node seed
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 21:41:32 -08:00
hailin 8a0bff5010 fix(planting-service): Dockerfile添加自动seed步骤
启动时自动运行 prisma db seed 创建合同模板

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 21:29:46 -08:00
hailin bc34907a84 fix(auth): 注册验证码页面显示完整手机号
验证码页面不再隐藏手机号中间数字,改为完整显示
格式: 138 1234 5678

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 21:03:30 -08:00
hailin 8b1db58318 fix(planting-service): 修复用户ID字段名与JwtAuthGuard一致
JwtAuthGuard 设置 req.user.id,controller 需要使用相同字段名

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:50:58 -08:00
hailin aa9370dc56 fix(planting-service): 排除 prisma 目录修复编译输出路径
prisma/seed.ts 导致 TypeScript 编译时目录结构变化,
dist/main.js 变成 dist/src/main.js

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:39:19 -08:00
hailin 80a854e9d8 chore(planting-service): 更新 package-lock.json
添加 @nestjs/schedule 依赖的锁文件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:25:31 -08:00
hailin 33a5b79c2a fix(planting-service): 修复合同签署功能编译错误
- 修复 JwtAuthGuard 导入路径
- 添加 @nestjs/schedule 依赖

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:24:00 -08:00
hailin 714ce42e4f feat(contract-signing): 添加电子合同签署功能及单点配置优化
- planting-service: 添加合同签署任务管理和超时检测
  - 新增 ContractSigningTask 领域模型
  - 添加 24 小时合同签署超时定时任务
  - 支付后资金保持冻结,由 referral-service 统一确认扣款

- referral-service: 单点配置 CONTRACT_SIGNING_ENABLED
  - 新增 ContractSigningHandler 处理合同签署/超时事件
  - 新增 WalletServiceClient 调用钱包服务确认扣款
  - planting.created 处理后根据配置决定是否等待合同签署

- reward-service: 移除 CONTRACT_SIGNING_ENABLED 配置
  - 扣款确认由 referral-service 在发送事件前完成
  - 保持奖励分配逻辑不变

配置说明:
- CONTRACT_SIGNING_ENABLED=true (默认): 等待合同签署后分配奖励
- CONTRACT_SIGNING_ENABLED=false: 立即分配奖励(原有流程)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:12:12 -08:00
hailin fff88d0323 chore(db): 添加用户画像系统数据库迁移
新增表:
- tag_categories: 标签分类
- user_tags: 用户标签定义
- user_tag_assignments: 用户-标签关联
- user_classification_rules: 分类规则
- user_features: 用户特征 (RFM等)
- audience_segments: 人群包
- user_tag_logs: 标签变更日志
- notification_tag_targets: 通知-标签关联
- notification_user_targets: 通知-用户关联

新增枚举:
- TagType, TagValueType, TagAction, SegmentUsageType, TargetLogic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 16:43:19 -08:00
hailin b5e45c4532 feat(user-profile): 实现用户画像系统和通知定向功能
后端 (admin-service):
- 新增用户标签系统:标签分类、标签定义、用户标签分配
- 新增分类规则引擎:支持自动打标规则
- 新增人群包管理:支持复杂条件组合筛选用户
- 增强通知系统:支持按标签、按人群包、指定用户定向发送
- 新增自动标签同步定时任务
- Prisma Schema 扩展支持新数据模型

前端 (admin-web):
- 通知管理页面新增 Tab 切换:通知列表、用户标签、人群包
- 用户标签管理:分类管理、标签 CRUD、颜色/类型配置
- 人群包管理:条件组编辑器、逻辑运算符配置
- 通知编辑器:支持按标签筛选和指定用户定向

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 16:19:05 -08:00
hailin 934323e4c6 feat(kyc): 优化手机号验证/更换流程
- 将入口重命名为"验证/更换手机号"
- 验证旧手机成功后更新 phoneVerified 状态
- 首次验证成功时显示恭喜弹窗,用户可选择完成或继续更换
- 已验证过的用户验证通过后直接进入下一步

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:50:54 -08:00
hailin 0f745a17fd feat(kyc): 实现完整三层KYC认证功能
实现三层KYC认证系统,支持后台配置开关:
- 层级1: 实名认证 (二要素: 姓名+身份证号)
- 层级2: 实人认证 (人脸活体检测)
- 层级3: KYC (证件照上传验证)

后端变更:
- 更新 Schema 添加三层认证字段和 KycConfig 表
- 添加 migration 支持增量字段和配置表
- 重写 AliyunKycProvider 支持阿里云实人认证 API
- 重写 KycApplicationService 实现三层认证逻辑
- 更新 KycController 添加用户端和管理端 API

前端变更:
- 更新 KycService 支持三层认证 API
- 重构 KycEntryPage 显示三层认证状态
- 重构 KycIdPage 用于层级1实名认证
- 新增 KycFacePage 用于层级2人脸认证
- 新增 KycIdCardPage 用于层级3证件照上传
- 添加 uploadFile 方法到 ApiClient

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 07:14:11 -08:00
hailin a549768de4 feat(kyc): 实现实名认证和更换手机号功能
主要变更:
- 注册流程: 添加跳过短信验证选项(3分钟后显示)
- KYC功能: 手机号验证 + 身份证实名认证(阿里云二要素)
- 更换手机号: 四步验证流程(旧手机验证→输入新号→新手机验证→确认)
- 独立管控: phoneVerified, emailVerified, kycStatus 三个状态分别管理

后端:
- 新增 KYC 控制器和服务
- 新增更换手机号 API 端点
- Schema 添加 KYC 和验证状态字段
- 集成阿里云身份二要素验证

前端:
- 新增 KYC 入口页、手机验证页、身份证验证页
- 新增更换手机号页面
- Profile 页面添加实名认证入口

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 06:38:39 -08:00
hailin d4b802502e fix: 修复验证码竞态条件和火柴人对齐问题
1. 修复验证码发送的竞态条件:
   - 调整执行顺序,先存储验证码到 Redis,再发送短信/邮件
   - 避免用户收到验证码后立即输入但 Redis 中尚未存储的情况
   - 影响:sendSmsCode、sendWithdrawSmsCode、sendResetPasswordSmsCode、sendEmailCode

2. 修复火柴人组件昵称与数量标签对齐问题:
   - 使用底部对齐 + Padding 让昵称标签与数量标签在同一水平线

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 03:54:25 -08:00
hailin 906279ee8a fix(mobile): 修复用户详情页头像和用户ID显示问题
- 修复avatarUrl为SVG数据时的渲染问题,添加SVG检测逻辑
- 修复后端getUserInfoBySequence响应解析,处理包装格式
- 将用户详情弹窗改为全屏页面,提供更好的用户体验
- 新增统计数据卡片展示直推人数、伞下用户、认种数量
- 改进卡片样式,添加图标和阴影效果

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 01:28:28 -08:00
hailin 3ed17bb4eb fix(notification): 修复通知中心API路径
问题: 前端调用 /admin-service/mobile/notifications 路径不存在于Kong网关

修复:
1. Kong网关添加 /api/v1/mobile/notifications 路由到 admin-service
2. 前端 NotificationService 修正 API 路径:
   - /admin-service/mobile/notifications -> /mobile/notifications
   - /admin-service/mobile/notifications/unread-count -> /mobile/notifications/unread-count
   - /admin-service/mobile/notifications/mark-read -> /mobile/notifications/mark-read

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 01:20:43 -08:00
hailin 6745721399 fix: 修复火柴人排名点击查看用户详情功能
- 后端DTO添加accountSequence字段
- 后端服务返回accountSequence
- 前端映射accountSequence到StickmanRankingData
- 优化错误提示样式与页面风格一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 01:05:18 -08:00
hailin e9a64a8163 fix(identity): 使用Prisma直接查询用户详情
getUserDetailBySequence 方法改用 Prisma 直接查询数据库,
以获取 email 和 realName 等领域模型中未暴露的字段。

之前的实现通过领域模型 UserAccount 访问这些字段会导致编译错误,
因为领域模型没有直接暴露这些属性。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 00:46:45 -08:00
hailin bf64391c0c feat(identity): 改用创意组合名字替代序号命名
将用户名格式从"榴莲皇后x号"改为"榴莲皇后xxx",
其中xxx是2-4字的创意组合,包含前缀、核心词和后缀。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 00:25:03 -08:00
hailin ed1f863919 fix(authorization): 修复团队升级竞态条件,改用事件链模式
问题:authorization-service 和 referral-service 并行消费 TreePlanted 事件,
导致升级检查时统计数据尚未更新完成。

解决方案:
- referral-service: 批量更新团队统计后发布 TeamStatisticsUpdatedEvent
- authorization-service: 监听该事件触发升级检查,替代原有的即时检查
- TeamStatistics 聚合添加 accountSequence 字段用于事件发布

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 00:13:39 -08:00
hailin 647f86ec89 fix(authorization): 暂时禁止所有用户查看私密资料
由于系统尚未实现权限管理功能,暂时将 checkPrivateProfileAccess
始终返回 false,禁止所有用户查看其他用户的手机号、邮箱等隐私信息。

后续实现权限系统后可恢复原有逻辑。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:46:15 -08:00
hailin 27a4bbfbef feat(authorization): 实现火柴人排名用户详情查看功能
后端:
- identity-service: 新增内部API获取用户详情(手机号、邮箱、KYC等)
- referral-service: 新增内部API获取用户团队统计(直推人数、伞下用户数、认种数量)
- authorization-service:
  - 新增用户公开资料和私密资料API
  - 聚合identity-service和referral-service数据
  - 省团队以上权限可查看私密信息(脱敏处理)

前端:
- 新增UserProfileDialog弹窗组件,支持查看用户详情
- stickman_race_widget: 排名列表项可点击查看用户详情
- authorization_service: 新增getUserProfile/getUserPrivateProfile方法

用户详情包括:
- 基本信息: 用户ID、昵称、头像、注册时间、所在地区
- 团队数据: 推荐人、直推人数、伞下用户数、个人/团队认种数
- 授权信息: 授权类型、权益激活状态
- 联系信息(特权用户可见): 手机号、邮箱、真实姓名(脱敏)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:42:19 -08:00
hailin 53ef1ade42 fix(sms): 增强短信发送重试机制
- 最大重试次数从 2 次增加到 4 次
- 基础延迟从 3 秒增加到 6 秒
- 最大延迟从 10 秒增加到 30 秒

这些调整提高了短信发送在网络不稳定情况下的成功率

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:14:32 -08:00
hailin ab23270863 chore(identity): add migration for email field and email_codes table
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:23:36 -08:00
hailin f8dbac449a fix(identity): add EmailService to InfrastructureModule in app.module.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:12:22 -08:00
hailin 93b0f1ff96 chore(identity): add nodemailer dependency for email service
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:05:26 -08:00
hailin 4e670ad774 fix(wallet): 隐藏临时流水记录并统一充值名称显示
- 在流水明细查询中排除冻结/解冻等临时记录
- 将"充值 (KAVA)"统一改为"充值"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 21:00:31 -08:00
hailin a38aac5581 feat(email): 实现邮箱绑定/解绑功能
后端:
- 新增 EmailService 邮件发送服务,支持 Gmail SMTP
- 新增 EmailCode 数据模型用于存储邮箱验证码
- UserAccount 添加 email 字段
- 新增 API 接口:
  - GET /user/email-status 获取邮箱绑定状态
  - POST /user/send-email-code 发送邮箱验证码
  - POST /user/bind-email 绑定邮箱
  - POST /user/unbind-email 解绑邮箱
- 新增 DTOs: SendEmailCodeDto, BindEmailDto, UnbindEmailDto
- 新增 Commands: SendEmailCodeCommand, BindEmailCommand, UnbindEmailCommand

前端:
- account_service 新增邮箱相关方法和 EmailStatus 类
- bind_email_page 更新为使用真实 API:
  - 绑定/更换邮箱功能
  - 独立的解绑验证码输入和倒计时
  - 解绑确认对话框

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:53:20 -08:00
hailin 336306d6c0 fix(wallet-service): 修复账本统计双重计算问题
排除临时性流水类型(冻结/解冻)的收支统计:
- PLANT_FREEZE(认种冻结)
- PLANT_UNFREEZE(认种解冻)
- FREEZE(通用冻结)
- UNFREEZE(通用解冻)

问题原因:认种流程产生两笔流水(冻结+支付),导致一笔支出被统计两次
修复后:只统计最终的实际支付,冻结/解冻作为中间状态不计入收支

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:38:27 -08:00
hailin 69fa43ebee feat(auth): 实现修改密码API和Token过期自动跳转登录
后端:
- 新增 ChangePasswordCommand 和 ChangePasswordDto
- 新增 POST /user/change-password 接口
- 实现 changePassword() 方法,验证旧密码后更新新密码

前端:
- 新增 AuthEventService 认证事件服务,处理 token 过期事件
- api_client 在 token 刷新失败时发送过期事件
- App 监听认证事件,token 过期时清除账号状态并跳转登录页
- splash_page 优化路由逻辑:退出登录后跳转手机登录页而非向导页
- change_password_page 调用真实 API 修改密码
- account_service 新增 changePassword() 方法
- multi_account_service 退出登录时清除 phoneNumber 和 isPasswordSet

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:25:56 -08:00
hailin 7ae6af7841 fix(docker): 添加 Kafka/Zookeeper JVM 时区配置
- 添加 KAFKA_OPTS="-Duser.timezone=Asia/Shanghai" 设置 JVM 时区
- 挂载 /usr/share/zoneinfo 确保容器内有完整的时区数据

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 19:14:46 -08:00
hailin bb16844220 fix(docker): 为 zookeeper 和 kafka 挂载时区文件
confluentinc 镜像不支持 TZ 环境变量,需要挂载宿主机时区文件:
- /etc/localtime
- /etc/timezone

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 19:06:28 -08:00
hailin df0a041faa chore(docker): 为 mpc-system、api-gateway、infrastructure 添加时区配置
统一所有 Docker 服务时区为 Asia/Shanghai:

mpc-system:
- docker-compose.yml: postgres, session-coordinator, message-router, server-party-1/2/3, server-party-api, account-service
- docker-compose.prod.yml: postgres, message-router, session-coordinator, account-service, server-party-api
- docker-compose.party.yml: postgres, server-party

api-gateway:
- kong-db, kong-migrations, kong

infrastructure:
- consul, jaeger, grafana, minio

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 18:35:09 -08:00
hailin 65e9422fe5 chore(docker): 统一所有服务时区配置为 Asia/Shanghai
为所有 Docker 服务添加 TZ=Asia/Shanghai 环境变量,确保日志时间和定时任务使用中国时区:
- 基础设施: postgres, redis, zookeeper, kafka
- 应用服务: identity, wallet, backup, planting, referral, reward, mpc, leaderboard, reporting, authorization, admin, blockchain

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 18:29:20 -08:00
hailin 050cfacec3 fix(authorization): 增大 monthly_assessments.local_percentage 字段精度
将 local_percentage 字段从 DECIMAL(5,2) 改为 DECIMAL(10,2)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 08:02:21 -08:00
hailin 68621d3826 fix(authorization): 增大 progress_percentage 字段精度避免溢出
将 stickman_rankings 表的 progress_percentage 字段从 DECIMAL(5,2)
改为 DECIMAL(10,2),以支持超过 999.99% 的进度百分比。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 07:42:07 -08:00
hailin 454b466993 fix(authorization): 修复自动升级检查被提前返回跳过的问题
当认种用户没有授权时,不再提前返回,确保 checkAllTeamAutoUpgrade()
始终被调用,以正确检查所有市/省团队的自动升级条件。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 07:23:46 -08:00
hailin 8367530ebe refactor(authorization): 移除祖先链升级逻辑,只保留团队本人升级
业务规则简化:
- 市/省团队本人伞下认种数达到阈值时,团队本人获得区域授权
- 移除了"伞下成员达到阈值时该成员获得授权"的逻辑
- 两种逻辑是互斥的,只保留团队本人升级的方式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 07:14:08 -08:00
hailin 7c2d0b8b7f fix(authorization): 修正自动升级逻辑,totalTeamPlantingCount已是伞下认种数
referral-service 返回的 totalTeamPlantingCount 已经是不含自己的伞下认种数,
无需再减去 selfPlantingCount。更新注释说明。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 07:09:31 -08:00
hailin 8501cc34dc fix(authorization): 修改市/省团队自动升级逻辑为使用伞下认种数
业务规则调整:
- 市团队本人伞下认种数(不含自己)达到1万棵时自动升级为市区域
- 省团队本人伞下认种数(不含自己)达到5万棵时自动升级为省区域
- 伞下认种数 = 团队总认种数 - 自己认种数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 07:06:46 -08:00
hailin d24a474d02 feat(authorization): 火柴人排名更新频率从每天凌晨1点改为每10分钟
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 06:50:15 -08:00
hailin b4f685e25f fix(reward-service): 添加 BatchMonthlyEarningsRequest DTO 的 class-validator 装饰器
修复 authorization-service 调用 /internal/monthly-earnings/batch 接口时返回 400 错误的问题。
原因是 reward-service 使用了 ValidationPipe,但 DTO 类缺少必要的验证装饰器。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 05:22:34 -08:00
hailin 6572ef22c5 fix(docker): 移除 authorization-service 对 reward-service 的启动依赖
避免循环依赖:authorization-service <-> reward-service
使用 fallback 机制处理服务暂时不可用的情况(与 referral-service 类似)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 05:17:35 -08:00
hailin 16a3e76588 fix(authorization): 配置 REWARD_SERVICE_URL 环境变量
- 在 .env.example 添加 REWARD_SERVICE_URL 配置
- 在 docker-compose.yml 添加 REWARD_SERVICE_URL 和 REWARD_SERVICE_ENABLED 环境变量
- 在 docker-compose.windows.yml 添加相同配置
- authorization-service 依赖 reward-service 启动

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 05:15:20 -08:00
hailin 2f5ca85106 feat(authorization/reward): 实现火柴人排名本月收益显示功能
- reward-service: 添加批量查询月度收益内部接口
  - 新增 InternalController 提供 /internal/monthly-earnings/batch 端点
  - 在 RewardApplicationService 添加 batchGetMonthlyEarnings 方法
  - 支持按账户序列号、月份、权益类型批量查询可结算收益
  - 统计分享权益(SHARE_RIGHT)、省团队权益(PROVINCE_TEAM_RIGHT)、市团队权益(CITY_TEAM_RIGHT)

- authorization-service: 集成 reward-service 获取月度收益
  - 新增 RewardServiceClient 用于调用 reward-service 内部接口
  - 修改 getStickmanRanking 方法,调用 reward-service 获取月度收益
  - 省团队查询省团队权益+分享权益,市团队查询市团队权益+分享权益
  - monthlyEarnings 字段现在显示真实的月度可结算收益

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 05:04:55 -08:00
hailin bf63852a0f feat(authorization): 实现市/省团队自动升级为市/省区域机制
- 添加 findAllActiveAuthProvinceCompanies 和 findAllActiveAuthCityCompanies 仓储方法
- 在认种事件处理中添加 checkAllTeamAutoUpgrade 检查所有已激活团队
- 市团队达到1万棵自动升级为市区域(CITY_COMPANY)
- 省团队达到5万棵自动升级为省区域(PROVINCE_COMPANY)
- 保持原有手动授权功能不变

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 03:56:38 -08:00
hailin b04dd1f234 fix(authorization-service): 修复 identity-service 响应解析
- 处理 TransformInterceptor 包装的响应格式 { success, data }
- 正确提取 data 字段中的用户信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 03:12:58 -08:00
hailin 136c831922 fix(identity-service): 添加 DTO 验证装饰器
- 为 BatchGetUsersBySequenceDto 添加 class-validator 装饰器
- 修复 ValidationPipe 验证失败问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 03:08:25 -08:00
hailin 1d21ae8ff7 fix(identity-service): 修复 InternalController 未注册问题
- 在 app.module.ts 的内联 ApiModule 中添加 InternalController
- 添加 InfrastructureModule 导入和 UserAccountRepositoryImpl provider
- 修正 authorization-service 的 identity-service URL 默认值

问题原因:app.module.ts 定义了内联 ApiModule,不是导入的 api.module.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 03:04:57 -08:00
hailin a194fcad72 fix(identity-service): 内部接口改用 accountSequence 查询
- identity-service InternalController 改用 accountSequence 批量/单个查询
- 添加 findByAccountSequences 批量查询方法
- authorization-service 调用改为 batchGetUserInfoBySequence/getUserInfoBySequence
- 系统间通信统一使用 accountSequence 作为标识符

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 02:16:12 -08:00
hailin 5fa195e4bc fix: 修复火柴人排名显示问题
1. identity-service: 添加批量获取用户信息内部接口
   - 新增 InternalController 提供 POST /internal/users/batch
   - repository 添加 findByUserIds 批量查询方法

2. authorization-service: 修复 cumulativeCompleted=0 问题
   - assessAndRankRegion 改用 findByAccountSequence 查询团队统计
   - referral-service 使用 accountSequence 作为主键

3. mobile-app: 修复火柴人UI显示问题
   - 容器边距调整为16px与其他组件一致
   - 行高增加到100px避免火柴人重叠

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:48:16 -08:00
hailin e4f2a61ecb fix(authorization-service): 添加 identity-service 连接配置
authorization-service 缺少 IDENTITY_SERVICE_URL 和 IDENTITY_SERVICE_ENABLED
环境变量配置,导致无法获取用户信息(昵称、头像)。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:31:45 -08:00
hailin a9d5d297d8 feat(authorization): 火柴人排名查询时实时创建评估记录
当查询火柴人排名时,如果没有评估记录,则实时调用 assessAndRankRegion
创建评估记录,避免用户需要等待凌晨1点的定时任务。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:02:23 -08:00
hailin d862c9a623 Revert "fix(authorization): 自助申请市/省团队激活权益时创建考核评估记录"
This reverts commit d029cd5872.
2025-12-23 00:54:08 -08:00
hailin d029cd5872 fix(authorization): 自助申请市/省团队激活权益时创建考核评估记录
自助申请流程在激活权益时缺少创建 MonthlyAssessment 记录的逻辑,
导致火柴人排名功能无法正常显示。本次修复在 processCityTeamApplication
和 processProvinceTeamApplication 方法中添加了 createInitialAssessment 调用。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:43:29 -08:00
hailin 2d3891740c feat(authorization): 火柴人排名改为全系统排名,不按区域过滤
- 后端新增 findRankingsByMonthAndRoleType 方法查询全系统排名
- 修改 getStickmanRanking 不再按 regionCode 过滤
- 前端简化加载条件,只要有授权就加载排名
- 添加详细调试日志帮助排查问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:20:35 -08:00
hailin 2ce0177b59 fix(blockchain-service): 过滤热钱包发出的转账避免内部转账重复入账
内部转账时,wallet-service 已经处理了接收方入账,
需要过滤掉 blockchain-service 扫描到的热钱包转出交易,
避免将其当作充值重复处理导致双倍入账

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:56:53 -08:00
hailin 02361c4dcd fix(identity-service): 内部接口 by-wallet-address 添加 @Public 装饰器
修复服务间调用查询钱包地址时返回 401 的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:21:11 -08:00
hailin 428ac91737 feat(authorization): 优化市/省团队自助申请逻辑
- 团队链区域唯一性:同一直推链上只阻止申请已被占用的城市/省份,非全部阻止
- 市/省团队互斥:同一用户只能拥有市团队或省团队之一
- 前端优化:显示已占用区域数量提示,选择时验证区域可用性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 22:52:39 -08:00
hailin f9222fed50 feat: 实现ID-to-ID内部转账功能
- 添加内部转账标识字段:is_internal_transfer, to_account_sequence, to_user_id
- 提现时自动检测目标地址是否为内部用户
- 内部转账确认后创建双向流水:发送方TRANSFER_OUT,接收方TRANSFER_IN
- 新增identity-service钱包地址查询API支持内部用户识别

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 22:22:47 -08:00
hailin 3f5203c142 feat: 已认种用户分享权益直接进入可结算状态
- 新增 hasPlanted 字段标记用户是否已认种
- 已认种用户的分享权益直接进入可结算余额,无需待领取
- 修正前端权益考核数值(576/288/252/144/108 绿积分)
- 修复账本明细筛选栏选择后滚动位置重置问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 21:10:49 -08:00
hailin 726b317c23 fix(admin-service): 修复用户事件消费时 payload 嵌套层级错误
identity-service 发布的消息结构为 { eventId, eventType, payload: {...} },
但 admin-service 消费时直接使用 eventData 而不是 eventData.payload,
导致 payload.userId 为 undefined,BigInt(undefined) 抛出异常被静默吞掉,
用户数据无法同步到 UserQueryView。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 19:06:23 -08:00
hailin cb0f10af34 feat: 多项业务功能增强
- 动态提取手续费配置:支持固定/百分比两种费率类型,默认2绿积分/笔
- 找回密码功能:新增手机号+短信验证码重置密码流程
- 授权申请优化:自助申请时验证团队链授权状态
- UI文案调整:登录账号、监控页待开启等

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 19:00:02 -08:00
hailin 7a264a0158 feat(authorization): 实现省区域/市区域自动升级机制
- 添加 createAutoUpgradedProvinceCompany/CityCompany 工厂方法
- 在 handleTreePlanted 中检查自动升级条件
- 省区域:团队累计5万棵时自动升级
- 市区域:团队累计1万棵时自动升级
- 扩展 ITeamStatisticsRepository 接口添加 getReferralChain 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 17:24:44 -08:00
hailin 0506a3547c fix(authorization): 自助申请授权状态设为AUTHORIZED而非PENDING
问题:自助申请的社区/市团队/省团队授权创建时状态为PENDING,
导致在推荐关系查询中无法找到这些授权(查询只匹配AUTHORIZED状态)

解决方案:
- 新增 createSelfAppliedCommunity 工厂方法,状态直接设为 AUTHORIZED
- 新增 createSelfAppliedAuthCityCompany 工厂方法
- 新增 createSelfAppliedAuthProvinceCompany 工厂方法
- 更新事件类型允许 authorizedBy 为 null(表示自助申请)
- 自助申请处理方法改用新的工厂方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 16:59:20 -08:00
hailin 21519c1a97 fix(authorization): 使用 benefitActive 属性替代不存在的 isBenefitActivated 方法
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 06:17:34 -08:00
hailin 05c8e1d6aa refactor(authorization): 简化自助申请授权逻辑,移除待审核状态
自助申请授权直接生效,无需审核流程:
- 移除 pendingApplications 字段(不再需要待审核列表)
- 简化响应 DTO:applicationId -> authorizationId, 移除 status/reviewedAt/reviewNote
- 新增 benefitsActivated 字段表示是否已激活权益
- 更新前端 SelfApplyAuthorizationResponse 和 UserAuthorizationStatusResponse

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 06:13:14 -08:00
hailin 13df91a55e fix(wallet-service): 修复 resolve-address API 路径
identity-service 的 resolve-address 接口在 UserAccountController 下,
需要添加 /user 前缀:/users/resolve-address -> /user/users/resolve-address

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 04:17:11 -08:00
hailin 0374e2a55c fix(wallet-service): 修复 identity-client 响应数据解析
identity-service 使用响应拦截器将所有响应包装在 { success, data } 结构中。
修复所有方法的响应解析,从 response.data?.valid 改为 response.data?.data?.valid。

影响方法:
- verifyTotp
- isTotpEnabled
- verifyWithdrawSmsCode
- verifyPassword
- resolveAccountSequenceToAddress

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 04:12:48 -08:00
hailin 9ae1c1cbdb fix(wallet-service): 添加验证码验证调试日志并修复布尔值比较
- 添加完整响应数据日志以便调试
- 使用严格比较 === true 代替 ?? false

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 04:06:40 -08:00
hailin ac4bd46c13 fix(wallet-service): 添加 /api/v1 前缀到 identity-client 的 baseURL
identity-service 有全局前缀 api/v1,所以调用路径应该是:
- /api/v1/user/sms/send-withdraw-code
- /api/v1/user/sms/verify-withdraw-code
- /api/v1/user/verify-password

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 03:51:49 -08:00
hailin 9b9427d6a8 fix(identity-service): 修复 seed 脚本会清除所有用户数据的严重 bug
问题:每次部署 identity-service 时,seed 脚本会执行 deleteMany() 删除所有用户数据
修复:
- 检查现有用户数量,如果 > 5 则跳过 seed(保护生产数据)
- 移除所有 deleteMany() 调用
- 使用 upsert 确保系统账户存在而不是先删后建
- 管理员账户只在不存在时创建

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 03:28:59 -08:00
hailin 9bc7bb1200 fix(withdraw): 修复提取功能短信验证和手续费计算
- 修复 wallet-service 调用 identity-service 的 API 路径(添加 /user 前缀)
- 修复 identity-client 默认端口从 3001 改为 3000
- 添加 docker-compose 中 IDENTITY_SERVICE_URL 环境变量配置
- 手续费改为按 0.1% 费率动态计算(前后端统一)
- 最小提取金额从 10 改为 100
- 文案修改:Kava EVM 网络 → Kava安全网络,接收地址 → 接收账号

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 03:14:22 -08:00
hailin 74c78440f7 fix: 推荐码必填 + referral-service种子用户userId修复
1. register-by-phone.dto.ts: inviterReferralCode 改为必填
2. user-application.service.ts: 添加日志和推荐码验证
3. referral-service/seed.ts: userId改为25129999999(与accountSequence一致)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 00:37:08 -08:00
hailin 0220650cd9 fix(identity-service): 种子用户序列号改为 D25129999999
避免与真实用户序列号冲突

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 23:36:54 -08:00
hailin 1f15c494c1 fix(identity-service): 添加注册流程详细日志和保存验证
问题:用户注册后 referral-service 有数据但 identity-service 没有
原因:save() 方法和 registerByPhone 方法缺少日志,无法追踪问题

修复:
- save() 方法添加完整日志和 try-catch
- registerByPhone 方法添加每个步骤的日志
- 添加关键验证:保存后检查 userId 是否为 0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 23:19:24 -08:00
hailin 45fcae5ef5 revert: 撤销 admin-service seed 脚本
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 22:41:24 -08:00
hailin a1a9a087c5 fix(admin-service): 修复 Kafka topic 订阅不匹配问题
问题:admin-web 用户管理页面无数据
原因:admin-service 订阅的是 'identity.events',
     但 identity-service 发送到的是具体的 topic 如 'identity.UserAccountCreated'

修复:将订阅的 topics 改为与 identity-service 的 IDENTITY_TOPICS 一致:
- identity.UserAccountCreated
- identity.UserAccountAutoCreated
- identity.PhoneBound
- identity.KYCSubmitted
- identity.KYCVerified
- identity.KYCRejected
- identity.UserAccountFrozen
- identity.UserAccountDeactivated

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 22:40:31 -08:00
hailin 8579529571 feat(admin-service): 添加 seed 脚本同步系统账户到 user_query_view
问题:admin-web 用户管理页面无数据,因为 user_query_view 表是空的
原因:identity-service 的 seed 创建的系统账户不会触发 Kafka 事件

解决方案:
- 创建 admin-service 的 seed.ts,直接同步系统账户到 user_query_view
- 配置 package.json 的 prisma.seed

运行方式:
cd backend/services/admin-service && npx prisma db seed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 22:35:32 -08:00
hailin ecf3755227 feat: integrate real API for authorization apply page
Changes:
- Add generic image upload API endpoint (POST /user/upload-image)
- Add uploadImage method in StorageService for backend
- Add uploadImage method in AccountService for frontend
- Add selfApplyStatus and selfApplyAuthorization methods in AuthorizationService
- Replace mock data with real API calls in authorization apply page
- Add API endpoints for self-apply status and self-apply authorization

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:01:28 -08:00
hailin 5904f2f84d fix: improve logging for wallet retry task and idempotent status updates
- Change misleading "unexpected" log to correctly indicate idempotent behavior
- Add debug log for completed records being skipped in retry task

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 21:40:04 -08:00
hailin 188075b2be fix: 短信超时返回成功状态避免前端报错
超时情况下短信可能已发送成功,返回 success: true + uncertain: true

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:55:31 -08:00
hailin d36a58341d fix: 优化短信重试策略避免触发流控
- 降低重试次数到 2 次
- 增加基础延迟到 3 秒
- 超时错误不重试(短信可能已发送成功)
- 流控错误不重试

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:38:47 -08:00
hailin e5e4e3512b feat: 添加短信发送重试机制提高可靠性
- 最多重试 3 次(共 4 次尝试)
- 指数退避延迟(1s, 2s, 4s)
- 超时时间增加到 15 秒
- 只对网络错误重试,业务错误不重试
- 可重试错误:ConnectTimeout, ReadTimeout, ETIMEDOUT, ECONNRESET 等

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:32:45 -08:00
hailin b4dafc9e38 fix: 添加遗漏的 registerByPhone 方法到 user-application.service.ts
修复构建错误:Property 'registerByPhone' does not exist on type 'UserApplicationService'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:22:44 -08:00
hailin 2897a0c74c feat: 添加 register-by-phone API 实现手机号一步注册
- 后端: 添加 POST /user/register-by-phone 接口
  - 验证短信验证码、创建账户、绑定手机号、设置密码、触发钱包生成
  - 添加 RegisterByPhoneCommand 和 RegisterByPhoneDto
- 前端: 修改注册流程使用新 API
  - SmsVerifyPage 直接跳转到密码页面传递验证码
  - SetPasswordPage 调用 registerByPhoneWithPassword 一步完成
  - AccountService 添加 registerByPhoneWithPassword 方法

修复手机号注册流程中手机号和密码未正确保存的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:19:46 -08:00
hailin 86d3a3f6a2 perf(docker): 优化Dockerfile构建,避免最后chown整个目录
- 在build阶段提前创建用户和设置目录权限
- 使用--chown=nestjs:nodejs复制文件
- 删除chown -R nestjs:nodejs /app

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 19:31:58 -08:00
hailin b1508f1a5a fix(mpc-service): 注册DistributedLockService到InfrastructureModule
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 19:28:18 -08:00
hailin 10b25e222e fix: 防止钱包生成中状态下重复触发MPC keygen
问题:
- 前端在钱包状态为"generating"时仍然调用retryWalletGeneration
- 后端identity-service没有检查生成中状态
- mpc-service没有幂等保护,可能导致同一用户多次keygen

修复:
1. 前端 wallet_status_provider.dart:
   - 只在"failed"状态下才触发重试
   - "generating"状态只更新UI,继续轮询等待

2. 后端 identity-service user-application.service.ts:
   - retryWalletGeneration添加Redis状态检查
   - pending/generating/deriving状态下跳过重试
   - 只有failed或无状态时才触发重试

3. 后端 mpc-service keygen-requested.handler.ts:
   - 使用分布式锁防止同一用户重复keygen
   - 锁TTL为5分钟,覆盖整个keygen过程
   - 无法获取锁时跳过请求

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:55:51 -08:00
hailin c77cb7a55f fix: 添加 -m 参数创建用户home目录
npm cache 需要写入 /home/nestjs 目录,useradd 需要 -m 参数才会创建

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:01:19 -08:00
hailin 36f8ee1d6a fix: SEED01用户状态改为ACTIVE
- SYSTEM状态会被识别为冻结账户
- 必须是ACTIVE才能作为有效推荐人

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:52:06 -08:00
hailin 7a9bb26423 perf: 优化Dockerfile避免chown -R耗时
- 先创建用户再安装依赖
- 使用 COPY --chown 直接设置文件权限
- 移除 chown -R nestjs:nodejs /app 步骤
- 显著减少 Docker 构建时间

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:41:27 -08:00
hailin a533987013 fix: SEED01用户accountSequence改为D25122100000格式
- identity-service: S0000000005 -> D25122100000
- referral-service: S0000000005 -> D25122100000
- 种子用户序号0,真实用户从1开始

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:35:01 -08:00
hailin 17121da422 fix: referral-service启动时自动执行seed
- 添加ts-node依赖用于执行seed.ts
- 在start.sh中添加prisma db seed命令
- 与identity-service保持一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:19:16 -08:00
hailin 6039bffa73 fix: 修改种子用户推荐码为SEED01(6字符)
生产环境的ReferralCode值对象限制推荐码必须恰好6个字符,
GENESIS(7字符)不符合格式要求,改为SEED01

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 06:05:45 -08:00
hailin 80713fbb33 chore: 添加 tsbuildinfo 到 .gitignore
TypeScript 增量编译缓存文件不应提交到版本控制。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 04:34:26 -08:00
hailin 60faa5e3cc chore: 添加 prisma 编译文件到 .gitignore
防止 seed.ts 的编译产物(.js, .js.map, .d.ts)被误提交。
seed.ts 应该保持为源码形式,由 ts-node 直接执行。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 04:32:49 -08:00
hailin 9a5abab0bd fix: 修复 referral-service 编译配置以支持 prisma seed.ts
- 移除错误添加的 rootDir 配置(恢复原始行为)
- 在 tsconfig.build.json 中排除 prisma 目录
- 确保编译输出为 dist/main.js(符合 Dockerfile 期望)
- prisma/seed.ts 不会被 NestJS 编译流程处理

问题原因:添加 rootDir: "./src" 后,TypeScript 拒绝编译
src/ 目录之外的 prisma/seed.ts 文件。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 04:30:35 -08:00
hailin c58cc351d0 feat: 添加 GENESIS 系统种子用户用于初始推荐码
- 在 identity-service 中添加 GENESIS 用户 (userId=5, code=GENESIS)
- 创建 referral-service seed.ts 同步 GENESIS 推荐关系
- 新用户注册时可使用 GENESIS 推荐码进行注册
- GENESIS 用户作为根节点,便于追踪无推荐人的用户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 04:09:39 -08:00
hailin 7d6e776e5e refactor: 清理 migration 和 seed 数据重复定义
Migration 职责:
- 只负责表结构(CREATE TABLE、索引、外键)
- 设置 user_id 序列从 10 开始(预留 1-9 给系统)
- 移除 GENESIS 用户插入(数据应由 seed 管理)

Seed 职责:
- 恢复到前天状态,移除重复的 GENESIS 定义
- 保留 4 个系统账户(ID 1-4)
- 保留管理员账户初始化

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 00:43:28 -08:00
hailin 37f2b556e9 refactor: 合并 identity-service migrations 为单一 init
将 7 个碎片化的 migration 文件合并为一个完整的 init migration:
- 删除增量 migrations (add_user_totp, add_outbox_events, add_password_hash 等)
- 创建统一的 20241204000000_init migration 包含所有表结构
- 包含所有索引、外键约束、序列设置和系统种子用户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 00:32:58 -08:00
hailin 7a6d8adcb5 fix: 在 seed 中添加 GENESIS 系统种子用户
问题原因:
- seed.ts 会删除所有 userAccount 记录
- 即使 migration 创建了 GENESIS 用户,seed 运行后也会被删除
- 之前的系统账户使用 userId 1-4,但 GENESIS 应该是 userId 1

解决方案:
- 将 GENESIS 用户添加到 SYSTEM_ACCOUNTS 数组
- userId: 1, accountSequence: 'SYSTEM00001', referralCode: 'GENESIS'
- 其他系统账户的 userId 顺延到 2-5

系统账户列表:
- userId 1: GENESIS (系统种子用户,用于注册推荐码)
- userId 2: 总部社区 (HQ000001)
- userId 3: 成本费账户 (COST0002)
- userId 4: 运营费账户 (OPER0003)
- userId 5: RWAD底池账户 (POOL0004)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 23:44:15 -08:00
hailin 14d4107a10 fix: 修复推荐码验证 API 错误处理
后端修复:
- getUserByReferralCode() 在推荐码不存在时抛出异常
- 之前返回 null,导致前端无法正确判断错误

前端修复:
- 增强 verifyReferralCode() 的响应检查
- 检查 response.data 和 data 字段是否为 null
- 添加详细的 debug 日志输出
- null 响应视为推荐码无效并抛出异常

问题原因:
- 后端返回 null 时,前端解析 response.data.data 会得到 null
- 前端没有检查 null 情况,导致显示 "status: null" 错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 23:41:53 -08:00
hailin 636a06c241 feat: 手机号注册时触发钱包生成
修复问题:
- 之前手机号注册只创建账户,不生成钱包
- autoCreateAccount 方法会触发钱包生成,但 register 方法没有

解决方案:
- 在 register() 方法中添加 MpcKeygenRequestedEvent 发布
- 与 autoCreateAccount() 保持一致的钱包生成流程

流程:
1. 验证短信验证码和推荐码
2. 创建用户账户并保存到数据库
3. 发布 UserAccountCreatedEvent(推荐关系等)
4. 发布 MpcKeygenRequestedEvent(触发异步钱包生成)
5. 返回 JWT Token 给用户

钱包生成异步流程:
- MPC Service 监听 MpcKeygenRequestedEvent
- 生成 MPC 密钥对,发布 KeygenCompleted
- Blockchain Service 派生区块链地址
- Identity Service 保存钱包地址到数据库

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 23:11:16 -08:00
hailin ef9056c5ef revert: 移除 Dockerfile 中的 migration 特定修复逻辑
- Dockerfile 应该保持通用,不针对特定 migration
- migration 文件本身已修复(没有 created_at 列)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 22:09:50 -08:00
hailin 5fcaeb8794 fix: 恢复 GENESIS 种子用户 migration(正确版本)
- 之前误删了 migration 文件
- 重新创建正确的 migration(不包含 created_at 列)
- 添加启动时自动处理失败 migration 的机制

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 22:08:37 -08:00
hailin 0c94b966b0 fix(identity-service): 修复 GENESIS 种子用户 migration - 移除不存在的 created_at 列
- 修复 migration 失败问题:user_accounts 表只有 registered_at 和 updated_at,没有 created_at
- 保持 user_id = 1 用于系统种子用户(GENESIS 推荐码)
- 普通用户从 user_id = 10 开始

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 21:18:57 -08:00
hailin ac8eb6d38d fix: 修复系统种子用户 migration,移除错误的序列重置
问题:
- 之前的 migration (20251220000000) 已经预留了 user_id 1-9 给系统账号
- 并设置序列从 10 开始
- 不应该再次重置序列,否则会覆盖之前的设置

修复:
- 保留使用 user_id = 1(在预留范围内)
- 移除序列重置代码
- 添加注释说明与之前 migration 的关系

这样确保:
 系统账号使用 1-9
 普通用户从 10 开始(之前的设置)
 不会产生 ID 冲突

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 21:01:34 -08:00
hailin 9fd5d1d17d feat: 添加系统种子用户 migration (推荐码: GENESIS)
## 目的
解决"第一个用户无法注册"的问题,通过创建系统种子用户提供根推荐码。

## 种子用户信息
- User ID: 1 (固定ID)
- Account Sequence: SYSTEM00001
- 推荐码: GENESIS
- 昵称: 系统
- 状态: ACTIVE
- 手机号: NULL (系统用户不需要手机号)

## 使用方式
第一批用户在注册时使用推荐码 **GENESIS** 即可完成注册。

## 特点
 保持推荐码必填的业务逻辑
 所有用户都有完整的推荐关系链
 系统用户只提供推荐码功能,不参与其他业务
 使用固定 ID,方便识别和管理
 自动重置序列,确保后续用户从 100000000 开始

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:57:34 -08:00
hailin 4c645afc44 fix: 修复钱包重试事件创建的字段错误
移除 createWalletGenerationEvent 方法中不存在的字段:
- deviceName(事件定义中不存在)
- deviceInfo(事件定义中不存在)
- inviterReferralCode(应该是 inviterSequence)

使用正确的事件字段结构,与正常账号创建保持一致。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:45:10 -08:00
hailin d45be594a2 fix: 修复 UserAccountCreatedEvent phoneNumber 类型错误
修改 phoneNumber 字段类型从 string 改为 string | null,
以支持钱包重试场景中手机号可能为空的情况。

这个修复解决了 Docker 构建时的 TypeScript 编译错误:
- Type 'string | null' is not assignable to type 'string'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:43:26 -08:00
hailin b4c4239593 feat: 实现手机号+密码登录和账号恢复功能
## 后端更改

### 新增功能
- 添加手机号+密码登录 API (`POST /user/login-with-password`)
  - 新增 LoginWithPasswordDto 验证手机号格式和密码长度
  - 实现 loginWithPassword 服务方法,使用 bcrypt 验证密码
  - 返回 JWT tokens(accessToken + refreshToken)

### 代码优化
- 修复 phone.validator.ts 中的 TypeScript 类型错误(Object -> object)

## 前端更改

### 新增功能
- 实现手机号+密码登录页面 (phone_login_page.dart)
  - 完整的表单验证(手机号格式、密码长度)
  - 集成 AccountService.loginWithPassword API
  - 登录成功后自动更新认证状态并跳转主页

### 账号服务优化
- 在 AccountService 中添加 loginWithPassword 方法
  - 调用后端 login-with-password API
  - 自动保存认证数据(tokens、用户信息)
  - 使用 _savePhoneAuthData 统一保存逻辑

### UI 文案更新
- 向导页文案修改:"创建账号" → "注册账号"
  - 更新标题、副标题和按钮文本
  - 添加"恢复账号"按钮,跳转到手机号密码登录页

## 已验证功能

 前端代码编译通过(0 errors, 仅有非关键警告)
 后端代码编译通过(0 errors, 仅有非关键警告)
 30天登录状态保持(JWT refresh token 已配置为30天)
 自动路由逻辑(有登录状态直接进入主页)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:35:44 -08:00
hailin ceee3167cb feat(identity-service): 添加手动钱包重试 API
功能:
- 新增 POST /user/wallet/retry 接口
- 用户可主动触发钱包生成重试
- 自动检查钱包是否已完成,避免重复生成
- 幂等操作:重新发布 UserAccountCreatedEvent

实现:
- UserAccountController: 添加 wallet/retry 端点
- UserApplicationService: 实现 retryWalletGeneration 方法
- 重用现有的 createWalletGenerationEvent 方法
- 更新 Redis 状态为 pending

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 19:22:27 -08:00
hailin 959fe93092 feat(identity-service): 添加钱包生成自动重试机制
功能:
- 新增 WalletRetryTask 定时任务,每分钟扫描一次
- 自动检测超过 60 秒仍在 generating/deriving 状态的钱包
- 自动检测状态为 failed 的钱包生成
- 幂等重试机制,最多 10 分钟内持续重试
- 记录重试次数和时间戳

技术实现:
- 使用 @nestjs/schedule 的 Cron 装饰器
- 在 UserAccount 聚合根中添加 createWalletGenerationEvent() 方法
- 在 RedisService 中添加 keys() 方法支持模式匹配扫描
- 通过重新发布 UserAccountCreatedEvent 触发幂等重试

相关需求:
- 用户手机号验证成功后立即创建账号
- 钱包生成在后台异步进行
- 失败后自动重试,无需用户感知

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 19:20:55 -08:00
hailin 4ec92d015b fix(identity-service): 添加 CA 证书以支持 HTTPS 连接
- 在 Dockerfile 中安装 ca-certificates 包
- 修复阿里云短信 API SSL 证书验证错误
- 解决 "error setting certificate file" 问题

问题: curl 提示 "error setting certificate file: /etc/ssl/certs/ca-certificates.crt"
原因: 容器内缺少 CA 证书文件
解决: 安装 ca-certificates 包

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 18:30:04 -08:00
hailin 287ab6bfa9 fix(identity-service): 增加阿里云短信 API 连接超时时间
- 连接超时从默认值增加到 10 秒
- 读取超时从默认值增加到 10 秒
- 改善网络不稳定环境下的短信发送成功率

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 18:29:07 -08:00
hailin 3f904ab6f7 fix(identity-service): 设置 user_id 自增序列从 10 开始
- 添加数据库 migration 设置 user_id 序列起始值为 10
- 保留 user_id 1-9 给系统账户使用
- 修复用户注册时的唯一约束冲突错误
- 序列值安全检查:仅在当前值 < 10 时重置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 18:16:08 -08:00
hailin 1edbe7a9c9 fix(identity-service): 添加全局异常过滤器日志记录以便调试 2025-12-20 17:36:35 -08:00
hailin 4260930a55 docs(backend): 添加阿里云短信服务配置到 .env.example
在 backend/services/.env.example 中添加短信服务配置项:
- ALIYUN_ACCESS_KEY_ID: 阿里云 AccessKey ID
- ALIYUN_ACCESS_KEY_SECRET: 阿里云 AccessKey Secret
- ALIYUN_SMS_SIGN_NAME: 短信签名(默认:榴莲皇后)
- ALIYUN_SMS_TEMPLATE_CODE: 短信模板代码
- ALIYUN_SMS_ENDPOINT: API 端点
- SMS_ENABLED: 是否启用真实发送(默认 false)

部署者需要:
1. 在阿里云获取 AccessKey
2. 申请短信签名和模板
3. 复制 .env.example 到 .env 并填写实际值

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 05:55:42 -08:00
hailin 173640b869 feat(identity-service): 添加阿里云短信服务配置到 docker-compose
在 identity-service 的环境变量中添加阿里云 SMS 配置:
- ALIYUN_ACCESS_KEY_ID: 阿里云 AccessKey ID
- ALIYUN_ACCESS_KEY_SECRET: 阿里云 AccessKey Secret
- ALIYUN_SMS_SIGN_NAME: 短信签名(默认:榴莲皇后)
- ALIYUN_SMS_TEMPLATE_CODE: 短信模板代码
- ALIYUN_SMS_ENDPOINT: API 端点(默认:dysmsapi.aliyuncs.com)
- SMS_ENABLED: 是否启用真实发送(默认:false,使用模拟模式)

配置后需在 .env 文件或系统环境变量中设置实际值。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 05:46:27 -08:00
hailin 9ea3d03b73 fix(admin-service): 在主 docker-compose.yml 中添加 Kafka 配置
在 backend/services/docker-compose.yml 中为 admin-service 添加:
- KAFKA_BROKERS=kafka:29092
- KAFKA_CLIENT_ID=admin-service
- KAFKA_CONSUMER_GROUP=admin-service-user-sync
- kafka 服务依赖

确保生产环境部署时能正确连接 Kafka 同步用户数据。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 03:18:33 -08:00
hailin 4fabefc5d2 fix(admin-service): 添加 Kafka 配置解决用户数据同步问题
添加 KAFKA_BROKERS, KAFKA_CLIENT_ID, KAFKA_CONSUMER_GROUP 环境变量,
使 admin-service 能够正确连接 Kafka 并从 identity-service 同步用户数据。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 03:09:44 -08:00
hailin 3d93ebe928 fix(admin-service): 修复 Dockerfile 启动脚本生成问题
使用 printf 替代 echo 来创建 start.sh 脚本,确保正确处理换行符,
使数据库迁移能够在容器启动时正确执行。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 02:59:53 -08:00
hailin 00a239a271 fix(admin-service): 添加 user_query_view 等表的迁移文件
添加缺失的迁移文件:
- user_query_view 表(用户查询视图)
- event_consumer_offsets 表(事件消费位置追踪)
- processed_events 表(已处理事件记录)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 02:37:11 -08:00
hailin dc64a28efb refactor(reporting-service): 移除仪表板区域分布和趋势的模拟数据
- 区域分布无真实数据源时返回空数组
- 趋势数据无数据时返回空数组
- 删除 generateTrendData 模拟方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 02:26:34 -08:00
hailin 59b83acfa4 refactor(reporting-service): 移除仪表板最近活动的模拟数据
无真实数据时返回空数组,不再生成假数据

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 01:07:39 -08:00
hailin dbba229c91 fix(reporting-service): 启动 Kafka 微服务消费者以记录真实活动
- 在 main.ts 添加 Kafka 微服务连接配置
- 调用 startAllMicroservices() 启动事件消费
- 支持消费 identity/authorization/planting 服务的事件
- 实现仪表板"最近活动"显示真实数据

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 21:50:36 -08:00
hailin e153e2144d fix(identity-service): 添加 TotpService 到 ApplicationModule 2025-12-19 19:27:43 -08:00
hailin fd5768f8c5 fix(identity-service): 将 AuthController 和 TotpController 添加到 ApiModule 2025-12-19 19:17:46 -08:00
hailin 701deb1e27 fix(test): 修复测试文件 TypeScript 类型错误
authorization-service:
- UserId.create 第二个参数 accountSequence 由 BigInt 改为 string
- mockAuthorizationRoleRepository 添加缺失的方法
- TeamStatistics mock 对象添加 selfPlantingCount 和 subordinateTeamPlantingCount

reward-service:
- accountSequence 由 BigInt 改为 string 类型
- 方法调用参数名由 userId 改为 accountSequence

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 06:44:28 -08:00
hailin f20643599e fix: 修复多个服务的 TypeScript 编译错误
- admin-service: 添加 kafkajs 依赖,修复 SystemConfigEntity null vs undefined 类型
- authorization-service: 修复 selfPlantingCount 属性名,修复 AuthorizationRole factory 参数
- identity-service: 修复测试文件 accountSequence 类型(number -> string)
- admin-web: 在 authSlice 中添加 refreshToken 支持

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 06:29:49 -08:00
hailin 943fd9efe9 chore: 提交所有未提交的修改
包括:
- admin-service: 系统配置功能
- authorization-service: 自助授权申请功能
- planting-service: 资金分配服务
- reward-service: 奖励计算服务
- admin-web: 用户管理和设置页面
- mobile-app: 授权、认证、路由等功能

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 06:09:43 -08:00
hailin 56fed2e5f3 fix(identity-service): 在 Docker 启动时自动运行 seed
- 安装 ts-node 用于运行 seed.ts
- 启动脚本中添加 prisma db seed 命令
- 自动初始化管理员账户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 06:07:25 -08:00
hailin b2c82ebeab fix(identity-service): 修复 PrismaService 导入路径
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 05:27:17 -08:00
hailin cb40463521 feat(identity-service): 添加管理员登录功能
- 新增 AdminAccount 数据表存储管理员账户
- 在 AuthController 添加 POST /auth/login 端点
- 支持邮箱+密码登录,使用 bcrypt 验证
- 在 seed.ts 中初始化默认管理员账户
  - 邮箱: admin@rwadurian.com
  - 密码: Admin@123456
- 前端登录页面适配新的响应格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 05:17:50 -08:00
hailin 917e3094a2 fix(api-gateway,admin-web): 修复仪表板API路由配置
Kong 网关:
- 添加 /api/v1/dashboard 路由到 reporting-service

Admin-Web 前端:
- 修复所有 API endpoints 添加 /v1 前缀
- 确保与 Kong 路由配置一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 04:21:53 -08:00
hailin 9452d14962 feat(identity-service): 添加密码设置和短信验证功能
- 添加 bcrypt 依赖用于密码哈希
- 添加 passwordHash 字段到 UserAccount 模型
- 添加 VerifySmsCodeCommand 和 SetPasswordCommand
- 添加 VerifySmsCodeDto 和 SetPasswordDto
- 添加数据库迁移 add_password_hash

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 03:23:36 -08:00
hailin 2662409d80 fix(identity-service): 修复 TypeScript 编译错误
- 修复 account.id -> account.userId 属性访问错误
- 修复 smsService.verifySmsCode 方法调用,改为直接从 Redis 验证

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 03:20:37 -08:00
hailin 5b2d255506 feat(auth): 增强提现安全验证
- 集成阿里云短信服务 (dysmsapi20170525)
- 提现需同时验证短信验证码和登录密码
- identity-service 添加 /verify-password API
- wallet-service 调用双重验证
- 移动端提现确认页添加密码输入

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 03:05:53 -08:00
hailin ca619bff0b feat(admin): 实现用户管理功能完整前后端架构
## 概述
为 admin-web 用户管理页面实现完整的前后端架构,采用事件驱动 CQRS 模式,
通过 Kafka 事件同步用户数据到本地物化视图,避免跨服务 HTTP 调用。

## admin-service 后端变更

### 数据库 Schema
- UserQueryView: 用户查询视图表 (通过 Kafka 事件同步)
- EventConsumerOffset: 事件消费位置追踪
- ProcessedEvent: 已处理事件记录 (幂等性)

### 新增组件
- IUserQueryRepository: 用户查询仓储接口
- UserQueryRepositoryImpl: 用户查询仓储实现
- UserEventConsumerService: Kafka 事件消费者
- UserController: 用户管理 API 控制器

### API 端点
- GET /admin/users: 用户列表 (分页/筛选/排序)
- GET /admin/users/🆔 用户详情
- GET /admin/users/stats/summary: 用户统计

## identity-service 变更
- 新增 UserProfileUpdatedEvent 事件
- updateProfile 方法现在会发布事件

## admin-web 前端变更
- userService: 用户 API 服务封装
- useUsers/useUserDetail: React Query hooks
- 用户管理页面接入真实 API
- 添加加载骨架屏/错误重试/空数据提示

## 架构特点
- CQRS: 读从本地视图,写触发事件
- 事件驱动: Kafka 事件同步,微服务解耦
- Outbox 模式: 可靠事件发布
- 幂等性: ProcessedEvent 防重复处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 02:29:11 -08:00
hailin 92850d8c62 chore(deploy): 添加 blockchain-service 到部署脚本
- health 检查列表添加 blockchain-service
- migrate 服务列表添加 blockchain-service
- 帮助文档更新服务列表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:32:23 -08:00
hailin 0e367d042c feat(reporting): 实现 Dashboard API 完整功能
## 概述
为 reporting-service 实现完整的 Dashboard API 端点,支持统计卡片、趋势图表、
区域分布和最近活动等功能。

## API 端点
- GET /dashboard/stats: 获取统计卡片数据
- GET /dashboard/charts: 获取趋势图表数据 (支持 7d/30d/90d 周期)
- GET /dashboard/region: 获取区域分布数据
- GET /dashboard/activities: 获取最近活动列表

## 新增 DTO
- DashboardStatsResponseDto: 统计卡片响应
- DashboardTrendResponseDto: 趋势数据响应
- DashboardRegionResponseDto: 区域分布响应
- DashboardActivitiesResponseDto: 活动列表响应

## Repository 层
- IDashboardStatsSnapshotRepository: 统计快照接口
- IDashboardTrendDataRepository: 趋势数据接口
- ISystemActivityRepository: 系统活动接口

## External Clients (已弃用)
- AuthorizationServiceClient: 授权服务客户端
- IdentityServiceClient: 身份服务客户端
注:已改为事件驱动架构,这些客户端仅作为备用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:31:08 -08:00
hailin f65b0d14b7 feat(authorization): 实现 Outbox 模式事件发布
## 概述
为 authorization-service 实现 Outbox 模式,确保数据库事务和 Kafka 事件发布的原子性。

## 新增表
- OutboxEvent: 事件暂存表,用于事务性事件发布

## 新增组件
- OutboxRepository: Outbox 事件持久化
- OutboxPublisherService: 轮询发布未处理事件到 Kafka

## 支持的事件
- authorization-events: 授权角色创建/更新事件(省公司、市公司授权)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:30:09 -08:00
hailin 05a9ca31f6 feat(identity): 实现 Outbox 模式事件发布
## 概述
为 identity-service 实现 Outbox 模式,确保数据库事务和 Kafka 事件发布的原子性。

## 新增表
- OutboxEvent: 事件暂存表,用于事务性事件发布

## 新增组件
- OutboxRepository: Outbox 事件持久化
- OutboxPublisherService: 轮询发布未处理事件到 Kafka

## 支持的事件
- identity.UserAccountCreated: 用户注册事件
- identity.UserAccountAutoCreated: 自动创建用户事件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:29:40 -08:00
hailin e684068eae feat(reporting): 实现事件驱动的仪表板统计架构
## 概述
将 reporting-service Dashboard 从 HTTP API 调用改为事件驱动架构,
通过消费 Kafka 事件在本地维护统计数据,实现微服务间解耦。

## 架构变更
之前: Dashboard → HTTP → planting/authorization/identity-service
现在: 各服务 → Kafka → reporting-service → 本地统计表 → Dashboard

## 新增表
- RealtimeStats: 每日实时统计 (认种数/订单数/新用户/授权数)
- GlobalStats: 全局累计统计 (总认种/总用户/总公司数)

## 新增仓储
- IRealtimeStatsRepository: 实时统计接口及实现
- IGlobalStatsRepository: 全局统计接口及实现

## Kafka 消费者更新
- identity.UserAccountCreated: 累加用户统计
- identity.UserAccountAutoCreated: 累加用户统计
- authorization-events: 累加省/市公司统计
- planting.order.paid: 累加认种统计

## Dashboard 服务更新
- getStats(): 从 GlobalStats/RealtimeStats 读取,计算环比变化
- getTrendData(): 从 RealtimeStats 获取趋势数据

## 优势
- 消除跨服务 HTTP 调用延迟
- 统计数据实时更新
- 微服务间完全解耦

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:25:31 -08:00
hailin 30db6b4238 fix(ledger): 优化账本明细流水类型显示
前端:
- 删除 '充值 (BSC)' 筛选选项
- '充值 (KAVA)' → '充值绿积分'
- 添加 '提取' 筛选选项 (REWARD_SETTLED)

后端:
- '充值 (KAVA)' → '充值绿积分'
- '奖励结算' → '提取'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 08:44:34 -08:00
hailin d565bb91fa feat(authorization): 添加审计查询方法支持查询已删除记录
- findAllByUserIdIncludeDeleted: 按用户ID查询所有记录(含已删除)
- findAllByAccountSequenceIncludeDeleted: 按账号序列查询所有记录(含已删除)
- findByIdIncludeDeleted: 按ID查询记录(含已删除)

确保撤销的授权记录可审计追溯

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 07:53:37 -08:00
hailin 29df9955f9 feat(authorization): 实现软删除支持撤销后重新授权
- 添加 deletedAt 字段到 AuthorizationRole 聚合根和 Prisma schema
- revoke() 方法同时设置 deletedAt,使撤销的记录被软删除
- Repository 所有查询添加 deletedAt: null 过滤条件
- 创建部分唯一索引,只对未删除记录生效 (大厂通用做法)
- 支持撤销授权后重新创建相同角色

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 07:43:30 -08:00
hailin 15e2bfe236 feat(trading): 添加账本明细页面,含统计图表和流水筛选
后端新增:
- GET /wallet/ledger/statistics 流水统计API(按类型汇总)
- GET /wallet/ledger/trend 流水趋势API(按日期统计)
- LedgerStatisticsResponseDTO, LedgerTrendResponseDTO 等DTO

前端新增:
- 账本明细页面(统计概览Tab + 流水明细Tab)
- 收支概览卡片、趋势柱状图、按类型统计
- 流水列表支持分页加载和类型筛选
- 兑换页面右上角添加账本明细入口

授权服务:
- 5种授权方法添加认种前置检查(需至少认种1棵树才能授权)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 07:41:07 -08:00
hailin cf27e55c45 fix: 修正 sourceOrderNo 属性访问路径 2025-12-17 06:58:21 -08:00
hailin 36074948d7 feat(reward): 可结算列表改为从 reward-service 读取
将前端可结算奖励列表的数据源从 wallet-service 改为 reward-service:
- 后端:在 reward-service 添加 GET /rewards/settleable 接口
- 前端:修改 getSettleableRewards() 调用 /rewards/settleable
- 前端:更新 SettleableRewardItem 字段映射 (rightType, claimedAt, sourceOrderNo, memo)

解决权益收益(社区权益、市区域权益)无法在可结算列表显示的问题。
遵循单一数据源原则,reward-service 是奖励的权威数据源。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 06:55:41 -08:00
hailin 834a1fc0b0 fix(authorization): 省区域和市区域授权即激活,无需初始考核
修改 createProvinceCompany 和 createCityCompany 方法:
- 授权后立即激活权益 (benefitActive: true)
- 从第1个月开始考核 (currentMonthIndex: 1)
- 省区域月度目标:150, 300, 600, 1200, 2400, 4800, 9600, 19200, 11750
- 市区域月度目标:30, 60, 120, 240, 480, 960, 1920, 3840, 2350
- 保留 skipAssessment 参数兼容性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 03:44:48 -08:00
hailin 1cc27731d9 fix(planting): 移除个人最大认种数量限制
删除 MAX_TREES_PER_USER = 1000 的限制和 checkRiskControl 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 01:10:03 -08:00
hailin 92772f071a feat(ui): 优化待领取明细显示和移除认种数量限制
- 移除单次认种100棵的数量限制 (planting-service)
- 龙虎榜省市信息分两行显示
- 待领取明细改为堆叠卡片样式,节省屏幕空间
  - 支持上下滑动选择卡片
  - 滑动时有震动反馈
  - 选中卡片展开显示完整信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 22:46:48 -08:00
hailin 2399cc29d6 fix(authorization): 修正省区域角色唯一性检查逻辑
将省区域角色从"全系统唯一"改为"按省份唯一":
- 修改 grantProvinceCompany 使用 findProvinceCompanyByRegion 检查
- 删除废弃的 findAnyProvinceCompany 方法
- 现在不同省份可以分别授权给不同账户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 17:20:36 -08:00
hailin 2730bcb354 feat(identity): 完善账户安全和恢复功能
1. 账户冻结/解冻功能:
   - POST /user/freeze: 用户主动冻结账户
   - POST /user/unfreeze: 验证身份后解冻账户(支持助记词或手机号验证)
   - 添加 AccountUnfrozenEvent 审计事件

2. 密钥轮换功能:
   - POST /user/key-rotation/request: 验证助记词后请求 MPC 密钥轮换
   - 添加 KeyRotationRequestedEvent 事件触发后台轮换

3. 恢复码备份功能:
   - POST /user/backup-codes/generate: 生成8个一次性恢复码
   - POST /user/recover-by-backup-code: 使用恢复码恢复账户
   - 恢复码存储在 Redis,有效期1年
   - 每个恢复码只能使用一次

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 17:06:28 -08:00
hailin f2a6c09d86 feat(identity/blockchain): 增强助记词安全性和审计日志
1. blockchain-service 助记词验证增强:
   - 验证前先检查是否存在已挂失(REVOKED)的助记词记录
   - 如果检测到挂失记录,立即拒绝恢复请求

2. identity-service 审计日志事件:
   - 新增 AccountRecoveredEvent: 账户恢复成功事件
   - 新增 AccountRecoveryFailedEvent: 账户恢复失败事件
   - 新增 MnemonicRevokedEvent: 助记词挂失事件

3. 恢复操作审计:
   - recoverByMnemonic: 记录所有失败原因和成功事件
   - recoverByPhone: 记录所有失败原因和成功事件
   - revokeMnemonic: 记录挂失成功事件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 16:56:42 -08:00
hailin d3e680ea14 feat(identity/blockchain): 添加助记词挂失功能
后端:
- blockchain-service: 新增 revokeMnemonic() 方法和 POST /internal/mnemonic/revoke API
- identity-service: 新增 POST /user/mnemonic/revoke 用户端API
- 挂失后助记词状态变为 REVOKED,无法用于账户恢复

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 07:56:27 -08:00
hailin 257236480f feat(wallet/profile): 添加可结算和已过期奖励逐笔显示功能
后端:
- wallet-service 新增 getSettleableRewards() 和 getExpiredRewards() 方法
- 新增 GET /wallet/settleable-rewards 和 GET /wallet/expired-rewards API

前端:
- reward_service.dart 新增 SettleableRewardItem、ExpiredRewardItem 数据模型
- profile_page.dart 可结算区域和已过期区域支持逐笔明细显示

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 07:20:44 -08:00
hailin bad14bcb32 chore(admin-service): 更新 package-lock.json
同步 uuid 依赖到 lock 文件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 01:00:08 -08:00
hailin 44f7e16d3a fix(admin-service): 添加缺失的 uuid 依赖
notification.controller.ts 使用了 uuid 生成 ID,但 package.json 缺少依赖

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 00:57:04 -08:00
hailin ab31ad3726 feat(blockchain): 添加 Redis 缓存自动恢复机制
扫描区块时检测缓存是否为空,如果为空则自动从数据库重新加载地址缓存,
避免因 Redis 数据丢失导致充值漏检。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 23:13:04 -08:00
hailin c1fe54a8d4 feat: 暂时禁用 BSC 链,添加 Kafka 企业级重试配置
- blockchain-service: getSupportedChains() 只返回 KAVA
- 所有 Kafka consumer 添加企业级重试配置(15次重试,指数退避)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 22:33:34 -08:00
hailin 286e6aad01 fix(db): 添加缺失的数据库迁移文件
问题:
- wallet-service schema 中有 version 字段,但迁移文件中缺失
- presence-service 缺少初始化迁移文件

修复:
- wallet-service: 添加 20241216000000_add_version_column 迁移
- presence-service: 添加 20241204000000_init 初始化迁移(包含 version 字段)
- presence-service: 删除无效的 20251215100000 迁移(依赖不存在的表)

验证所有服务 schema 与 migration 一致性:
- identity-service:  OK
- wallet-service:  已修复
- blockchain-service:  OK (无 version 字段)
- planting-service:  OK
- reward-service:  OK
- referral-service:  OK
- leaderboard-service:  OK
- presence-service:  已修复

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 21:53:31 -08:00
hailin e75b968aeb feat(identity): 增强账户创建流程可靠性
问题:
- saveWallets() 无事务保护,并发时可能部分成功部分失败
- 事件处理器静默失败,Kafka 不会重试
- 无幂等性检查,重试可能创建重复钱包

修复:
1. saveWallets() 添加事务保护 + 幂等性检查
   - 使用 prisma.$transaction 确保原子性
   - 检查已存在的钱包地址,跳过重复创建

2. 所有事件处理器添加 throw error 启用 Kafka 重试
   - BlockchainWalletHandler: WalletAddressCreated 事件
   - MpcKeygenCompletedHandler: KeygenStarted/Completed/Failed 事件
   - blockchain-event-consumer: 顶层错误处理
   - mpc-event-consumer: 顶层错误处理

影响文件:
- user-account.repository.impl.ts: saveWallets 事务+幂等
- blockchain-wallet.handler.ts: throw error
- mpc-keygen-completed.handler.ts: throw error (3处)
- blockchain-event-consumer.service.ts: throw error
- mpc-event-consumer.service.ts: throw error

预期效果:
- 100并发账户创建成功率: 85% → 97%+
- Kafka 消息失败自动重试
- 防止重复创建钱包地址

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 20:37:54 -08:00
hailin be7ec87f05 feat(wallet): 增强认种流程可靠性 - 添加事务保护和乐观锁
## 问题背景

认种流程(冻结→确认扣款→解冻)存在以下可靠性问题:
1. 余额检查与冻结操作非原子性,存在并发竞态条件
2. 钱包更新与流水记录分开执行,可能导致数据不一致
3. 缺少乐观锁机制,并发修改时可能出现余额错误
4. Kafka consumer 错误被吞掉,消费失败无法重试

## 修复内容

### wallet-application.service.ts

1. **freezeForPlanting (冻结资金)**
   - 添加 `prisma.$transaction` 事务保护
   - 添加乐观锁 (version 字段检查)
   - 添加重试机制 (最多 3 次,指数退避)
   - 幂等性检查移入事务内,避免竞态

2. **confirmPlantingDeduction (确认扣款)**
   - 添加事务保护,确保扣款与流水原子性
   - 添加乐观锁防止并发修改
   - 添加重试机制

3. **unfreezeForPlanting (解冻资金)**
   - 添加事务保护,确保解冻与流水原子性
   - 添加乐观锁防止并发修改
   - 添加重试机制

### planting-event-consumer.service.ts

- 添加 `throw error` 重新抛出错误
- 确保消费失败时 Kafka 能感知并触发重试

## 乐观锁实现

```typescript
const updateResult = await tx.walletAccount.updateMany({
  where: {
    id: walletRecord.id,
    version: currentVersion,  // 版本检查
  },
  data: {
    usdtAvailable: newAvailable,
    version: currentVersion + 1,  // 版本递增
  },
});

if (updateResult.count === 0) {
  throw new OptimisticLockError('版本冲突');
}
```

## 测试验证

- wallet-service 构建成功
- 服务重启正常,所有 handler 注册成功

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:56:49 -08:00
hailin a01284678d feat(wallet/mpc): 增强提现和充值流程可靠性
## 主要改进

### MPC 签名系统 (mpc-system)
- 添加签名缓存机制,避免重复签名请求
- 修复 yParity 恢复逻辑,确保签名格式正确
- 优化签名完成报告流程

### 区块链服务 (blockchain-service)
- EIP-1559 降级为 Legacy 交易(KAVA 测试网兼容)
- 修复 gas 估算逻辑

### 钱包服务 (wallet-service)
- 添加乐观锁机制 (version 字段) 防止并发修改
- 提现确认流程添加事务保护 + 乐观锁
- 提现失败时正确解冻 amount + fee
- 充值流程添加事务保护 + 乐观锁
- Kafka consumer 添加错误重抛,触发重试机制

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:47:20 -08:00
hailin dcf857059e fix(scripts): 修正容器名为 rwa-blockchain-service
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:34:25 -08:00
hailin b9b6dacbab fix(scripts): 使用 docker exec blockchain-service 计算地址
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:32:43 -08:00
hailin 6fe615eac5 fix(scripts): 进入 blockchain-service 目录使用 ethers 计算地址
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:30:19 -08:00
hailin a4d3f21475 revert(scripts): 恢复到 578a865 版本
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:28:05 -08:00
hailin 8465f53996 fix(scripts): 使用项目目录的 ethers 计算地址
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:27:42 -08:00
hailin 578a865c4d feat(scripts): 获取 mpc-system 实际创建的 username
- 添加 get_actual_username 函数从数据库查询实际 username
- mpc-system 自动生成 wallet-xxx 格式,脚本输出实际值
- show_result 使用 ACTUAL_USERNAME 显示正确配置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:22:34 -08:00
hailin cdf858520d revert(scripts): 恢复脚本到JWT认证版本,不修改username
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:20:43 -08:00
hailin 8641529028 revert: 移除 verify_and_fix_username 调用
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:19:28 -08:00
hailin 0bf52c7b2c fix(scripts): 自动修复热钱包 username
- verify_and_fix_username 函数通过 docker exec 直接查询和更新数据库
- 移除手动回退,全自动化处理
- 将函数添加到主流程中

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:18:33 -08:00
hailin 2af5938821 fix(mpc-service): 规范化 messageHash 去掉 0x 前缀
mpc-system 期望纯 hex 字符串(不带 0x 前缀),
blockchain-service 发送的 messageHash 带有 0x 前缀导致 400 错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 10:00:21 -08:00
hailin 54ac2ee225 feat(mpc): 将 blockchain-service MPC 签名从 HTTP 改为 Kafka 事件驱动
重构 blockchain-service 和 mpc-service 之间的 MPC 签名通信方式:
- blockchain-service: MpcSigningClient 改用 Kafka 发布签名请求事件
- blockchain-service: MpcEventConsumerService 新增 SigningCompleted 事件监听
- mpc-service: SigningRequestedHandler 支持识别请求来源 (source 字段)

事件流:
blockchain-service → Kafka(mpc.SigningRequested) → mpc-service
mpc-service → HTTP → mpc-system
mpc-service → Kafka(mpc.SigningCompleted) → blockchain-service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 09:45:39 -08:00
hailin 0682f6aac3 Revert "fix(mpc-service): 添加 DTO 验证装饰器"
This reverts commit 6eb4b6b153.
2025-12-15 09:36:31 -08:00
hailin 6eb4b6b153 fix(mpc-service): 添加 DTO 验证装饰器
添加 class-validator 装饰器到 CreateKeygenDto 和 CreateSigningDto,
修复 NestJS ValidationPipe 的 forbidNonWhitelisted 验证错误。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 09:36:03 -08:00
hailin 9b3f33ea42 fix(blockchain): 修复 MPC 签名 API 路径
mpc-service 使用全局前缀 api/v1,调整签名 API 路径:
- /mpc/sign → /api/v1/mpc/sign
- /mpc/sign/:sessionId/status → /api/v1/mpc/sign/:sessionId/status

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 09:28:47 -08:00
hailin 71e805b1fd feat(deploy): 添加 HOT_WALLET 配置到 install 模板
在 deploy.sh 的 install() 函数中添加热钱包配置,
新部署时会自动包含这些环境变量。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 09:06:51 -08:00
hailin 317532109d config: 添加热钱包配置
HOT_WALLET_USERNAME=rwadurian-system-hot-wallet-01
HOT_WALLET_ADDRESS=0x895aaf83C57f807416E3BbBd093d7aB74a6FDd33

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:58:42 -08:00
hailin 93c658d914 fix(scripts): 添加 JWT 认证支持
mpc-system account-service 需要 JWT 认证,脚本需要:
- 添加 --jwt-secret 参数或从 MPC_JWT_SECRET 环境变量读取
- 使用 openssl 生成 HS256 JWT token
- 所有 API 请求添加 Authorization: Bearer header

用法:
  export MPC_JWT_SECRET='your_secret'
  ./init-hot-wallet.sh --username rwadurian-system-hot-wallet-01 --threshold-n 3 --threshold-t 2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:52:40 -08:00
hailin c0e6e1f620 refactor(scripts): 简化热钱包初始化脚本参数
- 只保留 --username, --threshold-n, --threshold-t 参数
- 移除 --host, --verbose, --help 参数(host 固定为 localhost:4000)
- username 改为必填参数
- 更新使用说明和错误提示

用法: ./init-hot-wallet.sh --username rwadurian-system-hot-wallet-01 --threshold-n 3 --threshold-t 2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:48:51 -08:00
hailin fce8a919ff fix(scripts): 修改热钱包初始化脚本直接调用mpc-system
- 改为直接调用 mpc-system account-service (端口 4000)
- 使用 snake_case API 格式 (threshold_n, threshold_t, require_delegate)
- 系统热钱包设置 require_delegate: false (不需要用户持有share)
- 更新状态查询路径为 /api/v1/mpc/sessions/{sessionId}

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:44:45 -08:00
hailin 9531405c9b fix(scripts): 修复热钱包初始化脚本默认端口为3006
mpc-service 实际运行在 3006 端口,将脚本默认值从 3013 改为 3006

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:20:48 -08:00
hailin ad22c23656 refactor(scripts): 完善热钱包MPC初始化脚本
主要改进:
- 修复API路径: /mpc/keygen -> /api/v1/mpc/keygen
- 添加彩色日志输出 (info/success/warn/error/debug)
- 添加依赖检查 (curl, jq)
- 添加服务连通性检查 (health endpoint)
- 添加参数验证
- 添加详细模式 (-v/--verbose)
- 改进等待进度显示 (spinner动画)
- 支持多种地址派生方式 (Node.js ethers / Python eth_keys)
- 改进错误处理和用户提示
- 添加使用示例
- 完成后提供一键复制的环境变量配置命令

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:17:40 -08:00
hailin 9cac91b5f0 feat(blockchain): 将提现转账从私钥签名改为 MPC 签名
背景:
- 原实现使用 HOT_WALLET_PRIVATE_KEY 进行热钱包签名
- 私钥直接存储存在安全风险
- 系统已有 MPC 基础设施,应该复用

改动内容:

1. 新增 MPC 签名客户端
   - infrastructure/mpc/mpc-signing.client.ts: 调用 mpc-service 的签名 API
   - 支持创建签名会话、轮询等待、获取签名结果

2. 重构 ERC20 转账服务
   - domain/services/erc20-transfer.service.ts: 从私钥签名改为 MPC 签名
   - 移除 Wallet 依赖,改用 Transaction 手动构建交易
   - 使用 MPC 签名后广播已签名交易

3. 新增初始化服务
   - mpc-transfer-initializer.service.ts: 启动时注入 MPC 客户端
   - 解决 Domain 层和 Infrastructure 层的循环依赖

4. 新增热钱包初始化脚本
   - scripts/init-hot-wallet.sh: 便捷创建系统热钱包的 MPC 密钥
   - 支持配置门限值、用户名等参数

5. 更新配置
   - 移除 HOT_WALLET_PRIVATE_KEY 依赖
   - 新增 MPC_SERVICE_URL, HOT_WALLET_USERNAME, HOT_WALLET_ADDRESS
   - 更新 docker-compose.yml 和 .env.example

部署前需要:
1. 运行 init-hot-wallet.sh 初始化热钱包
2. 配置 HOT_WALLET_USERNAME 和 HOT_WALLET_ADDRESS
3. 向热钱包充值 USDT 和原生币(gas)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 08:04:17 -08:00
hailin 28c44d7219 fix(wallet): 提现失败解冻时优先使用 accountSequence 查找钱包
问题背景:
- 原实现使用 userId 查找钱包进行解冻操作
- userId 来自外部 identity-service,存在变化风险
- 如果 userId 发生变化,可能导致解冻到错误的钱包

解决方案:
- 优先使用 accountSequence 查找钱包(wallet-service 内部主键,稳定可靠)
- 保留 userId 作为兜底查找方式,确保向后兼容
- 增加钱包找不到时的详细错误日志

改动点:
- withdrawal-status.handler.ts: handleWithdrawalFailed() 方法
- 与认种(planting)的钱包查找逻辑保持一致

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 07:37:36 -08:00
hailin 80b74e9877 feat(sentry): 集成 Sentry 自建崩溃收集与错误追踪系统
Backend (infrastructure/sentry):
- 添加 Sentry 自建部署 Docker Compose 配置
- 包含 PostgreSQL, Redis, Kafka, ClickHouse, Snuba 等组件
- 添加 Relay (事件网关) 和 Symbolicator (符号化服务) 配置
- 添加部署脚本 deploy.sh 和配置文件
- 更新 infrastructure README 文档

Frontend (mobile-app):
- 添加 sentry_flutter SDK 依赖
- 创建 SentryService 封装类,统一管理崩溃收集
- 创建 SentryConfig 配置类,支持开发/生产环境配置
- 创建 SentryNavigationObserver 自动追踪页面导航
- 创建 SentryDioInterceptor 自动追踪 HTTP 请求
- 在 bootstrap.dart 中集成 Sentry 初始化
- 支持 Flutter 错误和异步错误捕获
- 自动过滤敏感信息 (密码、助记词、私钥等)
- 在登录/登出/切换账号时同步 Sentry 用户信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 07:15:13 -08:00
hailin cc06638e0e feat(telemetry): 将userId改为userSerialNum字符串格式并完善遥测追踪
Backend (presence-service):
- 将EventLog.userId从BigInt改为String类型,存储userSerialNum(如D25121400005)
- 更新Prisma schema,userId字段改为VarChar(20)并添加索引
- 更新心跳相关命令和事件,统一使用userSerialNum字符串
- 添加数据库迁移文件
- 更新相关单元测试和集成测试

Frontend (mobile-app):
- TelemetryEvent新增toServerJson()方法,格式化为后端API期望的格式
- AccountService登录/恢复时设置TelemetryService的userId
- MultiAccountService切换账号时同步更新TelemetryService的userId
- 退出登录时清除TelemetryService的userId
- AuthProvider初始化时设置userId

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 06:55:25 -08:00
hailin 579e8c241e fix(backend): 修复构建错误并添加 TOTP 数据库迁移
修复内容:
- identity-service: 添加 CurrentUserPayload 接口定义
- identity-service: 添加 user_totp 表的数据库迁移文件
- wallet-service: 安装 axios 依赖
- wallet-service: 修复 withdrawal-status.handler.ts 中的类型错误
  - userId.toString() → userId.value (BigInt 类型)
  - unfreezeUsdt() → unfreeze() (正确的方法名)
  - amount.asNumber → amount.value (Money 值对象属性)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:29:29 -08:00
hailin b01277ab7d feat(withdraw): 实现完整的提取功能 - TOTP验证和KAVA转账
功能实现:
- identity-service: 添加TOTP二次验证功能
  - 新增 UserTotp 数据模型
  - 实现 TotpService (生成/验证/启用/禁用)
  - 添加 /totp/* API端点

- wallet-service: 提取API添加TOTP验证
  - withdrawal.dto 添加可选 totpCode 字段
  - 添加 IdentityClientService 调用identity-service验证TOTP
  - 添加 WithdrawalStatusHandler 处理区块链确认/失败事件

- blockchain-service: 实现真实KAVA ERC20转账
  - 新增 Erc20TransferService (热钱包USDT转账)
  - 更新 withdrawal-requested.handler 执行真实转账
  - 发布确认/失败事件回wallet-service

- 前端: 对接真实提取API
  - withdraw_confirm_page 调用 walletService.withdrawUsdt

环境变量配置:
- TOTP_ENCRYPTION_KEY (identity-service)
- IDENTITY_SERVICE_URL (wallet-service)
- HOT_WALLET_PRIVATE_KEY (blockchain-service)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:16:42 -08:00
hailin 09e66cef10 refactor: 多项UI优化和品牌更名
- 品牌更名: 将"榴莲女皇"全部替换为"榴莲皇后"(前端+后端共15处)
- 导航优化: 将"交易"Tab改名为"兑换"
- 创建钱包页: 添加返回按钮,可返回向导页第5页(仅账号未创建时显示)
- 兑换页面: 禁用"一键结算"和"卖出DST"按钮,提款按钮在余额为0时禁用

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 01:43:47 -08:00
hailin db37fbf860 feat(notification): 添加通知中心功能
后端 (admin-service):
- 新增 Notification 和 NotificationRead 数据模型
- 支持通知类型: 系统/活动/收益/升级/公告
- 实现管理端 API: 创建/更新/删除/列表
- 实现移动端 API: 获取通知列表/未读数量/标记已读

前端 (mobile-app):
- 新增 NotificationService 和 Provider
- 新增通知中心页面 (NotificationInboxPage)
- 在"我的"页面右上角添加通知图标(带未读角标)
- 支持查看通知详情、标记已读、全部已读

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 20:45:03 -08:00
hailin 2e44263834 feat(profile): 添加我的伞下功能 - 展示下级用户树形结构
- 后端新增 GET /referral/user/:accountSequence/direct-referrals API
- 前端新增伞下树组件,支持懒加载、缓存、展开/收起
- 使用 CustomPaint 绘制父子节点连接线
- 超出屏幕宽度时显示省略号,点击弹出底部列表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 10:34:56 -08:00
hailin ed47e7ab2d fix(authorization): 修复下级团队认种数重复减去自己认种数的 BUG
问题描述:
- 社区/省公司/市公司的初始考核判断错误
- 原因: referral-service 返回的 totalTeamPlantingCount 已经是"下级团队认种数"(不含自己)
  但 authorization-service 又减了一次 selfPlantingCount,导致结果偏小

示例:
- D25121400003: 自己认种12棵,下级认种14棵
- 修复前: subordinateTeamPlantingCount = 14 - 12 = 2 (错误!)
- 修复后: subordinateTeamPlantingCount = 14 (正确)

影响范围:
- 社区权益初始考核 (10棵门槛)
- 省公司权益初始考核
- 市公司权益初始考核 (100棵门槛)
- 所有使用 subordinateTeamPlantingCount 的业务逻辑

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 09:15:00 -08:00
hailin 090c8b747e fix(reward): 修复 accountSequence 转 userId 时字母前缀导致的 BigInt 转换失败
问题描述:
- 社区权益激活后,用户收不到奖励
- 错误: SyntaxError: Cannot convert D25121400002 to a BigInt
- 原因: accountSequence 格式为 D25121400002 (D+日期+序号),直接 BigInt() 转换失败

修改方案:
- 新增 parseAccountSequenceToUserId() 辅助方法
- 如果 accountSequence 以字母开头,去掉第一个字符后再转 BigInt
- 影响 5 个方法: calculateProvinceTeamRight, calculateProvinceAreaRight,
  calculateCityTeamRight, calculateCityAreaRight, calculateCommunityRight

技术背景:
- accountSequence 格式: D25121400002 (用户) / S0000000001 (固定系统账户) / 9440000 (省系统)
- 省市系统账户在 authorization-service 动态创建,identity-service 中不存在
- reward-service 的 userId 字段实际业务中不被使用 (查询用 accountSequence)

潜在隐患:
1. userId 字段存储的不是 identity-service 中的真实 userId
   - D25121400002 -> 25121400002 (不是真实的自增 userId)
   - S0000000001 -> 1 (恰好匹配固定系统账户)
   - 9440000 -> 9440000 (省系统账户,本无字母前缀)
2. 如果未来 reward-service 需要与 identity-service 关联查询,可能出现问题
3. 建议后续考虑: 将 userId 改为可选字段,或完全移除该字段依赖

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 08:18:23 -08:00
hailin c7d54da49f fix(reward): 修复调用 authorization-service 时传递 userId 而非 accountSequence 的问题
- IAuthorizationServiceClient 接口参数类型从 userId: bigint 改为 accountSequence: string
- authorization-service.client.ts 调用时使用正确的 accountSequence 格式
- calculateCommunityRight/calculateProvinceTeamRight/calculateCityTeamRight 方法增加 sourceAccountSequence 参数

此修复确保 reward-service 调用 authorization-service 时传递正确的用户标识格式(如 D25121400006),
而不是数字形式的 userId(如 7),使 authorization-service 能正确查找社区授权记录。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 06:48:58 -08:00
hailin c9f944355c fix(referral): 修复 getReferralChain API 返回 accountSequence 而非 userId
- 修改 getReferralChain 方法返回的 ancestorPath 为 accountSequence 格式
- 修改 getBatchReferralChains 方法同样返回 accountSequence 格式
- 这修复了 authorization-service 查询社区层级时使用错误格式的问题
- 之前返回 userId (如 "25121400000"),现在返回 accountSequence (如 "D25121400000")

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 06:10:41 -08:00
hailin 367e34f3a6 fix(reward): 待领取奖励转可结算使用accountSequence
- 添加 claimPendingRewardsForAccountSequence 方法
- event-consumer 改用 accountSequence 查找待领取奖励
- 修复上家认种后待领取奖励不能转为可结算的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 05:58:19 -08:00
hailin 7d95a35204 fix(referral): 团队统计使用accountSequence替代userId
- UpdateTeamStatisticsCommand 改用 accountSequence
- PlantingCreatedHandler 传递 accountSequence
- TeamStatisticsService 使用 findByAccountSequence 查询
- 修复上家团队认种数不正确的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 05:46:11 -08:00
hailin a7c36b5ee1 fix(referral): 使用JWT中的accountSequence替代userId查询
- JwtAuthGuard解析accountSequence字段放入request.user
- getMyReferralInfo和getMyDirectReferrals改用accountSequence
- 修复referral-service与identity-service用户ID不匹配问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 05:27:22 -08:00
hailin 6ef8824ef0 fix(referral): 修复 getMyReferralInfo 使用 userId 而不是 accountSequence 的问题
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 05:05:03 -08:00
hailin 1a97a9df54 fix(reward): add WALLET_SERVICE_URL to reward-service
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 04:52:24 -08:00
hailin d6055099c7 fix(planting): 支付完成后直接开启挖矿,跳过底池注入流程
- enableMining() 允许从 PAID 状态直接开启
- addPlanting() 树直接进入 effectiveTreeCount
- payOrder() 删除底池批次逻辑,直接调用 enableMining()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 04:25:31 -08:00
hailin 17c3f61657 fix(identity): 优化默认昵称格式为简洁序号
修改默认昵称生成逻辑:
- 从完整序列号中提取后5位数字
- 去掉前导零后组合
- 示例: D24121400001 -> 榴莲女皇1号

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 03:33:40 -08:00
hailin 7c72be3ba0 fix(docker): 修复 referral-service Dockerfile 健康检查 URL
修复 referral-service 的健康检查端点配置:
- referral-service: /health -> /api/v1/health

注:backup-service 使用 /health,leaderboard-service 使用 /api/health(这是服务本身实现的端点)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 03:05:18 -08:00
hailin cd742856c0 fix(identity): 优化默认昵称生成格式
将新用户默认昵称从「用户D2512140001」改为「用户1」,
使用 accountSequence.dailySequence 提取当日序号并去除前导零。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:59:01 -08:00
hailin 35f5d54a0c fix(planting): 无推荐人时分享权益进入分享权益池
- 将无推荐人时的分享权益目标从 SYSTEM_HEADQUARTERS_COMMUNITY 改为 SYSTEM_SHARE_RIGHT_POOL
- 将 SYSTEM:OPERATION_ACCOUNT 改为 SYSTEM:SHARE_RIGHT_POOL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:18:32 -08:00
hailin 4478351f89 fix(authorization): 修复 grantProvinceCompany 业务验证逻辑
- 添加省区域/市区域互斥检查:同一用户不能同时拥有两种身份
- 添加省区域全局唯一性检查:整个系统只允许一个省区域角色被授权
- 添加 findAnyProvinceCompany 仓储方法用于全局唯一性校验
- 移除错误的 validateAuthorizationRequest 调用(该方法只适用于团队角色)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:15:09 -08:00
hailin 298ce52fc7 fix(authorization): 修复 grantCityCompany 业务验证逻辑
- 添加市区域/省区域互斥检查:同一用户不能同时拥有两种身份
- 添加用户市区域唯一性检查:一个用户只能有一个市区域角色
- 添加城市全局唯一性检查:同一城市只允许一个市区域角色
- 移除错误的 validateAuthorizationRequest 调用(该方法只适用于团队角色)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:11:13 -08:00
hailin 10ce981111 fix(authorization-service): 社区授权唯一性约束
- 一个用户只能拥有一个社区角色
- 社区名称全局唯一,不允许重复
- 添加 findCommunityByName repository 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:04:24 -08:00
hailin 95e1cdffba feat(authorization-service): 正式省公司(PROVINCE_COMPANY)阶梯考核及月度考核
- 添加 PROVINCE_COMPANY_LADDER 阶梯目标配置 (150→300→600→1200→2400→4800→9600→19200→11750)
- 修改 getProvinceAreaRewardDistribution 使用阶梯目标判断激活条件
- 添加 processExpiredProvinceCompanyBenefits 月度考核方法
- 添加每月最后一天23:59定时任务执行省公司月度考核
- 添加月度数据存档方法 archiveAndResetProvinceCompanyMonthlyTreeCounts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 23:43:41 -08:00
hailin 1896dd6b4c feat(authorization-service): 正式市公司(CITY_COMPANY)阶梯考核及月度考核
- 添加 CITY_COMPANY_LADDER 阶梯目标配置 (30→60→120→240→480→960→1920→3840→2350)
- 修改 getCityAreaRewardDistribution 使用阶梯目标激活权益
- 添加 processExpiredCityCompanyBenefits 月度考核处理方法
- 添加月末23:59考核定时任务 (判断是否当月最后一天)
- 添加正式市公司月度数据存档定时任务

业务规则:
- 第一个月达标30棵树即可激活权益
- 每月最后一天23:59执行考核
- 达标续期并递增月份索引
- 不达标停用权益

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 23:34:55 -08:00
hailin 4d58d4be6c feat(authorization-service): 省团队授权级联激活/停用及月度考核
- 添加 cascadeActivateParentAuthProvinces: 当省团队授权激活时级联激活上级省团队
- 添加 cascadeDeactivateAuthProvinceBenefits: 月度考核失败时级联停用上级省团队
- 添加 processExpiredAuthProvinceBenefits: 月度考核处理(500棵树/月)
- 修改 tryActivateBenefit 支持 AUTH_PROVINCE_COMPANY 级联激活
- 定时任务: 每天凌晨5点检查省团队权益过期
- 定时任务: 每月1号存档并重置省团队月度新增树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:32:39 -08:00
hailin 049a13c97e feat(authorization-service): 市团队授权级联激活/停用及月度考核
- 添加 cascadeActivateParentAuthCities: 当市团队授权激活时级联激活上级市团队
- 添加 cascadeDeactivateAuthCityBenefits: 月度考核失败时级联停用上级市团队
- 添加 processExpiredAuthCityBenefits: 月度考核处理(100棵树/月)
- 添加 findExpiredActiveByRoleType 仓储方法
- 修改 tryActivateBenefit 支持 AUTH_CITY_COMPANY 级联激活
- 定时任务: 每天凌晨4点检查市团队权益过期
- 定时任务: 每月1号存档并重置市团队月度新增树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:04:59 -08:00
hailin 4a2a1e3855 feat(authorization-service): 为 getProvinceTeamRewardDistribution 添加 addMonthlyTrees 调用
参考 getCommunityRewardDistribution 的实现,在以下三个场景添加月度新增树数累计:
1. benefitActive=true 时:全部 treeCount 给该省团队,累加 treeCount
2. currentTeamCount >= initialTarget 时(兜底处理):累加 treeCount
3. 跨越考核达标点时:只累加归自己的部分 afterTargetCount

这确保了省团队权益与社区权益的月度考核追踪逻辑一致。
- 考核目标:500棵(省团队)
- 奖励:20 USDT
- 无上级时分配到系统省团队账户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:55:28 -08:00
hailin 8f91a5b985 feat(authorization-service): 为 getCityTeamRewardDistribution 添加 addMonthlyTrees 调用
参考 getCommunityRewardDistribution 的实现,在以下三个场景添加月度新增树数累计:
1. benefitActive=true 时:全部 treeCount 给该市团队,累加 treeCount
2. currentTeamCount >= initialTarget 时(兜底处理):累加 treeCount
3. 跨越考核达标点时:只累加归自己的部分 afterTargetCount

这确保了市团队权益与社区权益的月度考核追踪逻辑一致。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:36:37 -08:00
hailin d12bf6df2f fix(authorization-service): 修复权益分配边界逻辑 + 添加 addMonthlyTrees 调用
边界逻辑修复:
- 社区/省/市团队和区域权益分配:第N棵(达标棵)也给上级,第N+1棵起才给自己
- 例如社区:第1-10棵全部给上级的上级/总部,第11棵起才归该社区

addMonthlyTrees 调用:
- 权益已激活时:累加全部树数
- 初始考核达标后:累加归自己的那部分(第11棵起)
- 已达标但未激活时:累加全部树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:24:16 -08:00
hailin 6bd6c6b5be feat(authorization-service): 实现月度考核数据存档机制(方案B)
- 新增 lastMonthTreesAdded 字段,用于存档上月业绩数据
- 新增 archiveAndResetMonthlyTreeCounts 定时任务:每月1日0:00将当月数据存档后重置
- 新增 getTreesForAssessment() 方法:根据 benefitValidUntil 判断使用当月或上月数据
- 修复月度考核时序问题:数据重置(0:00)在考核(3:00)之前执行

业务规则:
- 严格自然月统计,11月的业绩不计入12月
- 激活当月免考核,考核激活当月的下一个月
- 权益有效期在上月末 → 使用 lastMonthTreesAdded
- 权益有效期在当月末 → 使用 monthlyTreesAdded

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 20:39:16 -08:00
hailin b705c6aa91 feat(wallet-service): 新增分享权益池账户S0000000005
- 新增 S0000000005 分享权益池系统账户 (user_id = -5)
- 修改 reward-service: 无推荐人的分享权益(500 USDT/棵)进入分享权益池
- 与总部社区账户(S0000000001)分离,便于单独追踪无推荐人的分享权益

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 18:53:21 -08:00
hailin 947e81b58d chore(wallet-service): 确保 @nestjs/schedule 依赖正确配置
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 17:13:21 -08:00
hailin 2af44e5854 feat(authorization-service): 实现社区权益月度考核及级联激活/停用功能
- 新增 benefitValidUntil、lastAssessmentMonth、monthlyTreesAdded 字段追踪月度考核
- 实现级联激活:当社区权益激活时,自动激活所有上级社区的权益
- 实现级联停用:当月度考核不达标时,级联停用该社区及所有上级社区
- 新增定时任务:每天凌晨3点检查过期社区权益,每月1号凌晨重置月度树数
- 权益有效期为当前月+下月末

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 07:23:46 -08:00
hailin 846915badc fix(wallet-service): 使用事务确保 settleUserPendingRewards 原子性
- 将 pending_rewards 状态更新和 wallet_accounts 余额更新包装在 Prisma $transaction 中
- 修复 Bug 4: pending_rewards 被标记为 SETTLED 但 settleable_usdt 未更新的问题
- 添加 PrismaService 依赖注入
- 同时减少 pendingUsdt/pendingHashpower,增加 settleableUsdt/settleableHashpower
- 记录 REWARD_TO_SETTLEABLE 类型的流水

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:58:07 -08:00
hailin c93f43546e fix(planting-service): PlantingOrderPaidEvent 添加 accountSequence 字段
Bug 3 修复: wallet-service 结算待领取奖励时需要 accountSequence

- PlantingOrderPaidEvent 事件 data 添加 accountSequence 字段
- markAsPaid(accountSequence) 方法接收并传递 accountSequence
- payOrder 调用 markAsPaid 时传入 accountSequence
- 更新相关单元测试

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:13:59 -08:00
hailin 28864e6160 fix(wallet-service): 修复待领取奖励显示和结算触发问题
Bug 1: allocateToUserWallet 同步更新 wallet_accounts.pending_usdt
- 写入 pending_rewards 表时同步调用 wallet.addPendingReward()
- 修复前端待领取金额显示为 0 的问题

Bug 2: Kafka 事件类型匹配兼容 planting-service 格式
- 支持 eventName 字段解析 (planting-service 使用)
- 支持 data 字段解析 (planting-service 使用)
- 新增 PlantingOrderPaid 事件类型支持
- 修复用户认种后待领取无法转换为可结算的问题

其他: 定时任务频率改为每分钟一次 (测试用途)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 05:51:28 -08:00
hailin e4389a5733 fix(wallet-service): 优化资金分配逻辑 - 区分直接到账和待领取
- SHARE_RIGHT (分享权益): 写入 pending_rewards 表,24小时待领取
- PROVINCE_TEAM_RIGHT/PROVINCE_AREA_RIGHT/CITY_TEAM_RIGHT/CITY_AREA_RIGHT: 直接到账
- COMMUNITY_RIGHT (社区权益): 进入总部社区账户 S0000000001,直接到账

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 04:51:34 -08:00
hailin 737fc3bb3c fix(wallet-service): allocateToUserWallet 改用 pending_rewards 表
- 移除 wallet.addPendingReward() 调用(旧方案,更新 wallet_accounts.pending_usdt)
- 改用 PendingReward.create() + pendingRewardRepo.save() 写入 pending_rewards 表
- 支持 7+省代码(省团队)和 6+市代码(市团队)账户格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 03:53:23 -08:00
hailin 8f81c46d75 feat: 省市团队账户及待领取奖励逐笔追踪
1. authorization-service:
   - 省团队权益分配改用系统省团队账户 (7+provinceCode)
   - 市团队权益分配改用系统市团队账户 (6+cityCode)
   - 无推荐链时不再进总部,而是进对应团队账户

2. wallet-service:
   - 新增 pending_rewards 表支持逐笔追踪待领取奖励
   - ensureRegionAccounts 同时创建区域账户和团队账户
   - 新增 getPendingRewards API 查询待领取列表
   - 新增 settleUserPendingRewards 用户认种后结算
   - 新增 processExpiredRewards 定时处理过期奖励
   - PlantingCreatedHandler 监听认种事件触发结算
   - ExpiredRewardsScheduler 每小时处理过期奖励

账户格式:
- 省区域: 9+provinceCode (如 9440000)
- 市区域: 8+cityCode (如 8440100)
- 省团队: 7+provinceCode (如 7440000)
- 市团队: 6+cityCode (如 6440100)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 03:32:47 -08:00
hailin 4d3290f029 fix(wallet-service): 修复系统账户资金分配功能
问题:
- 认种订单支付后,系统账户(成本费、运营费、总部社区、RWA底池)余额始终为0
- reward-service 正确计算分配,但 wallet-service 未实际执行系统账户的资金转移

根本原因:
1. allocateToSystemAccount() 方法只打印日志,未执行任何数据库操作(遗留的 TODO)
2. UserId 值对象不允许负数,而系统账户 user_id 为负数(-1 到 -4)

修复内容:

1. wallet-application.service.ts - allocateToSystemAccount()
   - 实现完整的系统账户资金分配逻辑
   - 通过 findByAccountSequence() 获取系统账户
   - 调用 addAvailableBalance() 直接增加可用余额
   - 创建 SYSTEM_ALLOCATION 类型的流水记录

2. wallet-account.aggregate.ts
   - 新增 addAvailableBalance(amount: Money) 方法
   - 用于系统账户直接增加余额(无需待领取/过期机制)

3. ledger-entry-type.enum.ts
   - 新增 SYSTEM_ALLOCATION 枚举值,用于系统账户分配流水

4. user-id.vo.ts
   - 移除负数校验,允许系统账户使用负数 user_id
   - 系统账户约定:-1(总部社区)、-2(成本费)、-3(运营费)、-4(RWA底池)

验证结果(认种1棵树=2199 USDT):
- S0000000001 总部社区: 9 USDT ✓
- S0000000002 成本费账户: 400 USDT ✓
- S0000000003 运营费账户: 300 USDT ✓
- S0000000004 RWA底池: 800 USDT ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 02:01:48 -08:00