浏览代码

chore: refresh dependencies and modernize Go test idioms

Frontend deps: @hookform/resolvers 5.4.3 -> 5.5.7, Storybook 10.5.4 -> 10.5.5
across the four packages we declare, globals 17.7.0 -> 17.8.0, and jsdom
29.1.1 -> 30.0.1. The jsdom major replaces its CSS and selector stack --
@asamuzakjp/css-color 5 -> 6, @asamuzakjp/dom-selector 7 -> 8, undici 7 -> 8,
nwsapi and generational-cache folded into their parents, whatwg-url 17 nested
underneath. Nothing in the Vitest suites reaches those directly and the whole
frontend gate (typecheck, lint, tests, build, Storybook compile) is green.
Panel frontend version to 0.6.0.

Backend deps: mattn/go-sqlite3 1.14.48 -> 1.14.49 and valyala/fasthttp
1.72.0 -> 1.73.0, plus the golang.org/x/exp and genproto/googleapis/rpc
indirect bumps that came with them.

Go tests: modernize -fix output, covering range-over-int, sync.WaitGroup.Go
in place of manual Add/Done pairs, maps.Copy, and Go 1.26 new(expr) for
pointer-to-value in the forwarded-trust table. The storedAs helper is deleted
instead of being left behind a //go:fix inline directive -- keeping it that way
fails govet on the one call site the rewrite did not reach, and every caller now
takes new(...) directly. Behaviour is unchanged.

DnsTab: the hosts-sync effect tested dns while declaring dnsEnabled in its
dependency array. Both carry the same truth value, so this is exhaustive-deps
hygiene rather than a behaviour change.
Sanaei 12 小时之前
父节点
当前提交
c56f6447a8

+ 123 - 106
frontend/package-lock.json

@@ -1,17 +1,17 @@
 {
   "name": "3x-ui-frontend",
-  "version": "0.4.3",
+  "version": "0.6.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "3x-ui-frontend",
-      "version": "0.4.3",
+      "version": "0.6.0",
       "dependencies": {
         "@ant-design/icons": "^6.3.2",
         "@codemirror/lang-json": "^6.0.2",
         "@codemirror/theme-one-dark": "^6.1.3",
-        "@hookform/resolvers": "^5.4.3",
+        "@hookform/resolvers": "^5.5.7",
         "@noble/hashes": "^2.2.0",
         "@tanstack/react-query": "^5.101.4",
         "@tanstack/react-query-devtools": "^5.101.4",
@@ -32,10 +32,10 @@
       },
       "devDependencies": {
         "@eslint/js": "^10.0.1",
-        "@storybook/addon-a11y": "^10.5.4",
-        "@storybook/addon-docs": "^10.5.4",
-        "@storybook/addon-vitest": "^10.5.4",
-        "@storybook/react-vite": "^10.5.4",
+        "@storybook/addon-a11y": "^10.5.5",
+        "@storybook/addon-docs": "^10.5.5",
+        "@storybook/addon-vitest": "^10.5.5",
+        "@storybook/react-vite": "^10.5.5",
         "@testing-library/dom": "^10.4.1",
         "@testing-library/react": "^16.3.2",
         "@types/react": "^19.2.17",
@@ -47,13 +47,13 @@
         "eslint": "^10.8.0",
         "eslint-plugin-jsx-a11y": "^6.10.2",
         "eslint-plugin-react-hooks": "^7.1.1",
-        "globals": "^17.7.0",
+        "globals": "^17.8.0",
         "husky": "^9.1.7",
-        "jsdom": "^29.1.1",
+        "jsdom": "^30.0.1",
         "lint-staged": "^17.2.0",
         "msw": "^2.15.0",
         "playwright": "^1.62.0",
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "typescript": "6.0.3",
         "typescript-eslint": "^8.65.0",
         "vite": "8.1.5",
@@ -165,56 +165,58 @@
       }
     },
     "node_modules/@asamuzakjp/css-color": {
-      "version": "5.1.11",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
-      "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.5.tgz",
+      "integrity": "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@asamuzakjp/generational-cache": "^1.0.1",
-        "@csstools/css-calc": "^3.2.0",
-        "@csstools/css-color-parser": "^4.1.0",
+        "@csstools/css-calc": "^3.2.1",
+        "@csstools/css-color-parser": "^4.1.9",
         "@csstools/css-parser-algorithms": "^4.0.0",
-        "@csstools/css-tokenizer": "^4.0.0"
+        "@csstools/css-tokenizer": "^4.0.0",
+        "lru-cache": "^11.5.2"
       },
       "engines": {
-        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+        "node": "^22.13.0 || >=24.0.0"
+      }
+    },
+    "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
+      "version": "11.5.2",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
+      "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
+      "dev": true,
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": "20 || >=22"
       }
     },
     "node_modules/@asamuzakjp/dom-selector": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
