diff --git a/README.md b/README.md index f00a2fb0..326bed0e 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install. For full documentation, please visit the [project Wiki](https://github.com/MHSanaei/3x-ui/wiki). +## Settings Storage Migration + +The panel now uses a typed single-row settings model (`app_settings`) as the primary store. +Legacy key/value settings are still read as a compatibility fallback for one release window. + + ## A Special Thanks to - [alireza0](https://github.com/alireza0/) diff --git a/docs/cleanup_baseline_2026-02-20.md b/docs/cleanup_baseline_2026-02-20.md new file mode 100644 index 00000000..a77839b4 --- /dev/null +++ b/docs/cleanup_baseline_2026-02-20.md @@ -0,0 +1,66 @@ +# Cleanup Baseline (2026-02-20) + +This file captures the cleanup baseline and post-refactor validation checkpoints used for the DRY/KISS consolidation effort. + +## Baseline Snapshot (before implementation) +- `go build ./...`: PASS +- `go test ./...`: no test files in repository +- Go source files: 71 +- Go test files: 0 +- Total Go LOC: 19,882 +- `gocyclo` average complexity: 4.99 +- Highest hotspots: + - `web/service/tgbot.go` (~3,840 LOC) + - `web/service/inbound.go` (~2,510 LOC) + - `sub/subService.go` (~1,199 LOC) + +## Current Snapshot (after implementation) +- `go test ./...`: PASS +- `go vet ./...`: PASS +- `go build ./...`: PASS +- `staticcheck ./...`: PASS +- Go source files: 84 +- Go test files: 6 +- Total Go LOC: 20,434 +- `gocyclo` average complexity: 4.87 + +## Structural Changes Captured +- Added typed single-row settings model: `app_settings`. +- Added startup migration path from legacy key/value settings to typed settings. +- Kept legacy key/value reads as compatibility fallback and shadow writes for one release window. +- Added shared subscription URL builder used by both sub server and Telegram bot flows. +- Split large service files into focused units: + - `web/service/tgbot_subscription.go` + - `web/service/inbound_client_mutation.go` + - `web/service/settings_repository.go` +- Unified duplicated TLS listener wrapping between web/sub servers via `serverutil`. + +## Public Surface Guardrails +- CLI commands kept stable: + - `run` + - `migrate` + - `setting` + - `cert` +- Route families kept stable: + - `/panel/*` + - `/panel/api/*` + - subscription paths (`subPath`, `subJsonPath`) remain configurable via settings + +## Regression Guardrails Added +- Settings migration tests. +- SettingService typed storage + shadow-write behavior tests. +- Shared subscription URL generation tests. +- Inbound client mutation helper tests. +- Route/auth smoke tests. +- Command-level smoke checks with temp DB/log folders: + - `go run . setting ...` + - `go run . setting -show` + - `go run . migrate` +- Runtime HTTP smoke (temp DB, app process started/stopped): + - `GET /` -> `200` + - `GET /panel/` -> `307` + - `GET /panel/inbounds` -> `307` + - `GET /panel/settings` -> `307` + - `GET /panel/xray` -> `307` + - `GET /sub/non-existent-id` on panel port (`2099`) -> `404` (expected; route is on sub server) + - `GET /sub/non-existent-id` on sub port (`2096`) -> `400` diff --git a/docs/maintainer_architecture.md b/docs/maintainer_architecture.md new file mode 100644 index 00000000..d7cc231a --- /dev/null +++ b/docs/maintainer_architecture.md @@ -0,0 +1,31 @@ +# Maintainer Architecture Notes + +## Settings +- Authoritative settings storage is now `app_settings` (single typed row). +- Legacy `settings` key/value table remains as temporary compatibility fallback. +- `SettingService` is the single entry point for reads/writes. +- During compatibility window: + - reads prefer typed storage + - writes update typed storage and shadow-write legacy key/value rows + +## Subscription URL Generation +- Canonical URL generation lives in `web/service/subscription_urls.go`. +- Both flows must use this builder: + - sub server endpoint rendering (`sub/subService.go`) + - Telegram bot subscription links (`web/service/tgbot_subscription.go`) +- Avoid introducing URL construction logic directly in controllers/services. + +## Service File Layout +- Large services are split by concern while keeping package boundaries stable. +- `web/service/tgbot.go`: lifecycle, command handling core. +- `web/service/tgbot_subscription.go`: subscription link/QR behavior. +- `web/service/inbound.go`: core inbound CRUD/traffic/migration. +- `web/service/inbound_client_mutation.go`: repeated client mutation flows. + +## Web/Sub Listener Bootstrapping +- TLS listener wrapping is centralized in `serverutil/listener.go`. +- Both `web/web.go` and `sub/sub.go` must use it to avoid divergence. + +## Frontend Path Normalization +- Shared path utilities are in `web/assets/js/util/index.js` (`PathUtil`). +- Use `PathUtil.normalizePath` instead of inline ad-hoc normalization in templates. diff --git a/justfile b/justfile index a88f2d6a..198caf51 100644 --- a/justfile +++ b/justfile @@ -54,3 +54,19 @@ api-clients-list: api-login # Remove local temp artifacts clean-tmp: rm -rf tmp + + +# Run all unit tests +test: + GOPROXY=direct go test ./... + +# Run static checks +vet: + GOPROXY=direct go vet ./... + +staticcheck: + if command -v staticcheck >/dev/null 2>&1; then staticcheck ./...; else echo "staticcheck not installed"; fi + +# Print cyclomatic complexity snapshot +complexity: + if command -v gocyclo >/dev/null 2>&1; then gocyclo -avg $(rg --files -g '*.go'); else echo "gocyclo not installed"; fi