txlyre

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • edb487a005 chore(deps): migrate to react-router 8 and refresh frontend dependencies react-router-dom 7 is superseded by react-router 8, which folds the DOM bindings back into the core package. RouterProvider now comes from `react-router/dom`, while the hooks and `createBrowserRouter` move to `react-router`. Updates the nine importing modules and the router line in docs/architecture.md to match. Also refreshes antd, react-i18next, storybook, eslint, lint-staged and playwright to current patch/minor releases, and restores alphabetical order in devDependencies for the @vitest/browser-playwright and playwright entries. Bumps brace-expansion to 5.0.8, the only release outside the affected range of GHSA-mh99-v99m-4gvg (unbounded expansion length causing an OOM crash). `npm audit fix` could not apply this on its own: the lockfile pinned 5.0.7 and npm will not re-resolve a transitive-only dependency in place, so the entry was updated directly and reinstalled.
  • 35cf6be6f9 fix(ci): keep the triage prompt under the 21000-char expression cap The previous commit pushed handle-issue's prompt to 21587 characters and GitHub stopped parsing the file: "(Line: 39, Col: 19): Exceeded max expression length 21000". Because the prompt interpolates ${{ }}, GitHub treats the whole block scalar as a single expression, and the cap applies per expression. The failure mode is quiet and total - no job fails, the workflow itself disappears, its registered name reverts from "Claude Bot" to the file path, and the only signal is a run attributed to the push with no jobs in it. Drop the hand-written stack description, repository map and runtime-fact list from that prompt and point at CLAUDE.md and docs/architecture.md instead. Both are maintained, both are already in the checkout, and the copy in the prompt had drifted from them anyway - it still described the mtg worker, omitted internal/tunnelmonitor/ and memory.high, and filed internal/web/runtime/ under "wiring". Only the support-facing facts that live in neither file are kept: the install one-liner, the random initial credentials, the distro-dependent env file, the Docker image and the capabilities fail2ban needs. handle-issue is now 15069 characters, and a header comment records the limit so the next edit does not rediscover it in production.
  • 0f7329c3ce fix(ci): repair the Claude bot and narrow what it can reach Three problems, all in .github/workflows/claude-bot.yml. It was silently dead. No comment had been posted since 2026-07-20 while every run reported success: roughly twenty issues and pull requests each burned 18-56 turns and up to $2.59, ended with permission denials, and published nothing. Comment bodies are markdown, markdown is full of backticks, and inside a quoted `--body "..."` backticks are command substitution, so the write was rejected and a failed triage looked exactly like a clean one. The body now goes to /tmp through Write and out through --body-file, in every branch of both jobs, and each job re-reads the thread afterwards so a rejected write fails loudly instead of reporting success. The run transcript is kept as an artifact. It could reach much further than it claimed. Both jobs that any GitHub user can trigger declared themselves READ-ONLY in prose while holding Bash(gh:*), which is not a GitHub-scoped allowlist: `gh alias set --shell` runs its argument through sh -c and `gh extension install` fetches and executes code, both as single commands whose first token is gh. That is a general shell on a runner holding CLAUDE_CODE_OAUTH_TOKEN, which does not expire with the job. `gh api` accepted any method, issues: write is repo-scoped rather than issue-scoped, and `gh pr review --approve`, `gh pr close` and `gh pr checkout` were forbidden in prose only. Those two jobs now list the subcommands they actually run. The untrusted title and body are fenced in tags carrying github.run_id, unguessable at the time the issue is written, and the invariants an allowlist cannot express - one issue number, labels and title only, /tmp as the sole writable path, never $GITHUB_ENV - are stated explicitly. Both checkouts get persist-credentials: false. handle-pr-fix and mention keep their wildcards: only owners, members and collaborators can trigger them, and narrowing the maintainer's own path risks more than it protects. Its review hid findings and its triage quoted stale facts. "Prefer a few high-signal findings over many low-value ones" is read literally by Opus - it finds the bug, judges it below the stated bar and says nothing - while the Severity and Confidence tiers already existed to do that filtering. The review also never said that the working directory is the base revision, so it could assert that a case was unhandled in code the pull request had already rewritten, and label it confirmed, on an outside contributor's first patch. Four CLAUDE.md conventions were missing, each a guaranteed miss: openapigen's StructAllow allowlist, the layering rules including the runtime.Runtime dispatch requirement that silently breaks multi-node when bypassed, the assertion standard, and golden share-link fixtures regenerated to turn a red test green. On the triage side the invalid and duplicate branches were gated three times over and so never fired, leaving spam to collect a full investigation and a courteous reply; /etc/default/x-ui was given as the env file when it is distro-dependent, making the PostgreSQL migration advice a silent no-op on RHEL and Arch; an env list labelled "full" omitted XUI_PORT and the XUI_TUNNEL_HEALTH_* family; XTLS was offered as a security option the panel does not have. docs/architecture.md was invisible to both prompts despite being maintained and already in the checkout. From the bot's own output: it published a trigger only the maintainer can use, retitled issues without saying so, asked for screenshots it cannot open, and once invented a reason for a number it had miscounted. All four jobs move to Opus 5, at xhigh effort rather than max - the recommended tier for agentic work, and one below the overthinking that max invites on routine triage.
  • 29557e2153 fix(sub): gate the VLESS flow in JSON subscriptions like raw and Clash links genVless emitted client.Flow unconditionally, while the raw link (service.go:806) and the Clash proxy (clash_service.go:251) both gate it behind vlessFlowAllowed. A flow_override left on client_inbounds after its inbound moved to a transport Vision cannot use -- ws, grpc, httpupgrade -- therefore survived only into the JSON subscription, handing that client an outbound xray-core rejects while its other two formats were correct. Apply the same gate at the call site, reading the network from the per-host stream so a host that rewrites the transport is judged on what it actually emits. Verified by seeding a flow_override on a ws+tls inbound: before, raw and Clash dropped the flow and JSON kept it.
  • 0b60154383 fix(docs): force transitive sharp up to patched 0.35.3 sharp <0.35.0 inherits four libvips CVEs (GHSA-f88m-g3jw-g9cj). It comes in as an optional dependency of next, which still declares ^0.34.5 on its current release, so only an override reaches the fixed line. Brings libvips 8.18.3 via @img/sharp-libvips-* 1.3.2.
  • Ver comparación de estos 8 commits »

