Commit Graph

114 Commits

Author SHA1 Message Date
sagit a43653f252 fix: permission checks for speedId and inPort + multi-node IP constraints (#261)
* feat: restrict user permissions and multi-node IP constraints

- 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

* fix: allow non-admin users to submit null speedId and zero inPort

- Backend: Check speedId is not nil before rejecting non-admin requests
- Backend: Only reject inPort if value > 0 for non-admin users
- Frontend: Only include speedId and inPort in payload for admin users
- Tests: Add contract tests for null speedId and zero inPort cases
2026-03-04 14:50:36 +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 2e3d5c9249 fix: preserve speed_limit and auto_clear when saving forwards and user tunnels
- Add speed_limit and auto_clear fields to forward update mutation
- Update user tunnel save to preserve these fields
- Add contract test for forward save preserving speed_limit
- Add plan documents for the fixes
2026-03-03 22:10:33 +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 1450b25475 fix: preserve bind IP when editing forward without explicit inIp change
- Add replaceForwardPortsPreservingInIP to maintain existing InIP values
- Track inIpTouched state in frontend to distinguish user changes
- Only send inIp in update request when user explicitly changed it
- Add unit tests for forward port replacement with preserved InIP
2026-03-03 20:22:58 +08:00
sagitchu be9d8773ce merge: resolve conflicts with main branch 2026-03-03 14:19:18 +08:00
sagitchu 1c10347357 fix: use configured connectIp for tunnel chain diagnosis
- Pass connectIp through resolveChainProbeTarget in diagnosis stream start items
- Pass connectIp in appendChainHopDiagnosis for full chain probes
- Reconstruct tunnel state with connectIp field preserved
- Fix forward service config when bindIP already contains port
- Add contract tests for connectIp diagnosis scenarios
- Add unit test for bindIP with port in buildForwardServiceConfigs
- Update AGENTS.md with plan document rules

Entire-Checkpoint: 35a2e61c2431
2026-03-03 14:17:36 +08:00
sagit 5bd21e2ac1 feat: custom IP selection and forward list enhancements (#247)
* 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

* fix: apply custom IP binding to forward and tunnel chain services

Entire-Checkpoint: ceff329d4cf4
2026-03-03 10:59:00 +08:00
sagitchu e38335973d fix: apply custom IP binding to forward and tunnel chain services
Entire-Checkpoint: ceff329d4cf4
2026-03-03 10:58:15 +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 d33814e18c fix(diagnosis): tighten timeout handling and clarify timeout messaging 2026-03-01 18:37:53 +08:00
sagit cf51b305b0 fix(diagnosis): prevent progress stream blocking and refine tunnel type chips (#230)
* fix(diagnosis): avoid result channel deadlock in progress stream

Close the diagnosis result channel asynchronously after workers complete so progress can stream without blocking, and improve tunnel card type chip contrast for clearer protocol distinction.

* feat(diagnosis): stream pending items and render in-progress states

Pre-populate diagnosis stream with pending targets so tunnel and forward dialogs can show per-item diagnosing status immediately. Update result typing and UI states to distinguish in-progress, success, and failure rows/cards consistently.
2026-03-01 14:49:38 +08:00
sagitchu a92eb168aa feat(diagnosis): add streaming progress support and tunnel-grouped forward list
- Add SSE streaming endpoints for tunnel/forward diagnosis with real-time progress
- Increase diagnosis timeout to 2 minutes with context propagation
- Group forwards by tunnel within user groups in UI
- Add nginx SSE proxy configuration for streaming endpoints
2026-02-28 20:09:25 +08:00
sagitchu de21a55f37 fix(diagnosis): parallelize runtime checks and raise API timeouts 2026-02-28 18:46:36 +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 a628f31859 fix(backend): improve captcha validation and forward service sync
- Add cloudflare site/secret key validation for captcha enabled check
- Fix forward create to use UpdateService with tolerateExists for idempotent sync
- Introduce isAlreadyExistsMessage helper excluding address-in-use errors
- Add contract tests for forward toggle, address-in-use rollback, captcha compatibility
2026-02-27 14:49:59 +08:00
sagit feb357ff17 fix: tunnel chain order and speed limit UI improvements (#216)
* fix(backend): use correct chain order index for tunnel nodes

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

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

* fix(frontend): filter '不限速' from speed limit dropdowns and preserve node order

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-26 21:30:25 +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 4bdfa50b0c docs: update AGENTS.md files with current project state (#213)
- Update root AGENTS.md to commit 21008cc / tag 2.1.5-rc15
- Add CI workflows info (ci-build.yml, docker-build.yml, deploy-docs.yml)
- Add Repository Layer and Contract Tests to WHERE TO LOOK
- Add websocket_reporter to CODE MAP
- Add Go version conventions (1.24/1.23/1.22)
- Add PostgreSQL migration support note
- Update go-backend AGENTS.md with PostgreSQL support and contract tests
- Update go-gost AGENTS.md with CI build conventions
- Update vite-frontend AGENTS.md with component counts
- Update go-gost/x AGENTS.md with file counts and registry reference
- Update handler AGENTS.md with LOC estimates
2026-02-26 09:52:11 +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 bc71c524e0 fix(backend): accept top-level federation service payloads 2026-02-25 00:06:31 +08:00
sagitchu 9f17d63cdc fix(backend): keep shared federation port-forward services stable 2026-02-24 23:06:09 +08:00
sagitchu a97484cd9b fix(backend): track traffic stats for federation port-forward tunnels
Federation mode panel peering with port-forward tunnel type (tunnelType=1)
was not updating peer_share.current_flow because regular forward traffic
uses different service name pattern than federation tunnel traffic.

Added parsePeerShareIDFromFederationTunnelName() to extract shareID from
tunnel names matching 'Share-{shareId}-Port-{port}' pattern, and
processPeerShareFlowFromForward() to update peer_share flow stats when
the forward belongs to a federation port-forward tunnel.
2026-02-24 20:25:04 +08:00
sagitchu bafcfbde3a fix(backend): allow WHMCS API login when captcha is enabled 2026-02-23 14:40:29 +08:00
sagit daf34d0f6c fix(backend): prevent login block when captcha enabled without cloudflare key (#194)
When captcha_enabled=true but cloudflare_secret_key is not configured,
the login flow would block users with "未配置Cloudflare Site Key" error.
Now captcha is treated as disabled if the secret key is missing, allowing
users to log in normally on fresh PostgreSQL installations.

Fixes login issue on new panel setups with PostgreSQL.
2026-02-22 22:54:51 +08:00
sagit 39e22c07de feat(backend): auto redeploy tunnel and forward config after node upgrade (#180) 2026-02-21 12:29:34 +00:00
Sagit 2081dc9658 feat(node): support stable and test release channels 2026-02-21 04:17:20 +00:00
sagit d216567c02 fix(frontend): switch grouped forward view to full list (#161)
* fix(frontend): left-align announcement logo in homepage banner

* fix(frontend): keep multiselect panels floating and preserve summaries

* fix(frontend): rebalance config card header spacing

* fix(frontend): normalize formatting and fix multiselect modal behavior

* fix(frontend): polish batch actions and sharing page guidance

* fix(frontend): switch grouped forward view to full list

* fix(backend): switch diagnosis internet target to bing

* style(frontend): beautify forward group view list display

* style: remove 'x' suffix from traffic ratio input and center config alert

* fix(ui): expand exit node select upwards in modal

* style: fix vertical alignment of logo and title in announcement banner
2026-02-20 10:31:39 +00:00
sagit 45bfd35a20 fix(backend): respect tunnel IP preference in forward diagnosis (#160)
Forward diagnosis chain-hop probes now inherit the tunnel ipPreference so v6-priority tunnels test IPv6 targets instead of defaulting to IPv4. Add a contract test to lock IPv6 target selection for entry->chain and chain->exit diagnostics.
2026-02-20 05:56:12 +00:00
Sagit d12c5bf2e1 feat(user): support user-group assignment in user management 2026-02-18 14:47:12 +00:00
sagit 17f8a06704 fix(tunnel): sync forwards to agents after tunnel update (#139)
Co-authored-by: Antigravity <antigravity@google.com>
2026-02-18 19:48:09 +08:00
Antigravity e209fc689a fix(tunnel): respect IPv6 preference in tunnel creation and diagnostics 2026-02-18 02:03:19 +00:00
Antigravity 3d1a8c8963 refactor(tests): centralize DB query assertions with helpers
Reduce repetitive raw SQL in test bodies by routing scalar and multi-column checks through shared helpers, keeping test intent clearer without changing behavior.
2026-02-17 06:02:46 +00:00
Antigravity 66be07750f refactor(backend): migrate to modular repository pattern with separated concerns
- 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
2026-02-17 04:47:11 +00:00
sagit 45d7970177 feat: 添加公告系统(支持SQLite和PostgreSQL) (#129)
* feat(announcement): add database schema for SQLite and PostgreSQL

Add announcement table with id, title, content, enabled, created_at, updated_at columns to both SQLite and PostgreSQL schemas to support announcement system.

* feat(announcement): implement SQLite repository for announcement management

Add announcement CRUD operations in SQLite repository including create, read, update, delete, and list methods with proper error handling.

* feat(announcement): add HTTP handlers and auth middleware for announcement API

Implement admin-only update endpoint and public read endpoint for announcements. Add auth middleware to enforce admin-only access for update operations.

* feat(announcement): add frontend API client for announcement endpoints

Implement API client methods for fetching announcements and updating announcement settings with proper error handling.

* feat(announcement): add announcement display component to dashboard

Implement announcement display section in dashboard with real-time updates and proper styling using HeroUI components.

* feat(announcement): add announcement management UI to config page

Implement announcement settings panel with enable/disable toggle and content editor for admin users to manage announcements.
2026-02-15 15:43:41 +00:00
sagit 1b4500202a feat: update agents.md and add a feat (#128)
* docs(agents): update knowledge base with encryption, API envelope, and build conventions

Add comprehensive documentation of project conventions including:
- Encryption patterns (AES with node secret PSK)
- API envelope structure (code, msg, data, ts)
- Build peculiarities (minify: false, rolldown-vite, UPX compression)
- Unique styles (flat monorepo, asymmetric Go layout, hybrid frontend mode)
- Module boundaries and anti-patterns
- Large file hotspots and code map references

Updated 7 AGENTS.md files across root and submodules.

* test(backend): add comprehensive dual-stack IP preference test suite

Added 43 tests covering:
- Core IP selection logic (selectTunnelDialHost)
- Node capability detection (nodeSupportsV4/V6)
- Address picker functions
- API contract tests for create/update/list
- Database compatibility (SQLite + PostgreSQL)

Fixed pre-existing broken test in federation_runtime_test.go
2026-02-15 15:17:15 +00:00
sagit 9a9e83dda0 docs(agents): update knowledge base with encryption, API envelope, and build conventions (#127)
Add comprehensive documentation of project conventions including:
- Encryption patterns (AES with node secret PSK)
- API envelope structure (code, msg, data, ts)
- Build peculiarities (minify: false, rolldown-vite, UPX compression)
- Unique styles (flat monorepo, asymmetric Go layout, hybrid frontend mode)
- Module boundaries and anti-patterns
- Large file hotspots and code map references

Updated 7 AGENTS.md files across root and submodules.
2026-02-15 14:33:00 +00:00
sagit e5e22baf43 fix(federation): cleanup tunnels when unsharing federation node (#126)
When unsharing a federation node, tunnels created via federationTunnelCreate
were not cleaned up, allowing clients to continue using them. Added
cleanupFederationTunnels() to delete these tunnels and reload the node agent.
2026-02-15 11:04:53 +00:00
sagit 961c06655a fix(backend): enforce port range restrictions in federation mode (#125)
Added dual-layer port range enforcement for federation sharing:

Server-side (Provider):
- federationRuntimeApplyRole: validate runtime.Port against share range
- validateFederationCommandPorts: hardened against malformed JSON bypass
- New helpers: validateRemoteNodePort, remoteNodePortRange

Client-side (Consumer):
- prepareTunnelCreateState: pre-check ports for remote nodes
- tunnelCreate type=1: validate targetPort for remote entry
- forwardCreate/Update/BatchChangeTunnel: port range validation

Prevents consumers from using arbitrary ports outside provider's allowed range.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-15 10:42:39 +00:00
sagit 8dc31383e0 fix(backend): correct federation port forwarding tunnel type handling (#123)
- Fix Type 1 (port forwarding) tunnels to call applyFederationRuntime
  Previously only Type 2 tunnels applied federation runtime, causing
  port forwarding tunnels to not be properly configured in federation mode

- Remove incorrect UDP tunnel type override in federationTunnelCreate
  UDP tunnels were being incorrectly set to Type 2, which conflicted with
  the federation runtime logic that expects Type 1 for port forwarding

These fixes ensure all tunnel types are properly handled in federation mode
with correct runtime configuration applied.
2026-02-15 12:12:54 +08:00
sagitchu 77dbd719ed fix(backend): enforce port range in federation runtime commands
The federationRuntimeCommand handler forwarded AddService/UpdateService
commands from consumers to provider nodes without validating that the
port in the service payload falls within the share's allowed port range.
This allowed consumers to use any port on shared nodes, bypassing the
provider's port_range_start/port_range_end restrictions.

Add port extraction and validation in federationRuntimeCommand for
service commands, rejecting requests with ports outside the allowed
range with a 403 error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 11:22:50 +08:00
sagit fd1168d855 fix(backend): set udp ttl default for tls tunnel protocol 2026-02-13 14:22:13 +00:00
sagit 92c9590c1a fix(backend): apply entry chains for remote federation nodes
Ensure remote entry nodes receive AddChains during tunnel runtime apply while tolerating offline/timeout cases. Add focused contract coverage for online and offline remote entry behavior.
2026-02-13 13:59:17 +00:00
sagit a69a0f040b Merge branch 'main' into opencode/kind-planet 2026-02-13 17:48:27 +08:00
sagit cf6294a77d fix(backend): normalize strategy data and proxy ip parsing 2026-02-13 09:42:38 +00:00