* docs: add implementation plan for max conn limit
* feat: add CLimiters support for websocket reporter
* feat: add max_conn field to user and forward models
* feat: implement max conn limiter dispatching
* feat: add maxConn to user and forward CRUD API
* feat: add max conn UI to user management and forward rules
* fix: load MaxConn in get forward record and add e2e contract test for max conn limit
- Pass tunnel protocol through diagnosis work items
- Support protocol-specific ping (TCP/UDP/KCP) via remote nodes
- Add KCP probe support in websocket_reporter for chain hop testing
- Add NodeMetric/TunnelMetric/ServiceMonitor models and repository methods
- Implement metrics ingestion service with per-minute bucket aggregation
- Add health checker for node connectivity monitoring
- Wire node metrics from WebSocket SystemInfo messages
- Add tunnel metrics ingestion from flow upload endpoint
- Create monitoring REST API endpoints for nodes, tunnels, services
- Implement service monitor CRUD and execution (TCP/ICMP checks)
- Add MonitorPermission for non-admin access control
- Create frontend monitor page with node/tunnel/service views
- Add tunnel metrics ingestion from agent flow reports
- Include schema migration for tunnel_metric unique index
- Fix tunnel entry port conflict validation to use transaction
Entire-Checkpoint: 030821a7c8e3
* fix(dialog): prevent both open and close auto focus to avoid page scroll
Add onOpenAutoFocus handler to prevent Radix Dialog from auto-focusing
content on open, which can cause unwanted scroll behavior.
* fix(dialog): remove onOpenAutoFocus, keep only onCloseAutoFocus
Remove onOpenAutoFocus handler that was causing scroll issues on first open.
Keep onCloseAutoFocus to prevent scroll to trigger element on close.
Key fix: Move {...props} before onCloseAutoFocus to prevent override.
* fix(dialog): prevent scroll to top on modal close
- Move {...props} before onCloseAutoFocus to prevent override
- Simplify handler to just e.preventDefault()
- Apply fix to both dialog.tsx and modal.tsx
- Replace tunnel_quota table with user_quota table
- Add user-level daily/monthly quota tracking and enforcement
- Update user CRUD to include quota configuration
- Migrate backup/restore to use user quota fields
- Update frontend API and UI for user quota management
Implement per-tunnel traffic quota feature:
- Add TunnelQuota model with daily/monthly usage tracking
- Integrate quota enforcement into flow accumulation path
- Pause forwards and disable tunnel when quota exceeded
- Block new forward creation/resume when tunnel quota disabled
- Auto-reset daily/monthly windows at 00:05 via maintenance job
- Add manual reset API endpoint for admins
- Include quota config in tunnel backup/restore
- Add frontend UI for quota settings and usage display
Entire-Checkpoint: e629b27ca437
- Add renewal_cycle field to nodes for tracking paid vs free cycles
- Implement auto-advance scheduling when renewal is processed
- Add migration test for renewal_cycle column
- Update dashboard to show renewal cycle count
- Add renewal status display on node detail page
- Return actual user_tunnel.status in admin permission list instead of hardcoded 1
- Allow non-admin users to update forwards when keeping the same speedId selection
- Add contract tests for user tunnel status mapping and forward permission edge case
Entire-Checkpoint: deb90fb942ee
- Add extra_ips field to nodes for multi-IP servers
- Add connect_ip field to chain_tunnel for specifying connection address
- Add in_ip field to forward_port for specifying listen address
- Frontend: add UI controls for extra IPs on node form
- Frontend: add connect IP input for tunnel chain nodes
- Frontend: add listen IP input for forward form
- Backend: resolve forward ingress with custom listen IP priority
Entire-Checkpoint: 557563462c16
- Add file upload support for logo and favicon with automatic PNG conversion
- Add backend validation for brand asset data URLs (app_logo, app_favicon)
- Change vite_config.value column type from varchar(200) to text for PostgreSQL
- Add schema migration v3 for vite_config.value column type conversion
- Update frontend to use file picker instead of manual URL input
- Add early favicon application in index.html to prevent flash
- Make SpeedLimit.TunnelID and TunnelName nullable (optional binding)
- Add SpeedID field to Forward model for forward-level rate limiting
- Update ForwardRecord to include SpeedID for control plane
- Update repository methods to handle optional tunnel binding
- Update handlers to accept optional tunnelId in create/update
- Modify control plane to prioritize Forward.SpeedID over UserTunnel speed limit
- Update frontend limit.tsx to support creating speed limits without tunnel binding
- Update TypeScript types for optional tunnelId and new speedId fields
This allows speed limits to be created as reusable rules that can be applied
to either tunnels (via UserTunnel.SpeedID) or individual forwards (via Forward.SpeedID).
- Extract database layer into model and repo packages
- Split repository into focused modules (control, federation, flow, groups, mutations)
- Remove monolithic db.go and sqlite/repository.go
- Update handlers to use new repository structure
- Migrate contract tests to new patterns
- Add migration plan documentation