hace 9 horas

txlyre hizo push a master en txlyre/libqirt

hace 11 horas

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • cd674c8d4f feat(sub): expose live online status and add ?format=info endpoint Custom subscription templates only received the lastOnline timestamp, so template authors had to fake an online indicator by comparing it against the current time, and the page was a one-shot server render with no way to refresh usage without reloading the whole HTML. The template context (and window.__SUB_PAGE_DATA__) now carries isOnline, computed from the panel's own online-client tracking (local xray plus remote nodes) at render time. The subscription URL also answers ?format=info with the page view-model as JSON — minus the links, with emails deduplicated — so templates can poll live status cheaply. The shared view-model construction moved into buildSubPageData/subPageContext so the HTML page, the SPA payload and the info JSON cannot drift apart. Also documents the previously injected but undocumented announce template variable.

hace 1 día

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • b319dd0c3a fix(panel): align telegram icon with its label in home card actions The .tg-icon override (display: inline-block; vertical-align: -2px) defeated the default .anticon flex centering that every other card action icon relies on, so the icon rendered ~2px below the @XrayUI text. Dropping the override lets AntD center it like its neighbors.
  • 8ef2eec3d1 fix(hosts): assign group ids to imported hosts and repair empty ones Host rows created from a legacy streamSettings.externalProxy during inbound import got an empty group_id, and the one-time HostGroupIds seeder had already been gated off, so the UI rendered them under a synthetic fallback_<id> group the update/delete API could not resolve, failing every edit with "host group not found". Assign a real group id in externalProxyEntryToHost at creation, and replace the seeder with backfillEmptyHostGroupIds, an idempotent startup repair that runs on every boot so rows from older builds and restored backups are healed too. Also rename the leaked internal error "host group not found" to "host not found" since groups are not a user-facing concept.
  • 941c6116a9 chore(openapi): regenerate schemas with int64 formats on node fields Output of make gen: the generator now stamps format int64 on the node status schema's 64-bit integer fields (timestamps, net counters, uptime), syncing the committed OpenAPI doc and generated schemas with the Go structs.
  • Ver comparación de estos 3 commits »

