Commit Graph

96 Commits

Author SHA1 Message Date
sagit c259645227 feat: implement user and forward max connection limit (#461)
* 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
2026-04-23 17:35:39 +08:00
sagitchu c431d79403 fix: correct tunnel protocol handling for KCP cleanup and diagnosis
- Fix KCP tunnel not reclaimed after deletion: service name was
  hardcoded to {id}_tls but services were created as {id}_kcp,
  causing DeleteService to never find the actual KCP service.
  Now reads tunnel.Protocol from DB and derives correct name.

- Fix KCP diagnosis using TCP ping instead of UDP ping:
  tunnel.Protocol was always hardcoded to 'tls' at creation,
  so isUDPBasedProtocol() never matched kcp tunnels. Now
  stores the actual protocol from entry node configuration.

- Fix addTunnelServiceOnNode to extract service name from
  serviceData instead of hardcoding _tls suffix.

- Fix rollbackTunnelRuntime to accept protocol parameter
  so retry cleanup uses correct service name.

- UpdateTunnelTx now persists protocol on tunnel updates.
2026-04-21 18:48:11 +08:00
sagitchu 5107f59d94 fix: tolerate offline nodes when controlling forward services and editing tunnels
- controlForwardServices: skip offline nodes instead of failing entire operation,
  so forward pause/resume/delete works when some entry nodes are offline
- onNodeOnline: always sync forward state on node reconnect (not just post-upgrade),
  so forwards that changed status while a node was offline get synced
- add ListForwardIDsByNode repo method to sync all forwards (including paused)
- tunnel edit UI: allow deselecting already-selected offline nodes in
  entry/chain/exit selectors, matching the backend's existing tolerance
2026-04-21 16:53:47 +08:00
sagitchu e995d70be7 feat(diagnosis): add protocol-aware connectivity diagnosis for tunnel chains
- 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
2026-04-21 14:00:02 +08:00
sagitchu 608fbf74de fix(backend): randomize new tunnel relay ports safely 2026-04-01 20:16:31 +08:00
sagit 5efe790937 fix: 实现用户端口数量限制验证 (#399)
- 在 ensureUserTunnelForwardAllowed 中添加 User.Num 限制验证
- 在 ensureUserTunnelForwardAllowed 中添加 UserTunnel.Num 限制验证
- 新增 CountActiveForwardsByUser 和 CountActiveForwardsByUserTunnel 函数
- 添加转发数量限制的契约测试

Closes #390
2026-03-31 02:52:49 +00:00
Misaka Master 352fc82907 fix(backend): include interfaceName in ListNodes API response (#395)
- Add missing interfaceName field to node list API response map
- Fixes bug where interface name value disappears after page refresh
- Field is correctly saved to DB but was not returned in API response

Co-authored-by: Alex-WU-Gen-9-png <github@enomria0785.eu.org>
2026-03-29 20:59:52 +08:00
sagit 87722e461c feat(monitor): hop-by-hop latency metrics for forwarding chain (#394) 2026-03-29 18:59:06 +08:00
sagitchu 61d95ab5d5 fix(backend): clean up forwards when revoking tunnel permissions 2026-03-25 20:24:27 +08:00
sagit c27be19915 fix: bracket IPv6 forward entry addresses (#383)
Return standard [host]:port values from forward list responses so IPv6 rule entries can be copied directly from the UI.
2026-03-24 22:16:55 +08:00
sagitchu 2a1caf32c4 fix(monitor): resolve PostgreSQL type encoding issues for node metrics 2026-03-24 10:45:17 +08:00
sagitchu efaffb0475 chore: release 2.1.9-rc8 2026-03-24 09:45:21 +08:00
sagitchu 3826cb02c0 chore: update monitor rendering and release rc2 2026-03-22 17:55:10 +08:00
sagit 8ebde9dca9 feat: node OS logo and UI fixes (#367)
* chore: update AGENTS.md with next release info

* feat: node OS logo, UI rate fix, and monitor trend updates
2026-03-22 05:03:04 +00:00
sagitchu c914040b7d fix(repo): qualify tunnel_metric columns to avoid ambiguity in ON CONFLICT 2026-03-21 19:40:16 +08:00
sagitchu bd4e1f66cb feat: implement theme selection and system integration 2026-03-20 22:47:49 +08:00
sagitchu f6a753baa3 fix: include missing field in repository 2026-03-20 22:18:45 +08:00
sagitchu 27c13d6c47 chore: release 2.1.9-beta7 2026-03-20 22:15:51 +08:00
sagitchu 1780be73b9 fix(monitor): hide remote nodes from monitor view 2026-03-20 18:41:31 +08:00
sagitchu 3c57a5ac84 feat: periodic tunnel quality probing and monitoring 2026-03-20 12:34:09 +08:00
sagitchu 5972378897 fix: resolve merge conflicts and fix monitoring bugs
- Add missing 'uptime' field to NodeMetricApiItem type definition
- Fix WS message handling: non-UpgradeProgress typed messages now
  broadcast via broadcastInfo instead of being silently dropped
- Strengthen looksLikeSystemInfoMessage heuristic to require ≥3
  matching keys to avoid false positives
- Fix tab/space indentation inconsistency in admin.tsx useEffect
- Remove duplicate method declarations from merge (repository_control,
  mutations)
- Update tunnel_entry_sqlite_test to use renamed Tx suffix function
2026-03-18 14:12:47 +08:00
sagitchu 455900ba41 Merge branch 'main' into opencode/shiny-falcon
# Conflicts:
#	go-backend/internal/http/handler/mutations.go
#	go-backend/tests/contract/issue313_entry_port_conflict_contract_test.go
2026-03-18 14:09:00 +08:00
sagit 2df061a19f fix(backend): resolve SQLite deadlock in tunnel entry updates (#334)
- Fix deadlock when updating tunnel entries with offline nodes
- Add test file for tunnel entry SQLite operations
- Update contract tests for entry port conflict and limiter sync
- Add plan documents for SQLite deadlock fix and contract semantics
2026-03-18 09:00:20 +08:00
sagitchu 46a60376c4 Merge remote-tracking branch 'origin/main' into opencode/shiny-falcon
# Conflicts:
#	vite-frontend/src/pages/node.tsx
#	vite-frontend/src/pages/user.tsx
2026-03-17 15:18:25 +08:00
sagitchu 9de240f034 feat(monitoring): add node/tunnel metrics, service monitors, and health checks
- 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
2026-03-17 14:59:09 +08:00
sagitchu 5ff9621227 feat: use DatePicker for expiry time and add ExpiryReminderDismissed migration
Entire-Checkpoint: af1825430330
2026-03-14 12:36:26 +08:00
sagitchu 06bb8b3b04 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
2026-03-14 10:29:22 +08:00
sagitchu ad9b336fb9 refactor(quota): migrate traffic quota from tunnel to user level
- 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
2026-03-12 14:17:57 +08:00
sagit 5e96a8de72 feat(quota): add tunnel traffic quota with daily/monthly limits (#291) (#308)
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
2026-03-11 16:09:03 +08:00
sagit 5cb935e0e5 fix(frontend): refine node renewal UI and filters (#299)
* style: restore Prettier formatting in renewal.ts

* fix(frontend): refine node renewal UI and filters

Entire-Checkpoint: 88c8ae47fb7d

* refactor(nodes): remove unused tags field from node model

* refactor(node): improve card layout and reorder elements

Entire-Checkpoint: fb89f3ebef5c
2026-03-09 08:37:57 +00:00
sagit 413081f72a feat(nodes): add renewal cycle and auto-advance scheduling (#296)
- 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
2026-03-08 22:05:25 +08:00
sagitchu d60655045a feat(forward): display tunnel traffic ratio on forward page 2026-03-08 20:00:26 +08:00
sagitchu 31ef861504 feat(nodes): add node metadata and expiry reminders (#246)
Entire-Checkpoint: d8b429492cbe
2026-03-08 19:44:46 +08:00
sagitchu e0dd70a054 fix(backend): migrate PostgreSQL traffic columns from int4 to bigint
Widens legacy PostgreSQL traffic/quota columns to BIGINT to prevent
int4 overflow when storing large values like 536870912000 (500GB).

Affected tables:
- user (flow, in_flow, out_flow)
- forward (in_flow, out_flow)
- statistics_flow (flow, total_flow)
- tunnel (flow)
- user_tunnel (flow, in_flow, out_flow)
- peer_share (max_bandwidth, current_flow)

Schema version bumped from 4 to 5 with auto-migration on startup.
2026-03-08 11:48:36 +08:00
sagitchu 3e11549370 fix(backend): sync user tunnel status and relax forward speedId permission check
- 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
2026-03-08 00:56:13 +08:00
sagitchu 15e6cd69eb feat: allow user custom inport with range validation
Entire-Checkpoint: fcd76aac10e9
2026-03-05 17:03:19 +08:00
sagit 348900de01 feat: restrict user permissions and multi-node IP constraints (#260)
- Non-admin users cannot set speedId or inPort on forward create/update
- Multi-entrance tunnels disable custom listen IP for forwards
- Multi-exit tunnels disable custom connect IP
- Multi-node hop chains disable custom connect IP per hop
- Remove tunnel-first-IP fallback in forward ingress resolution
- Add contract tests for non-admin permission restrictions

Entire-Checkpoint: 133693290660
2026-03-04 14:04:22 +08:00
sagitchu 1c596fae4b feat: auto-fallback to default bind IP when invalid bind address detected
When a forward service is updated with a bind IP that doesn't exist on the
host network interfaces, the system now automatically falls back to the
default bind address (listening on all interfaces) instead of failing.

- Added syncForwardServicesWithWarnings to collect fallback warnings
- Implemented fallbackForwardPortToDefaultBind for graceful degradation
- Added UpdateForwardPortBindIP repository method to persist fallback
- Enhanced error detection for 'cannot assign requested address' errors
- Frontend displays warning toasts when fallback occurs
- Added comprehensive unit tests for new error detection functions
2026-03-03 21:34:12 +08:00
sagitchu 7efb49bdab fix: handle forward service rebind on self-occupied port
When UpdateService encounters bind address conflicts (port already in use),
the handler now automatically deletes existing forward services and retries
the AddService operation. This resolves issues where a forward's own stale
listener prevents the update.

- Add isBindAddressInUseError() to detect port bind conflicts
- Add rebindForwardServiceOnSelfOccupiedPort() for automatic cleanup and retry
- Add HasOtherForwardOnNodePort() repository method to verify port ownership
- Add unit tests for bind conflict detection
2026-03-03 20:53:55 +08:00
sagitchu 9cf9f4f1f7 feat: add comprehensive migration test for legacy columns
- Add ExtraIPs, TCPListenAddr, UDPListenAddr to Node migration
- Add ip_preference to Tunnel migration
- Add test for very legacy database migration (1.x schema)
- Include issue #211 tracking document

Entire-Checkpoint: 0d086883c34a
2026-03-03 10:27:29 +08:00
sagitchu 05bd6a686d feat: add IP selection dropdown for tunnels and forwards
Entire-Checkpoint: fde43d8c94e5
2026-03-03 09:16:05 +08:00
sagitchu b8193417f5 feat: add custom IP selection for nodes, tunnels, and forwards
- 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
2026-03-03 08:24:15 +08:00
sagitchu 6e8406f439 feat: remove speed limit tunnel binding and add migration cleanup
- Remove tunnel binding UI from speed limit page (no more Select component)
- Remove /api/v1/speed-limit/tunnels route alias
- Simplify CreateSpeedLimit/UpdateSpeedLimit to not accept tunnel parameters
- Add schema migration v4 to clear historical tunnel_id/tunnel_name bindings
- Update contract tests to verify tunnel binding is ignored
- Add limiter sync failure tests for forward-level rate limiting
2026-02-27 19:30:02 +08:00
sagitchu e5ce0501a2 feat: add brand asset upload with PNG conversion and improve config validation
- 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
2026-02-27 15:54:04 +08:00
sagitchu 61c5b5e759 feat: add speed limit contract tests and refine limit/user UI 2026-02-26 20:18:29 +08:00
sagitchu c8eb780c67 feat: decouple speed limits from tunnels and add forward-level rate limiting
- 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).
2026-02-26 13:08:35 +08:00
sagit 6189fe23f1 feat: include forward ports in federation remote usage and display share flow (#209)
* feat(backend): include forward ports in federation remote usage list

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(frontend): display federation share flow in forward list

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-25 16:59:39 +08:00
sagit 7ba90e8696 fix(backend): resolve federation forward traffic stats and listener disappearance (#208)
* fix(backend): add repository methods for federation forward runtime management

- GetActiveForwardPeerShareRuntimeByServiceName: lookup runtime by share_id and service_name
- MarkForwardPeerShareRuntimeReleasedByServiceName: release runtime by service_name
- ListActiveForwardPeerShareRuntimesByNodeAndServiceName: node-scoped query for flow processing

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(backend): bind and release federation forward runtimes on service commands

- bindPeerShareForwardRuntimeServices: create runtime if missing, update ServiceName/Port/Applied/Status
- releasePeerShareForwardRuntimeServices: handle deleteservice command to mark runtime released
- parseFederationForwardServiceNamesForRelease: extract service names from delete payload
- Tests: bind creates runtime when missing, release marks runtime as released

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(backend): scope federation flow lookup by node to avoid cross-share collisions

- flowUpload: use GetNodeBySecret to extract nodeID for flow processing
- processFlowItem: accept nodeID parameter and pass to flow handlers
- processPeerShareFlowByServiceName: try node-scoped query first, fallback to global
- Add warning log when multiple runtimes match (ambiguous)
- Tests: update all processFlowItem calls with nodeID parameter

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(contract): adjust federation dual panel contract expectations

Update assertion for entry share runtime binding behavior after fix

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-25 14:10:24 +08:00
sagitchu 466cc65069 fix: stabilize federation forward runtime cleanup and wire frontend version update UX 2026-02-25 11:20:51 +08:00
sagitchu 9f17d63cdc fix(backend): keep shared federation port-forward services stable 2026-02-24 23:06:09 +08:00