The AuthEventBus was causing "Cannot use ref functions after the
dependency of a provider changed" error when 401 responses triggered
logout during provider rebuilds.
Now 401 handling is done through normal exception flow in splash page
and route guards respond to isLoggedInProvider state changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Login fixes:
- Add AuthEventBus for global 401 error handling with auto-logout
- Add route guards with GoRouter redirect to protect authenticated routes
- Remove setMockUser() security vulnerability and legacy login() dead code
- Remove unused AuthInterceptor class
Contribution page:
- Add ContributionRecord entity and model for records API
- Connect contribution details card to GET /accounts/{id}/records endpoint
- Display real team stats (direct referrals, unlocked levels/tiers)
- Calculate expiration countdown from actual record data
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change Dockerfile to use `prisma db push` instead of `migrate deploy`
- Add publish steps for contribution records and network progress in full-reset
- This ensures new tables are created automatically when schema changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
合同生成时使用 new Date().toISOString().split('T')[0] 获取日期,
该方法返回UTC时间,导致北京时间凌晨签署的合同显示为前一天日期。
修复方案:新增 getBeijingDateString() 函数,将UTC时间转换为北京时间(UTC+8)
影响范围:仅影响PDF合同上显示的签署日期,不影响数据库时间戳或业务逻辑
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed display name from "总部社区" to "总部" in:
- authorization-service
- identity-service seed
- leaderboard-service seed and entity
Note: Existing database records need manual update if already seeded.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add complete settlement-to-balance feature that transfers settleable
earnings directly to wallet USDT balance (no currency swap). Key changes:
Backend (wallet-service):
- Add SettleToBalanceCommand for settlement operations
- Add settleToBalance method to WalletAccountAggregate
- Add settleToBalance application service with ledger recording
- Add internal API endpoint POST /api/v1/wallets/settle-to-balance
Backend (reward-service):
- Add settleToBalance client method for wallet-service communication
- Add settleRewardsToBalance application service method
- Add user-facing API endpoint POST /rewards/settle-to-balance
- Build detailed settlement memo with source user tracking per reward
Frontend (mobile-app):
- Add SettleToBalanceResult model class
- Add settleToBalance() method to RewardService
- Update pending_actions_page to handle SETTLE_REWARDS action
- Add completion detection via settleableUsdt balance check
Settlement memo now includes detailed breakdown by right type with
source user accountSequence for each reward entry, e.g.:
结算 1000.00 绿积分到钱包余额
涉及 5 笔奖励
- SHARE_RIGHT: 500.00 绿积分
来自 D2512120001: 288.00 绿积分
来自 D2512120002: 212.00 绿积分
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add accountSequence field to PendingActionResponseDto
- Add helper methods to fetch accountSequence from UserAccount
- Update queryActions and getAction to include accountSequence
- Update admin-web table and detail view to show both fields
- accountSequence displayed prominently, userId shown as secondary info
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The TSS native bridge returns signatures in Base64 format, but the
broadcast function expected hex format. Added Base64 decoding in
broadcastTransaction() to properly parse r, s, v components.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The resetSessionStatus() function was not clearing pendingSessionId,
causing events from new sessions to be ignored because pendingSessionId
still held the old session ID.
Added:
- Clear pendingSessionId = null in resetSessionStatus()
- Clear _currentSession.value = null in resetSessionStatus()
- Added debug logging for session state clearing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Add sign initiator handling for participant_joined events in MainViewModel
- Add sign initiator handling for session_started events in MainViewModel
- Add sign initiator handling for all_joined events in MainViewModel
- Set pendingSessionId in TssRepository.createSignSession for event matching
- Refactor initiateSignSession to wait for session_started instead of starting immediately
- Add PendingSignInitiatorInfo data class to store pending sign info
- Add sessionAlreadyInProgress flag to SignSessionResult for immediate trigger case
This fixes the issue where sign initiator couldn't detect when other parties
joined the signing session, making Android flow 100% consistent with Electron.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical fixes to prevent app crashes when screens are kept open for extended periods:
- Add repositoryScope with SupervisorJob for structured concurrency in TssRepository
- Replace detached CoroutineScope(Dispatchers.IO).launch with repositoryScope.launch:
- Session event subscription (line 206)
- Session status polling (line 291)
- Message routing (line 1508)
- Add cleanup() method to properly cancel all jobs and repositoryScope
- Update disconnect() to also cancel sessionStatusPollingJob
- Update MainViewModel.onCleared() to call repository.cleanup()
This ensures all background coroutines are properly cancelled when the ViewModel
is cleared, preventing memory accumulation over time.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AppSettingEntity and AppSettingDao to Database.kt for key-value storage
- Add database migration (version 1 → 2) to create app_settings table
- Modify TssRepository.registerParty() to load/create partyId from database
- PartyId is now persisted across app restarts, matching Electron's getOrCreatePartyId()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The app was crashing with FRAME_SIZE_ERROR because the gRPC client
was using plaintext mode when connecting to port 443 (TLS endpoint).
This caused the client to receive encrypted data that it couldn't parse.
Fix: Use useTransportSecurity() for port 443, usePlaintext() for other ports.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
User says 3-of-5 meaning 3 signers needed, but tss-lib threshold t means t+1 signers.
Pass thresholdT-1 so tss-lib needs (t-1)+1 = t signers, matching user expectation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change /sign to /cosign/join so participants use the correct page
with auto-join functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fetch keygen session status from backend to get accurate party_index
- Filter out co-managed-party-* (server persistent parties) from signing
- Only temporary/external user parties participate in signing
- For 3-of-5 wallet: 3 user parties sign, 2 co-managed parties are backup only
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>