hace 1 día

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • c77608bc47 fix(nodes): make node API tokens write-only (#5613) * fix(nodes): make node API tokens write-only * fix(nodes): keep token optional on edit for write-only API tokens NodeView no longer returns apiToken, so the edit form must consume hasApiToken and not require re-entering the token. Relaxes the form validation on edit, adds a keep-current placeholder, and adds the i18n key to all 13 locales.
  • 892c06c8bc Bug-label issue sweep: 16 fixes (#6083) * fix(xray): block private-range egress in default freedom finalRules (#6037) With domainStrategy AsIs the router never resolves domains, so a domain with a private A record (e.g. 127-0-0-1.nip.io) sails past the geoip:private routing block and freedom's allow-all finalRules let it reach loopback services such as the xray gRPC API and metrics listener. Prepend a block rule for geoip:private to the default template and add the FreedomFinalRulesPrivateEgressBlock seeder so existing installs still carrying the stock allow-only (or legacy private-only-allow) finalRules are upgraded in place; customized rules are left untouched. * fix(sub): version-gate unencrypted-outbound drops in outbound subscriptions (#6033) Commit d38c912d taught CheckXrayConfig to keep unencrypted vless/trojan outbounds when the running core predates the v26.7.11 rejection, but filterOutboundsRejectedByCore still consulted the embedded validator unconditionally, so outbound subscriptions kept silently dropping those outbounds even on downgraded cores. Apply the same shouldSkipLegacyUnencryptedOutboundRejection gate when filtering fetched subscription outbounds. * fix(xray): resolve geodata assets before building outbound configs (#5928) Saving routing or template settings validates each outbound through the embedded config loader, and a freedom outbound whose finalRules reference geoip:private opens geoip.dat during that build. Unlike ApplyRoutingConfig, ValidateOutboundConfig and AddOutbound never pointed the in-process loader at the bin folder, so xray-core resolved the file relative to the panel executable and saving failed with 'stat /usr/local/x-ui/geoip.dat: no such file or directory'. Call ensureXrayAssetLocation before both build paths. * fix(api): use a real i18n key in the client get handler (#5911) The client fetch endpoint localized its error prefix with the bare key 'get', which exists in no translation file, so every lookup of a deleted client's email logged 'message "get" not found in language ...' noise alongside the expected record-not-found warning. Reuse the same pages.inbounds.toasts.obtain key the sibling list handler uses. * fix(sub): carry host record Host header and path into Clash/JSON output (#5944) The raw-link path overrides the host/path share params from a Host record via applyEndpointHostPath, but the Clash and JSON renderers read the transport settings object, which applyHostStreamOverrides never touched — so a Host record's WebSocket Host header (and path) silently vanished from Clash/Mihomo and JSON subscriptions whenever the inbound's own ws settings left them empty. Inject hostHeader/path into the ws/httpupgrade/xhttp settings of the per-host stream, mirroring the raw-link override. * fix(metrics): accept Unicode outbound tags in the observatory (#5972) The observatory validator whitelisted ASCII word characters, so any outbound whose tag carries a flag emoji or other non-ASCII text was silently dropped from the metrics snapshot, delay history, and health notifications. The history store is an in-process map, so the strict charset bought nothing. Validate tags as non-empty, bounded, control-character-free UTF-8 instead, keeping spaces and emoji while still rejecting garbage input on the query path. * fix(database): default sqlite to WAL to stop background-job lock storms (#6057, #6068) With journal_mode=DELETE every write serializes the whole database and blocks readers, so under normal multi-job load (traffic sampling, node sync, mtproto reconcile) transactions regularly outwaited the 10s busy timeout and jobs failed with 'database is locked'. Move to WAL by default: readers no longer block writers and vice versa, which removes the observed contention while writer-writer access still serializes safely. The single-file-at-rest property is preserved where it matters — Checkpoint() now issues wal_checkpoint(TRUNCATE), so panel and Telegram backups read a complete main file, and sqlite folds the WAL back into the db on clean shutdown. XUI_DB_JOURNAL_MODE=DELETE restores the previous behavior for setups that copy the live file directly. * fix(database): strip finalmask.tcp from REALITY inbounds on upgrade (#6038) validateFinalMaskRealityCombo blocks saving finalmask.tcp together with REALITY because that combination crashes Xray-core 26.7.11 on the first connection (XTLS/Xray-core#6453), but it only runs on add/update. An inbound saved before the validator existed sailed through the upgrade untouched and took the core down at boot. Add the InboundRealityFinalmaskTcpStrip seeder: one-time scan that removes finalmask.tcp from REALITY inbounds (other finalmask transports survive), so upgraded panels start cleanly. * fix(xray): stop deleting hand-written direct routing rules on save (#6056) The DNS allow-rule sync recognized 'its' rules purely by shape (type=field, ip, port, outboundTag=direct, nothing else), so any manual rule of that shape — e.g. routing a LAN CIDR to a NAS port over direct — was silently stripped on every settings save. Mark managed rules with ruleTag=xui-dns-allow (round-tripped untouched by both xray-core and the Routing tab editor) and only strip rules that carry the tag. Untagged legacy managed rules are adopted when their exact ip-set/port matches a currently configured private DNS endpoint; anything else is left alone. A stale pre-tag managed rule whose DNS server was removed now lingers until deleted manually — the safe side of the trade against eating user rules. * fix(clients): resolve email lookups through client_inbounds after a move (#6059) GetClientInboundByEmail trusted the client_traffics.inbound_id pointer whenever that inbound still existed, but a client moved between inbounds leaves the row pointing at its old (still existing) inbound. The lookup then searched the wrong inbound's clients and failed with 'Client Not Found In Inbound For Email', which broke the Telegram bot's link and QR generation for moved clients. When the pointed-at inbound no longer carries the email, re-resolve through the authoritative client_inbounds link to the inbound that actually hosts the client. * fix(nodes): replicate inbound fallbacks to nodes (#5963) Fallbacks live in the inbound_fallbacks table and were only merged into settings by the master's local config builder; the runtime inbound pushed to nodes rebuilt settings without them, and the reconcile job additionally fingerprinted the raw DB row, so fallback edits neither reached nodes nor triggered a re-push. Inject settings.fallbacks in buildRuntimeInboundForAPI (mirroring the local builder, gated on inboundCanHostFallbacks) and make ReconcileNode push and fingerprint that same runtime-built payload, aligning the interactive and reconcile paths. * fix(database): survive PostgreSQL outages without a runaway restart loop (#6023) A PostgreSQL that was down or still starting made InitDB fail instantly; the process exited with a generic startup error and systemd restarted it every 5s forever, flooding the journal. Retry the initial postgres connection with backoff (~70s total) and log the real driver error on every attempt, and cap the systemd units with StartLimitIntervalSec/StartLimitBurst so a persistently unreachable database stops the unit instead of looping indefinitely. * fix(xray): force a full restart when REALITY stream settings change (#6010) A changed inbound is normally hot-swapped over gRPC as RemoveInbound + AddInbound, but xray-core does not reliably rebuild a REALITY listener's authenticator on a runtime re-add — key or shortId edits appeared applied yet clients kept authenticating against the old parameters until someone restarted the core manually, on nodes in particular. Treat any non-client change to an inbound that uses (or starts using) REALITY as not hot-appliable so the panel restarts the core instead. Client-only edits on REALITY inbounds keep flowing through the per-user AlterInbound path and still avoid restarts. * feat(sub): allow insecure TLS for outbound subscription fetches (#6067) An outbound subscription served over HTTPS with a self-signed or private-CA certificate could never be fetched: the fetch client had no TLS options, so refreshes died with 'x509: certificate signed by unknown authority' and there was nothing the admin could toggle. Add a per-subscription 'Allow insecure' switch (persisted as allow_insecure, default off) that sets InsecureSkipVerify on the fetch transport — including when the fetch is routed through the panel egress proxy. The SSRF-guarded dialer and redirect re-validation stay in force either way. * fix(reality): send PROXY protocol header in the target scanner when xver is set (#6082) The REALITY target scanner always probed with a plain TLS handshake, so a target fronted by an Nginx listener that requires the PROXY protocol (matching the inbound's xver>=1) reset the connection and the panel reported a false 'TLS handshake failed'. Thread the inbound's xver into the scan request and, when it is >=1, lead with the matching PROXY protocol header (v1 for xver 1, binary v2 for xver 2) built from the dialed connection's own address pair. Batch candidate scans against public sites are unaffected (xver 0). * fix(frontend): default sockopt fields when editing a stored inbound (#5956) Opening an existing inbound ran rawInboundToFormValues over the raw DB row, and only xhttpSettings was re-parsed through its Zod schema to fill defaults. A sockopt object saved before the TProxy control existed has no tproxy key, so the Select rendered blank; picking Off didn't help because the wire normalizer drops tproxy=off, recreating the missing key on the next edit. Re-parse streamSettings.sockopt through SockoptStreamSettingsSchema on load, mirroring the xhttpSettings handling, so absent keys (tproxy, tcpcongestion, …) get their schema defaults every time the form opens.
  • Ver comparación de estos 2 commits »

hace 2 días

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • 16b9b3ce1c chore(deps): bump docs and frontend dependencies Routine minor/patch updates: Next.js 16.2.11 + eslint-config-next, fumadocs, React 19.2.8, Storybook 10.5.3, and assorted tooling. Docs stays on ESLint 9 (^9.39.5): eslint-config-next pulls in eslint-plugin-react 7.37.5, whose newest release still calls the context.getFilename API that ESLint 10 removed, so eslint crashes on every file under ESLint 10. The frontend workspace already ran ESLint 10 without eslint-plugin-react and is unaffected.

hace 2 días

txlyre hizo push a master en txlyre/qic

hace 3 días

txlyre sincronizados commits a main en txlyre/3x-ui desde la réplica

  • 2b1308ca29 feat(notifications): add a consecutive-failure threshold for outbound.down alerts (#5968) Problem: a flaky outbound produces hundreds of false-positive "outbound down" notifications overnight — each fires the moment xray's observatory reports a single failed probe, and the next successful probe fires an "up". applyObservatory forwarded every raw alive:true->false transition straight to EventOutboundDown; xray's observatory has effectively no hysteresis, and nothing on the panel side debounced it (the email/Telegram subscribers are pure formatters). Fix: debounce per outbound. outbound.down now fires only after outboundDownThreshold consecutive FAILED probes (new setting, default 3); outbound.up fires immediately on the first successful probe and only when a down was actually notified. The threshold gates the event itself, so email and Telegram share one knob (exposed next to the outbound.down toggle). The streak counts genuinely new probes (last_try_time advancing), not sampler polls — the sampler runs every 2s but the observatory re-probes per its probeInterval, so counting samples would trip the threshold instantly. outboundDownThreshold=1 reproduces the legacy notify-on-first-failure behaviour. Tuning the observatory's probe interval/timeout is not a workaround: those probes also drive the load balancer's outbound selection, so loosening them to quiet notifications would slow real failover away from a genuinely dead outbound. Notifications don't need observatory-grade latency, so the tolerance belongs at the notification layer, leaving the observatory (and balancer) untouched. Adds TestApplyObservatoryDebounce covering the threshold, probe-vs-sample counting, single-blip suppression and the legacy path. Co-authored-by: Yuriy Khachaturian <[email protected]> Co-authored-by: Claude Opus 4.8 <[email protected]>
  • 9e117bbdd3 fix(clients): keep VLESS xtls-rprx-vision flow when inbound options reload (#5971) The client form cleared the `flow` field whenever `showFlow` was false, but `showFlow` is derived from the inbound options list, which is transiently empty while the options query (re)loads (`inboundOptionsQuery.data ?? []`). During that window `showFlow` is a false negative, so the effect silently dropped a valid `xtls-rprx-vision` flow the user had picked for a Reality/TLS inbound and never restored it — the client was then saved with an empty flow and could not connect with XTLS Vision. Guard the clear so it only runs once the inbound options are actually available. Adds a regression test that reproduces the drop across an options reload. Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
  • 8cd71e07ea fix: refresh stale client_traffics row when an inbound-deleted client's email is reused (#6003) * fix: refresh stale client_traffics row when an inbound-deleted client's email is reused AddClientStat's OnConflict was DoNothing on email, so once an inbound is deleted (DelInbound only removes the client_inbounds link, matching ClientService.Detach's intentional Detach-then-later-Attach behavior) the orphaned client_traffics row for that email survives untouched. Re-creating a client under the same email on a new inbound silently kept the old enable/expiry_time/reset/total/inbound_id instead of adopting the new client's config. Switch the conflict path to DoUpdates on inbound_id/total/expiry_time/ enable/reset. up/down stay excluded on purpose: every call for an already-attached identity carries the same config values (one call per inbound), so the refresh is a no-op for that legitimate multi-inbound share, while zeroing usage counters on each additional attach would erase real traffic. Fixes #5958 * fix: don't let AddClientStat clobber import's forced-enabled ClientStats rows github-actions[bot] review on #6003 found that AddInbound writes client_traffics twice for the same import payload: first inserting each ClientStats row (DoNothing, with Enable forced true by controller.importInbound), then calling AddClientStat once per Settings-derived client. With AddClientStat's OnConflict now DoUpdates, that second call was unconditionally overwriting enable (and total/expiry_time/reset/inbound_id) with the Settings.clients[].enable value — which still holds whatever the client had at export time, silently undoing the controller's "always import as enabled" behavior for any client disabled at export. Fix: track which emails were already seeded by the ClientStats loop and skip the AddClientStat call for those emails, leaving the import path's forced values as authoritative. Plain (non-import) creates are unaffected since ClientStats is empty there, so every client still goes through AddClientStat's refresh as before. Also updated a stale comment in addClientTraffic that still described AddClientStat as DoNothing. Added TestAddInbound_ImportForcedEnableSurvivesDisabledSettingsClient, which reproduces the exact regression (verified it fails without this fix) and passes with it.
  • 79e65f63df fix(xray): validate generated egress targets (#5989) * fix(xray): validate panel egress target Avoid generating a loopback panel bridge and routing rule when a saved panel outbound disappears after an outbound subscription refresh. Preserve routing unchanged and log the missing target instead. * fix(xray): guard node and mtproto egress Apply the fail-closed target check to every generated egress bridge. Skip node and MTProto bridge injection when a selected outbound disappears or the relevant JSON cannot be parsed. * test(xray): complete node egress coverage Cover tag and port collisions plus absent and malformed routing. Clarify the fail-closed bridge behavior in the panel and MTProto egress documentation.
  • c87649d9f2 fix(sub) Happ profileEnableRouting button (#6008)
  • Ver comparación de estos 14 commits »

hace 3 días

txlyre hizo push a master en txlyre/libqirt

hace 4 días

txlyre hizo push a master en txlyre/qic

hace 6 días

txlyre hizo push a master en txlyre/qic

hace 6 días

txlyre hizo push a master en txlyre/qic

hace 6 días

txlyre hizo push a master en txlyre/libqirt

hace 6 días

txlyre hizo push a master en txlyre/libqirt

hace 6 días

txlyre hizo push a master en txlyre/libqirt

hace 6 días

txlyre hizo push a master en txlyre/libqirt

hace 6 días

txlyre hizo push a master en txlyre/libqirt

hace 6 días

txlyre hizo push a master en txlyre/qic

hace 6 días

txlyre hizo push a master en txlyre/qic

hace 6 días

txlyre hizo push a master en txlyre/qic

hace 6 días