-      "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.0.tgz",
+      "integrity": "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@asamuzakjp/generational-cache": "^1.0.1",
-        "@asamuzakjp/nwsapi": "^2.3.9",
         "bidi-js": "^1.0.3",
         "css-tree": "^3.2.1",
-        "is-potential-custom-element-name": "^1.0.1"
+        "is-potential-custom-element-name": "^1.0.1",
+        "lru-cache": "^11.5.2"
       },
       "engines": {
-        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+        "node": "^22.13.0 || >=24.0.0"
       }
     },
-    "node_modules/@asamuzakjp/generational-cache": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
-      "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
+    "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
+      "version": "11.5.2",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
+      "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
       "dev": true,
-      "license": "MIT",
+      "license": "BlueOak-1.0.0",
       "engines": {
-        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+        "node": "20 || >=22"
       }
     },
-    "node_modules/@asamuzakjp/nwsapi": {
-      "version": "2.3.9",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
-      "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/@babel/code-frame": {
       "version": "7.29.7",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
@@ -1384,9 +1386,9 @@
       }
     },
     "node_modules/@hookform/resolvers": {
-      "version": "5.4.3",
-      "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.4.3.tgz",
-      "integrity": "sha512-jtS1DEvkT1ql8ImIDQL+UmkhEnDmt3Bp7Yt4q5XQpc0JiQ8b8+I7yT/KQze4gw9Ocmi9xa9ef6zxifizPgdp3A==",
+      "version": "5.5.7",
+      "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.5.7.tgz",
+      "integrity": "sha512-CyPCYV8/KlXfEXLWj8HHHhVsR/IZ6Ckm3b/a4fWtO/lRnRK1huqncb8LlAWrmpPRsse5glF5aVuDRMHEr3UGag==",
       "license": "MIT",
       "dependencies": {
         "@standard-schema/utils": "^0.3.0"
@@ -1413,7 +1415,7 @@
         "react-hook-form": "^7.55.0",
         "superstruct": ">=0.12.0",
         "typanion": "^3.3.2",
-        "valibot": "^1.0.0 || ^1.0.0-beta.4 || ^1.0.0-rc",
+        "valibot": ">=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc",
         "vest": ">=3.0.0",
         "yup": "^1.0.0",
         "zod": "^3.25.0 || ^4.0.0"
@@ -3631,9 +3633,9 @@
       "license": "MIT"
     },
     "node_modules/@storybook/addon-a11y": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-10.5.4.tgz",
-      "integrity": "sha512-UWdZtB7Dh1GjqxTPOrisUNDhDGF5pKGzZdzW9DSSHMBcAOx2dsTmXGzLSFprAz4LTT0OHCtKhxNqKK0JZJ0Y8g==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-10.5.5.tgz",
+      "integrity": "sha512-nsMnSRe7pzepXIkUUqI/rL7sp8juXOluyypU4Dz0UuYHhw/cKaxfzuO+3WJN5EtEr/gcnKYb4awxH/duPGavUw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3645,20 +3647,20 @@
         "url": "https://opencollective.com/storybook"
       },
       "peerDependencies": {
-        "storybook": "^10.5.4"
+        "storybook": "^10.5.5"
       }
     },
     "node_modules/@storybook/addon-docs": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.5.4.tgz",
