- 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).
- 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
* 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>
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.
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.
* 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
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.
Reduce repetitive raw SQL in test bodies by routing scalar and multi-column checks through shared helpers, keeping test intent clearer without changing behavior.
- 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
* 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.
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.
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>
- 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.
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>
- Add transaction support for import operations with rollback on failure
- Add auto-backup before import to allow recovery on failure
- Convert user import to use INSERT ON CONFLICT pattern
- Add Execer interface to support both DB and Tx in import functions