- P2P-HIGH-1: Add peer scoring system with success/failure/timeout tracking
- PERF-HIGH-2: Add JSON encoding buffer pool for hot paths
- API-HIGH-1: Standardize error responses using APIError struct
- RESIL-MED-5: Add graceful disconnect with reason/code messages
All verified items (SQL indexes, keepalive) were already implemented.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 11 tests covering CRUD operations for ProfileManager
- Test persistence/loading of profiles from disk
- Test concurrent access (multiple goroutines)
- Test error handling for invalid JSON and missing files
- Test rollback on failed create
- Test config data preservation through save/load
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GenerateChallenge() for random 32-byte challenge generation
- Add SignChallenge() using HMAC-SHA256 with shared secret
- Add VerifyChallenge() with constant-time comparison
- Update performHandshake() to send challenge and verify response
- Update handleWSUpgrade() to sign incoming challenges
- Add comprehensive tests for challenge-response flow
The challenge-response authentication proves the peer has the matching
private key for their public key by signing a random challenge with
the ECDH-derived shared secret. This prevents impersonation attacks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add PeerAuthMode to control peer registration:
- PeerAuthOpen: Allow all peers (backward compatible default)
- PeerAuthAllowlist: Only allow pre-registered peers or allowlisted public keys
New features:
- PeerRegistry.SetAuthMode/GetAuthMode for mode control
- PeerRegistry.AllowPublicKey/RevokePublicKey for key management
- PeerRegistry.IsPeerAllowed check before connection acceptance
- Transport rejects unauthorized peers with proper handshake rejection
New API endpoints:
- GET/PUT /peers/auth/mode - Get/set authentication mode
- GET/POST/DELETE /peers/auth/allowlist - Manage allowlisted keys
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CONC-HIGH-1: Add mutex to wsClient.miners map to prevent race condition
P2P-CRIT-2: Add MaxMessageSize config (1MB default) to prevent memory exhaustion
P2P-CRIT-3: Track pending connections during handshake to enforce connection limits
RESIL-HIGH-1: Add recover() to 4 background goroutines to prevent service crashes
TEST-CRIT-1: Create auth_test.go with 16 tests covering Basic/Digest auth
RESIL-HIGH-3: Implement circuit breaker for GitHub API with caching fallback
Also fixed: NonceExpiry validation in auth.go to prevent panic on zero interval
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Error Handling:
- Fix silent Write() error in WebSocket (events.go)
- Add error context to transport handshake messages
- Check os.MkdirAll error in zip extraction (miner.go)
- Explicitly ignore io.Copy errors on drain with comments
- Add retry logic (2 attempts) for transient stats collection failures
Resource Lifecycle:
- Add shutdown mechanism to DigestAuth goroutine
- Call Service.Stop() on context cancellation
- Add NodeService transport cleanup to Service.Stop()
- Fix WriteStdin goroutine leak on timeout with non-blocking send
API Design:
- Add profile validation (name, miner type required)
- Return 404 instead of 500 for missing profile PUT
- Make DELETE profile idempotent (return success if not found)
- Standardize error responses in node_service.go handlers
Observability:
- Add logging for P2P GetAllStats failures
- Add request ID correlation helper for handler logs
- Add logging for miner process exits (xmrig_start.go)
- Rate limit debug logs in transport hot path (1 in 100)
- Add metrics infrastructure with /metrics endpoint
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Integrate gin-mcp to expose mining API endpoints as MCP tools,
enabling AI assistants like Claude, Cursor, and Continue to
interact directly with the mining dashboard.
- Add gin-mcp dependency
- Initialize MCP server in SetupRoutes
- Mount at /api/v1/mining/mcp
- Automatically converts 40 API routes to MCP tools
AI assistants can now connect via SSE to discover and call
mining API operations programmatically.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reliability fixes:
- Fix race condition on uninitialized HTTP server in transport.go
- Add proper error logging for HTTP server startup errors
- Fix potential goroutine leak in process cleanup (xmrig_start.go)
- Propagate context to DB writes for proper timeout handling
Architecture improvements:
- Centralize GitHub version fetching via FetchLatestGitHubVersion()
- Add respondWithMiningError() helper for standardized API error responses
- Update XMRig and TTMiner to use centralized version fetcher
Documentation:
- Add CHANGELOG.md with release history
- Update FUTURE_IDEAS.md with demo GIF task
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Migrate all log.Printf/Println calls across the codebase to use the
new pkg/logging structured logging package. This provides consistent
log formatting with levels, timestamps, and structured key-value fields.
Files updated:
- pkg/mining/manager.go, service.go, events.go, miner.go
- pkg/mining/xmrig_start.go, ttminer_start.go
- pkg/mining/syslog_unix.go, syslog_windows.go
- pkg/database/hashrate.go
- pkg/node/worker.go, transport.go, peer.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add visual diagrams to ARCHITECTURE.md:
- System overview diagram showing all components
- Data flow sequence diagram for miner start
- WebSocket event flow diagram
Diagrams render automatically on GitHub and in MkDocs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create pkg/logging with:
- Log levels: Debug, Info, Warn, Error
- Structured fields support (key-value pairs)
- Component-based logging (WithComponent)
- Global logger convenience functions
- ParseLevel for configuration
- Full test coverage
The package provides a migration path from log.Printf to
structured logging without external dependencies.
Example usage:
logging.Info("miner started", logging.Fields{"name": minerName})
logger := logging.New(cfg).WithComponent("Manager")
logger.Warn("connection lost", logging.Fields{"pool": pool})
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Collect stats from multiple miners concurrently using goroutines
- Minimize lock duration by taking a snapshot of miners early
- Remove redundant existence check (snapshot is sufficient)
- Extract collectSingleMinerStats for cleaner code
- Add early return when no miners are present
This reduces overall stats collection time when multiple miners
are running, as API calls now happen in parallel instead of
sequentially.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create pkg/mining/miner_factory.go with factory pattern
- Support for miner type aliases (e.g., "ttminer" -> "tt-miner")
- Add global convenience functions: CreateMiner, IsMinerSupported, etc.
- Replace 5 duplicate switch statements in manager.go and service.go
- Makes adding new miner types simpler (single registration point)
- Full test coverage in miner_factory_test.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add pkg/mining/manager_race_test.go with concurrent miner tests
- Add pkg/database/database_race_test.go with concurrent DB tests
- Add TestCleanupRetention, TestGetHashrateHistoryTimeRange tests
- Add TestMultipleMinerStats, TestIsInitialized tests
- Fix AVG() float64 to int scan error in GetHashrateStats
- Fix AVG() float64 to int scan error in GetAllMinerStats
- Fix throttle tests to use NewManagerForSimulation to avoid
autostart conflicts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- TestStartMiner_Ugly: Add algorithm to config for consistent instance naming,
ensuring duplicate detection works correctly
- TestListMiners_Good: Account for autostarted miners by checking delta instead
of absolute count
- TestListMiners: Renamed from TestListMinersEmpty since autostart may add miners
- Add defer manager.Stop() to all tests in mining_test.go for proper cleanup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add requestIDMiddleware that generates/propagates request IDs
- Accepts X-Request-ID from incoming requests or generates new one
- Sets request ID in response header and gin context
- Update CORS to allow/expose X-Request-ID header
Enables request tracing across logs for debugging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add APIError struct with code, message, details, suggestion, retryable
- Add error code constants (MINER_NOT_FOUND, PROFILE_NOT_FOUND, etc.)
- Add respondWithError helper with automatic suggestions per error type
- Update miner not found and profile not found errors to use new format
- Fix .gitignore to not match pkg/mining directory
Improves DX by providing machine-readable error codes and actionable suggestions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Why Mining Platform?" comparison table vs NiceHash, HiveOS, manual
- Highlight unique features: open source, no fees, embeddable, simulation mode
- Add simulation mode to Core Capabilities list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GitHub Actions CI status badge
- Add Angular 20+ badge with logo
- Add platform support badge (Linux/macOS/Windows)
- Update Go badge with logo
- Reorganize badge order: CI/Release → Tech → Quality → License
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WebSocket Real-Time Events:
- Add EventHub for broadcasting miner events to connected clients
- New event types: miner.starting/started/stopping/stopped/stats/error
- WebSocket endpoint at /ws/events with auto-reconnect support
- Angular WebSocketService with RxJS event streams and fallback to polling
Simulation Mode (miner-ctrl simulate):
- SimulatedMiner generates realistic hashrate data for UI development
- Supports presets: cpu-low, cpu-medium, cpu-high, gpu-ethash, gpu-kawpow
- Features: variance, sine-wave fluctuation, 30s ramp-up, 98% share rate
- XMRig-compatible stats format for full UI compatibility
- NewManagerForSimulation() skips autostart of real miners
Miners Page Redesign:
- Featured cards for installed/recommended miners with gradient styling
- "Installed" (green) and "Recommended" (gold) ribbon badges
- Placeholder cards for 8 planned miners with "Coming Soon" badges
- Algorithm badges, GitHub links, and license info for each miner
- Planned miners: T-Rex, lolMiner, Rigel, BzMiner, SRBMiner, TeamRedMiner, GMiner, NBMiner
Chart Improvements:
- Hybrid data approach: live in-memory data while active, database historical when inactive
- Smoother transitions between data sources
Documentation:
- Updated DEVELOPMENT.md with simulation mode usage
- Updated ARCHITECTURE.md with WebSocket, simulation, and supported miners table
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show spinning indicator while start/stop actions are in progress
- Disable buttons during loading to prevent double-clicks
- Applied to: start profile, stop worker, context menu stop
- Spinner uses CSS animation for smooth visual feedback
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, StopMiner would fail if the miner was already stopped
(crashed or killed externally), leaving it stuck in the workers list.
Now the miner is always removed from the manager, even if Stop()
returns "miner is not running". This allows cleaning up dead workers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Right-click on any worker in the dropdown to access:
- View Console: Navigate to console page for the worker
- View Stats: Navigate to dashboard for stats
- Hashrate History: Show hashrate history modal
- Edit Configuration: Navigate to profiles page
- Stop Worker: Stop the running worker
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed dropdown-menu positioning from left:0 to right:0 so the
dropdown expands leftward instead of rightward, keeping it visible
within the viewport.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The wails:// scheme is not supported by gin-contrib/cors v1.7.6
which requires origins to be http://, https://, or *.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove deprecated GetDB() function that exposed raw DB pointer
- Fix GetLatestHashrate to distinguish sql.ErrNoRows from real errors
- Document async saves in PeerRegistry mutation methods
- Fix deadlock in XMRig/TTMiner Start() by moving CheckInstallation
call before acquiring the main lock (Go RWMutex doesn't allow
recursive locking)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The xdg library caches paths, so setting XDG environment variables
in tests doesn't work when there's already an identity file at the
default path. Added NewNodeManagerWithPaths constructor similar to
NewPeerRegistryWithPath to allow tests to use isolated temp directories.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 30s context timeout for database transactions in hashrate.go
- Add helper function for parsing SQLite timestamps with error logging
- Implement atomic file writes (temp + rename) for profile_manager.go,
config_manager.go, and peer.go to prevent corruption on crash
- Add 5s timeout for stats collection per miner in manager.go
- Add 5s timeout for stdin writes in miner.go
- Clean up config file on failed miner start in xmrig_start.go
- Implement debounced saves (5s) for peer registry to reduce disk I/O
- Fix CheckInstallation data race in xmrig.go and ttminer.go by adding
proper mutex protection around shared field updates
- Add 10s handshake timeout for WebSocket connections in transport.go
- Update peer_test.go to call Close() before reload to flush changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Networking/Protocol fixes:
- Add HTTP server timeouts (Read/Write/Idle/ReadHeader) in service.go
- Fix CORS address parsing to use net.SplitHostPort safely
- Add request body size limit middleware (1MB max)
- Enforce MaxConns limit in WebSocket upgrade handler
- Fix WebSocket origin validation to only allow localhost
- Add read/write deadlines to WebSocket connections
Memory leak fixes:
- Add sync.Once to Manager.Stop() to prevent double-close panic
- Fix controller pending map leak by closing response channel
- Add memory reallocation for hashrate history slices when oversized
- Fix LogBuffer to truncate long lines and force reallocation on trim
- Add process wait timeout to prevent goroutine leaks on zombie processes
- Drain HTTP response body on copy error to allow connection reuse
Segfault/panic prevention:
- Add nil check in GetTotalHashrate for stats pointer
- Fix hashrate history slice reallocation to prevent capacity bloat
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add sync.RWMutex to config_manager.go for file operation synchronization
- Add deprecation warning to unsafe GetDB() function in database.go
- Fix UninstallMiner map modification during iteration in manager.go
- Add server readiness verification via TCP dial in service.go
- Add mutex-protected httpClient getter/setter in xmrig.go
- Update GetLatestVersion to use synchronized HTTP client in ttminer.go
- Update MockMiner in service_test.go to match context-aware GetStats interface
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical fixes:
- Release mutex before HTTP calls in GetStats() to prevent blocking
- Fix m.cmd race between Stop() and Wait() goroutine by capturing locally
- Add context support to GetStats() for proper request cancellation
High priority fixes:
- Add existence check in collectMinerStats() before operating on miners
- Add mutex-protected httpClient getter/setter for thread-safe test mocking
Changes:
- Miner interface now requires context.Context for GetStats()
- Stats HTTP requests timeout after 5 seconds (was 30s client default)
- All callers updated to pass context (service uses request context)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>