-      "integrity": "sha512-2Z/x2pKEmXOCQjmttYzPuQBu9aWeMly8uEs3msrCTBLiHs/F7IlBFnMu0Z+T2Qvk0LEy8O93AlcPSP76aCcKjw==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.5.5.tgz",
+      "integrity": "sha512-0YpKlimS4XE0kQ8Maa5coeefQxdyDrBHg1wOP3WTPuBe4FolFSCDveR0ge2+vuUBk+fZfn2+l+3Q2jmAWaRGDg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@mdx-js/react": "^3.0.0",
-        "@storybook/csf-plugin": "10.5.4",
+        "@storybook/csf-plugin": "10.5.5",
         "@storybook/icons": "^2.0.2",
-        "@storybook/react-dom-shim": "10.5.4",
+        "@storybook/react-dom-shim": "10.5.5",
         "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "ts-dedent": "^2.0.0"
@@ -3669,7 +3671,7 @@
       },
       "peerDependencies": {
         "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
-        "storybook": "^10.5.4"
+        "storybook": "^10.5.5"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -3678,9 +3680,9 @@
       }
     },
     "node_modules/@storybook/addon-vitest": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-10.5.4.tgz",
-      "integrity": "sha512-5lr81sgrbK3Tjjbstieg/yYj3jdtQYP70ihpOiN1TwogvFATY2/9eMT46FE5ioKtEFcfJRDcgJ2wSlmJKE+kZw==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-10.5.5.tgz",
+      "integrity": "sha512-Ymq9ErkSkYiIDuqpJ2+hE5GCQ5J6TCLOWhutqArvwaeAO+HAibM82XNExpJ1/kvPqk9y961GDPkv2W15I88JIw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3695,7 +3697,7 @@
         "@vitest/browser": "^3.0.0 || ^4.0.0",
         "@vitest/browser-playwright": "^4.0.0",
         "@vitest/runner": "^3.0.0 || ^4.0.0",
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "vitest": "^3.0.0 || ^4.0.0"
       },
       "peerDependenciesMeta": {
@@ -3714,13 +3716,13 @@
       }
     },
     "node_modules/@storybook/builder-vite": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.5.4.tgz",
-      "integrity": "sha512-eXdgow+brSzZrG3CnG18YwxZwEYNAZIh2G5qKwNoZf0uk2ZCPgLRQwtVAcd7BiiEDGnXUHm9pycAS+UiF4F4Mg==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.5.5.tgz",
+      "integrity": "sha512-dQoJ7gUl8y0z5rV9cE0mz6qTBNmN9R4GOLIZk98rJ8CwduNJOb9eGZXusDzzvnYcp8TnNkqDtyx4tXQSUDInPQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@storybook/csf-plugin": "10.5.4",
+        "@storybook/csf-plugin": "10.5.5",
         "ts-dedent": "^2.0.0"
       },
       "funding": {
@@ -3728,14 +3730,14 @@
         "url": "https://opencollective.com/storybook"
       },
       "peerDependencies": {
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
       }
     },
     "node_modules/@storybook/csf-plugin": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-10.5.4.tgz",
-      "integrity": "sha512-DSp5Z/eZlRnKq0KrKLJE6uoYf/Ysc+FP0Z5DVTGnOrie+z3tC0lNi9I4RB++EXkJeUDS9/4dxvJZVSWjhLlXxw==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-10.5.5.tgz",
+      "integrity": "sha512-/euibhRFqklYCZqUseokojmfYcQpXshVY2QmA1qCuxMz9SzVFD3iSTw+aFLTxpsJGGdcZJk8fnm/rEthLzZ9jA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3748,7 +3750,7 @@
       "peerDependencies": {
         "esbuild": "*",
         "rollup": "*",
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "vite": "*",
         "webpack": "*"
       },
@@ -3785,14 +3787,14 @@
       }
     },
     "node_modules/@storybook/react": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/react/-/react-10.5.4.tgz",
-      "integrity": "sha512-tOxfVgbYcaVsArN8XTDkJfdsnsnHh1LxjRHVpJ/N+VEkz4FveK/XH3jOLV0YqgrG8yXza7+CteDP4FfPVQY/mw==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/react/-/react-10.5.5.tgz",
+      "integrity": "sha512-T2Xj0ey7a9RHU6coYLC0L5lhjcdyhLCs9wNv15FvHvgmrRobkynEV72kq5vGW8tFkahNWI1X9+GZPQ6r8Nm38w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@storybook/global": "^5.0.0",
-        "@storybook/react-dom-shim": "10.5.4",
+        "@storybook/react-dom-shim": "10.5.5",
         "react-docgen": "^8.0.2",
         "react-docgen-typescript": "^2.2.2"
       },
@@ -3805,7 +3807,7 @@
         "@types/react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "typescript": ">= 4.9.x"
       },
       "peerDependenciesMeta": {
@@ -3821,9 +3823,9 @@
       }
     },
     "node_modules/@storybook/react-dom-shim": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-10.5.4.tgz",
-      "integrity": "sha512-YdlppEOReg8MvTECRNuf79gu2zL83JqKDHIR/65eS0M6y+ue9pkpfjYo7hZVIcyOcRd9npBDXMdt2kC92bCuaA==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-10.5.5.tgz",
+      "integrity": "sha512-PIk7N3LLrZIxfNxmkvmQN1d5UQ70XEedT8n0GhBiXnM6XL09xPGB8n8TZXeJBRYluKhDQcAyQeT0/OZmcDVQJg==",
       "dev": true,
       "license": "MIT",
       "funding": {
@@ -3835,7 +3837,7 @@
         "@types/react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
-        "storybook": "^10.5.4"
+        "storybook": "^10.5.5"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -3847,16 +3849,16 @@
       }
     },
     "node_modules/@storybook/react-vite": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/@storybook/react-vite/-/react-vite-10.5.4.tgz",
-      "integrity": "sha512-iw7EAA98n30vpf+ZSy2Ll4Ne7oyZ/lS6W22u5Sp5UOI2oAkYuklxIWjRIKGqpY0BHP+GqaGYtUGMZQnBqgul2g==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/@storybook/react-vite/-/react-vite-10.5.5.tgz",
+      "integrity": "sha512-Uy7VV72kVSkw6aDTAPQupXUeZX5LF6e4zqNvTZ+36qxsXAkaFgw7HPEm7L1tsaRfiV+s9anU7UvX47tfJpYGuQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@joshwooding/vite-plugin-react-docgen-typescript": "^0.7.0",
         "@rollup/pluginutils": "^5.0.2",
-        "@storybook/builder-vite": "10.5.4",
-        "@storybook/react": "10.5.4",
+        "@storybook/builder-vite": "10.5.5",
+        "@storybook/react": "10.5.5",
         "empathic": "^2.0.0",
         "magic-string": "^0.30.0",
         "react-docgen": "^8.0.2",
@@ -3870,7 +3872,7 @@
       "peerDependencies": {
         "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
         "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
-        "storybook": "^10.5.4",
+        "storybook": "^10.5.5",
         "typescript": ">= 4.9.x",
         "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
       },
@@ -7165,7 +7167,7 @@
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT"
     },
     "node_modules/fast-json-patch": {
@@ -7531,9 +7533,9 @@
       }
     },
     "node_modules/globals": {
-      "version": "17.7.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-17.7.0.tgz",
-      "integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==",
+      "version": "17.8.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-17.8.0.tgz",
+      "integrity": "sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -8525,39 +8527,39 @@
       }
     },
     "node_modules/jsdom": {
-      "version": "29.1.1",
-      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
-      "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==",
+      "version": "30.0.1",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.1.tgz",
+      "integrity": "sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@asamuzakjp/css-color": "^5.1.11",
-        "@asamuzakjp/dom-selector": "^7.1.1",
+        "@asamuzakjp/css-color": "^6.0.5",
+        "@asamuzakjp/dom-selector": "^8.3.0",
         "@bramus/specificity": "^2.4.2",
-        "@csstools/css-syntax-patches-for-csstree": "^1.1.3",
-        "@exodus/bytes": "^1.15.0",
+        "@csstools/css-syntax-patches-for-csstree": "^1.1.7",
+        "@exodus/bytes": "^1.15.1",
         "css-tree": "^3.2.1",
         "data-urls": "^7.0.0",
         "decimal.js": "^10.6.0",
         "html-encoding-sniffer": "^6.0.0",
         "is-potential-custom-element-name": "^1.0.1",
-        "lru-cache": "^11.3.5",
+        "lru-cache": "^11.5.2",
         "parse5": "^8.0.1",
         "saxes": "^6.0.0",
         "symbol-tree": "^3.2.4",
-        "tough-cookie": "^6.0.1",
-        "undici": "^7.25.0",
+        "tough-cookie": "^6.0.2",
+        "undici": "^8.9.0",
         "w3c-xmlserializer": "^5.0.0",
         "webidl-conversions": "^8.0.1",
         "whatwg-mimetype": "^5.0.0",
-        "whatwg-url": "^16.0.1",
+        "whatwg-url": "^17.1.0",
         "xml-name-validator": "^5.0.0"
       },
       "engines": {
-        "node": "^20.19.0 || ^22.13.0 || >=24.0.0"
+        "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
       },
       "peerDependencies": {
-        "canvas": "^3.0.0"
+        "canvas": "^3.2.3"
       },
       "peerDependenciesMeta": {
         "canvas": {
@@ -8575,6 +8577,21 @@
         "node": "20 || >=22"
       }
     },
+    "node_modules/jsdom/node_modules/whatwg-url": {
+      "version": "17.1.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.0.tgz",
+      "integrity": "sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@exodus/bytes": "^1.15.1",
+        "tr46": "^6.0.0",
+        "webidl-conversions": "^8.0.1"
+      },
+      "engines": {
+        "node": "^22.14.0 || >=24.0.0"
+      }
+    },
     "node_modules/jsesc": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -10420,7 +10437,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
       "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-      "devOptional": true,
+      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
@@ -10967,9 +10984,9 @@
       }
     },
     "node_modules/storybook": {
-      "version": "10.5.4",
-      "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.5.4.tgz",
-      "integrity": "sha512-bmLxPsxVSPnbeiZqYQpozyNOiJXfk+pf7WfHZflvPkwT6Y+rvYz3Cj/D6H4Kf2jHpuDNiMXBKO3yawLN2OWirg==",
+      "version": "10.5.5",
+      "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.5.5.tgz",
+      "integrity": "sha512-UscBIBJDloUeqntukHOhP1a5W/vouePDJbzPSxj466WK801FZtzQiMffMtkjzJiWSuj20wfaYlB2QQKh9aOYAg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -10989,7 +11006,7 @@
         "recast": "^0.23.5",
         "semver": "^7.7.3",
         "use-sync-external-store": "^1.5.0",
-        "ws": "^8.18.0"
+        "ws": "^8.21.1"
       },
       "bin": {
         "storybook": "dist/bin/dispatcher.js"
@@ -11760,13 +11777,13 @@
       }
     },
     "node_modules/undici": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
-      "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz",
+      "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==",
       "dev": true,
       "license": "MIT",
       "engines": {
-        "node": ">=20.18.1"
+        "node": ">=22.19.0"
       }
     },
     "node_modules/undici-types": {

+ 9 - 9
frontend/package.json

@@ -1,7 +1,7 @@
 {
   "name": "3x-ui-frontend",
   "private": true,
-  "version": "0.4.3",
+  "version": "0.6.0",
   "type": "module",
   "description": "3x-ui panel frontend (React 19 + Ant Design 6 + Vite 8).",
   "engines": {
@@ -30,7 +30,7 @@
     "@ant-design/icons": "^6.3.2",
     "@codemirror/lang-json": "^6.0.2",
     "@codemirror/theme-one-dark": "^6.1.3",
-    "@hookform/resolvers": "^5.4.3",
+    "@hookform/resolvers": "^5.5.7",
     "@noble/hashes": "^2.2.0",
     "@tanstack/react-query": "^5.101.4",
     "@tanstack/react-query-devtools": "^5.101.4",
@@ -51,10 +51,10 @@
   },
   "devDependencies": {
     "@eslint/js": "^10.0.1",
-    "@storybook/addon-a11y": "^10.5.4",
-    "@storybook/addon-docs": "^10.5.4",
-    "@storybook/addon-vitest": "^10.5.4",
-    "@storybook/react-vite": "^10.5.4",
+    "@storybook/addon-a11y": "^10.5.5",
+    "@storybook/addon-docs": "^10.5.5",
+    "@storybook/addon-vitest": "^10.5.5",
+    "@storybook/react-vite": "^10.5.5",
     "@testing-library/dom": "^10.4.1",
     "@testing-library/react": "^16.3.2",
     "@types/react": "^19.2.17",
@@ -66,13 +66,13 @@
     "eslint": "^10.8.0",
     "eslint-plugin-jsx-a11y": "^6.10.2",
     "eslint-plugin-react-hooks": "^7.1.1",
-    "globals": "^17.7.0",
+    "globals": "^17.8.0",
     "husky": "^9.1.7",
-    "jsdom": "^29.1.1",
+    "jsdom": "^30.0.1",
     "lint-staged": "^17.2.0",
     "msw": "^2.15.0",
     "playwright": "^1.62.0",
-    "storybook": "^10.5.4",
+    "storybook": "^10.5.5",
     "typescript": "6.0.3",
     "typescript-eslint": "^8.65.0",
     "vite": "8.1.5",

+ 1 - 1
frontend/src/pages/xray/dns/DnsTab.tsx

@@ -47,7 +47,7 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab
   const lastWrittenHostsRef = useRef<string | null>(null);
 
   useEffect(() => {
-    if (!dns) {
+    if (!dnsEnabled) {
       lastWrittenHostsRef.current = '{}';
       setHostsList([]);
       return;

+ 4 - 4
go.mod

@@ -13,14 +13,14 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/gorilla/websocket v1.5.3
 	github.com/joho/godotenv v1.5.1
-	github.com/mattn/go-sqlite3 v1.14.48
+	github.com/mattn/go-sqlite3 v1.14.49
 	github.com/mymmrac/telego v1.11.1
 	github.com/nicksnyder/go-i18n/v2 v2.6.1
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
 	github.com/robfig/cron/v3 v3.0.1
 	github.com/shirou/gopsutil/v4 v4.26.6
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
-	github.com/valyala/fasthttp v1.72.0
+	github.com/valyala/fasthttp v1.73.0
 	github.com/xlzd/gotp v0.1.0
 	github.com/xtls/xray-core v1.260327.1-0.20260728075948-5ca6f4b7d4dc
 	go.uber.org/atomic v1.11.0
@@ -99,7 +99,7 @@ require (
 	go.mongodb.org/mongo-driver/v2 v2.8.0 // indirect
 	go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
 	golang.org/x/arch v0.29.0 // indirect
-	golang.org/x/exp v0.0.0-20260718201538-764159d718ef // indirect
+	golang.org/x/exp v0.0.0-20260727155853-b88d891fe743 // indirect
 	golang.org/x/mod v0.38.0 // indirect
 	golang.org/x/net v0.57.0
 	golang.org/x/sync v0.22.0 // indirect
@@ -108,7 +108,7 @@ require (
 	golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
 	golang.zx2c4.com/wireguard v0.0.0-20260522210424-ecfc5a8d5446 // indirect
 	golang.zx2c4.com/wireguard/windows v1.0.1 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0 // indirect
 	google.golang.org/protobuf v1.36.11
 	gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 // indirect
 	lukechampine.com/blake3 v1.4.1 // indirect

+ 8 - 8
go.sum

@@ -129,8 +129,8 @@ github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15 h1:YkjVPl/YH5XlJ+
 github.com/lufia/plan9stats v0.0.0-20260627054121-477a66015f15/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
 github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
 github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
-github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs=
-github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
+github.com/mattn/go-sqlite3 v1.14.49 h1:B8jBHC3xhxZgxztrgruTuLucebnULQnx4W7cF7SAE9w=
+github.com/mattn/go-sqlite3 v1.14.49/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
 github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
 github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -204,8 +204,8 @@ github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY
 github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasthttp v1.72.0 h1:R7kYdoWhn1ye1fVpP+cDHDJwYm3NkwLliwgzJ/Abg7M=
-github.com/valyala/fasthttp v1.72.0/go.mod h1:zsbLTYqcpIktdQytlVBwIjY9La5d6bs990nBxWg8efk=
+github.com/valyala/fasthttp v1.73.0 h1:ocTOORnBWtJ+P8t/6wAjdkchMzdfHmWx2VD/DPbgZ7s=
+github.com/valyala/fasthttp v1.73.0/go.mod h1:EtXQDHaR+5P18p8wqDRFpUhxr108Ga9mXvVJXHRrN2k=
 github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
 github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
 github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
@@ -250,8 +250,8 @@ golang.org/x/arch v0.29.0 h1:8sSET5wB0+exBm0FGmOtdHMqjlRdV2DRD3/IV6OZgho=
 golang.org/x/arch v0.29.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
 golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
 golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
-golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A=
-golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q=
+golang.org/x/exp v0.0.0-20260727155853-b88d891fe743 h1:ex206bKw+v3K0dm3andkrIF+ijyQKJG1pLgwQ2PYdQM=
+golang.org/x/exp v0.0.0-20260727155853-b88d891fe743/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q=
 golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
 golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
 golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
@@ -279,8 +279,8 @@ golang.zx2c4.com/wireguard/windows v1.0.1 h1:eOxiDVbywPC+ZQqvdCK7x+ZwWXKbYv50TtH
 golang.zx2c4.com/wireguard/windows v1.0.1/go.mod h1:+fbT3FFdX4zzYDLwJh5+HPEcNN/3HyNdzhNSVsQM+zs=
 gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
 gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df h1:O3ig1i5WDDzsVzRp+cCdgelT9vXnlnOFdlEeFtL4HCc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0 h1:mJiOtnGp0k/BcSgdu03G2NwnscCfCH+h2QKUBZr18KI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260729162451-8efbd57d26e0/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
 google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
 google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
 google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=

+ 1 - 1
internal/database/backup_test.go

@@ -35,7 +35,7 @@ func TestBackupSQLiteProducesValidSnapshotDuringWrites(t *testing.T) {
 	firstWrite := make(chan error, 1)
 	writesDone := make(chan error, 1)
 	go func() {
-		for i := 0; i < 128; i++ {
+		for i := range 128 {
 			if err := db.Create(&model.Setting{Key: fmt.Sprintf("backup-write-%d", i), Value: value}).Error; err != nil {
 				if i == 0 {
 					firstWrite <- err

+ 4 - 8
internal/sub/external_subscription_test.go

@@ -43,11 +43,9 @@ func TestFetchSubscriptionLinksSharesConcurrentRefresh(t *testing.T) {
 	results := make(chan []string, callers)
 	var wg sync.WaitGroup
 	for range callers {
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
+		wg.Go(func() {
 			results <- fetchSubscriptionLinks(srv.URL)
-		}()
+		})
 	}
 
 	time.Sleep(100 * time.Millisecond)
@@ -123,11 +121,9 @@ func TestFetchSubscriptionLinksSharesStaleResultAfterRefreshFailure(t *testing.T
 	results := make(chan []string, callers)
 	var wg sync.WaitGroup
 	for range callers {
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
+		wg.Go(func() {
 			results <- fetchSubscriptionLinks(staleURL)
-		}()
+		})
 	}
 
 	time.Sleep(100 * time.Millisecond)

+ 5 - 9
internal/sub/forwarded_trust_test.go

@@ -40,10 +40,6 @@ func setTrustedProxyCIDRs(t *testing.T, value string) {
 	}
 }
 
-func storedAs(value string) *string {
-	return &value
-}
-
 func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 	tests := []struct {
 		name             string
@@ -65,7 +61,7 @@ func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 		},
 		{
 			name:             "empty stored value keeps trusting forwarded headers",
-			stored:           storedAs(""),
+			stored:           new(""),
 			remoteAddr:       "203.0.113.9:51000",
 			wantScheme:       "https",
 			wantHost:         "sub.example.net",
@@ -74,7 +70,7 @@ func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 		},
 		{
 			name:             "stored shipped default keeps trusting forwarded headers",
-			stored:           storedAs(service.DefaultTrustedProxyCIDRs),
+			stored:           new(service.DefaultTrustedProxyCIDRs),
 			remoteAddr:       "203.0.113.9:51000",
 			wantScheme:       "https",
 			wantHost:         "sub.example.net",
@@ -83,7 +79,7 @@ func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 		},
 		{
 			name:             "declared boundary ignores an origin outside it",
-			stored:           storedAs("10.0.0.0/8"),
+			stored:           new("10.0.0.0/8"),
 			remoteAddr:       "203.0.113.9:51000",
 			wantScheme:       "http",
 			wantHost:         "panel.example.com",
@@ -92,7 +88,7 @@ func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 		},
 		{
 			name:             "declared boundary trusts an origin inside it",
-			stored:           storedAs("10.0.0.0/8"),
+			stored:           new("10.0.0.0/8"),
 			remoteAddr:       "10.1.2.3:44000",
 			wantScheme:       "https",
 			wantHost:         "sub.example.net",
@@ -101,7 +97,7 @@ func TestResolveRequest_ForwardedHeaderTrust(t *testing.T) {
 		},
 		{
 			name:             "declared boundary ignores an unparsable origin",
-			stored:           storedAs("10.0.0.0/8"),
+			stored:           new("10.0.0.0/8"),
 			remoteAddr:       "not-an-ip",
 			wantScheme:       "http",
 			wantHost:         "panel.example.com",

+ 2 - 3
internal/web/service/golden_fixtures_xray_test.go

@@ -8,6 +8,7 @@ import (
 	"crypto/x509/pkix"
 	"encoding/json"
 	"encoding/pem"
+	"maps"
 	"math/big"
 	"os"
 	"path/filepath"
@@ -256,9 +257,7 @@ func TestGoldenStreamFixturesBuildInXray(t *testing.T) {
 				case "stream":
 					stream = fixture
 				case "security":
-					for key, value := range fixture {
-						stream[key] = value
-					}
+					maps.Copy(stream, fixture)
 				case "sockopt":
 					stream["sockopt"] = fixture
 				case "finalmask":

+ 2 - 3
internal/xray/api_users_e2e_test.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"maps"
 	"net"
 	"net/http"
 	"net/url"
@@ -138,9 +139,7 @@ func panelUser(email string, fields map[string]any) map[string]any {
 		"preSharedKey": "",
 		"keepAlive":    "",
 	}
-	for k, v := range fields {
-		user[k] = v
-	}
+	maps.Copy(user, fields)
 	return user
 }