700 Commits
Author SHA1 Message Date
omar d41a685d9b chore: relocate shater meta-docs to docs-shater/ (avoid upstream docs/ collision)
Upstream sing-box-lx already ships a docs/ mkdocs site; keep our project docs
separate and unambiguous in docs-shater/ (parallels upstream's docs-lx/).
Updated all references in README.md, CLAUDE.md, CONTEXT.md, ARCHITECTURE.md.
2026-07-14 14:19:34 +03:00
omar 2c7b1ff9d8 merge: fork sing-box-lx v1.14.0-lx.3 as v0.2 engine base
Fork upstream github.com/Leadaxe/sing-box-lx (tag v1.14.0-lx.3) into main as the
v0.2 engine, per docs/DECISIONS.md D3 (main IS the fork; additive overlay).

Conflict resolution:
- README.md  -> ours (shater v0.2 project readme)
- LICENSE    -> upstream (canonical GPL-3.0; identical license)
- .gitignore -> union of both; CLAUDE.md kept tracked

Go module stays github.com/sagernet/sing-box so our overlay (shater/, panel/)
can import engine packages directly. submodules/wireguard-go pinned at
1adc4c71 provides AmneziaWG 2.0 (populated next).
2026-07-14 14:18:14 +03:00
omar d68b8e7116 docs: add CLAUDE.md (orchestrator rules) + DESIGN.md (Faceplate spec) 2026-07-14 14:17:00 +03:00
omarandClaude Opus 4.8 903f2345f3 chore: reset main for v0.2 (sing-box fork) — full context docs
Foundation pivot. The complete, working, VM-verified xray-based project is
preserved on the `v0.1` branch; `main` is reset to a docs-first scaffold for
v0.2, which will be built as a FORK of sing-box-lx with our control-plane,
DNS filter, stats and admin panel embedded in the one binary.

- Preserve everything on branch v0.1 (pushed).
- Remove the v0.1 implementation + old design docs from main (recoverable from
  v0.1); keep LICENSE, .gitignore, .gitattributes, dist/shater-feed.pub (feed
  signing key 5ac4b177689cb8e0 carries over).
- License -> GPL-3.0 (sing-box is GPL-3.0).
- Add full project context so it survives compaction:
  docs/CONTEXT.md (start here), DECISIONS.md, ARCHITECTURE.md, ROADMAP.md,
  FEATURES.md, and a new README.

Engine/UI decisions (see docs/DECISIONS.md): fork sing-box-lx (AmneziaWG 2.0 +
broad protocols, GPL-3.0, library-first) and embed the whole product for tight
integration; keep the fork maintainable via an additive overlay (shater/, panel/,
openwrt/) rebased on upstream tags. UI = thin LuCI launcher + a separate admin
panel served by the daemon, entered via a short-lived token minted in the
authenticated LuCI session. Do NOT write a proxy engine from scratch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
2026-07-14 13:53:15 +03:00
omarandClaude Opus 4.8 972665798f docs: clean up repo — English docs under docs/, proper README (EN+RU), LICENSE
build / aarch64_cortex-a53 (push) Successful in 3m12s
build / x86_64 (push) Successful in 3m6s
build / release (push) Successful in 14s
Repository housekeeping so the tree is clean and navigable:

- Remove 11 stale internal working docs (00-07 planning/audit/design drafts,
  ACCEPTANCE, PROOFS, STATUS) and the architecture.html artifact — history stays
  in git.
- Consolidate docs under docs/: BUILD.md, FEED.md (moved), CONFIG.md (English
  translation of the old Russian CONTRACT.md — full UCI schema + xrayctl/ubus
  interface), ARCHITECTURE.md (distilled English, keeps the Mermaid diagrams).
- Rewrite README.md as a proper English project readme; add a Russian mirror
  README.ru.md. Both cross-link.
- Add LICENSE (GPL-2.0-or-later) and unify PKG_LICENSE across all three package
  Makefiles (was MIT / GPL-2.0 / GPL-2.0-or-later).
- Drop dist/README.md and dist/make-feed.sh (superseded by docs/FEED.md and the
  hardened ci/make-index.sh); keep dist/shater-feed.pub.
- Fix all dangling doc references (CONTRACT.md -> docs/CONFIG.md, dead numbered
  docs) in examples/, shater-core on-device comments, xrayctl/main.go, CI notes.
- Delete build junk from the worktree (shater.zip, xrayctl.exe, out/).

No code behavior change; go build + vet still pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
2026-07-14 00:18:50 +03:00
Leadaxe 9dc758e43c Merge upstream/testing (L3-forwarding, snell, bridge) into lx-1.14
Merges 14 upstream commits including L3-forwarding support (which bumped
wireguard-go v0.0.3->v0.0.5, already re-grafted in the prior commit),
snell protocol, bridge outbound, flow-tracking/sniff improvements, and
DNS/dialer fixes.

lx conflict resolutions:
- protocol/wireguard/endpoint.go: took upstream's new flow API
  (PreMatchFlow/PortAddresses/PortMTU/AttachReturn/DetachReturn/JudgeFlow),
  dropped our old PrepareConnection/NewDirectRouteConnection. SPEC 020
  idle-suspend wake guard (resumeOnDial) moved to WritePackets — the single
  point every L3-forwarded packet transits, incl. established flows that
  bypass DialContext.
- adapter/outbound.go: kept lx IdleSuspendable/ReachabilityInvalidator,
  restored 'time' import dropped by auto-merge.
- go.mod/go.sum + test/: took upstream dependency bumps (tailscale, sing,
  sing-tun); wireguard-go stays v0.0.5 with local submodule replace.

Green: full sing-box CLI with LX_TAGS (Go 1.24.7), libbox, wireguard/
adapter/dns/daemon packages, transport+protocol/wireguard tests, AWG
config validation.
2026-07-08 15:10:38 +03:00
世界 9ec7cc8cbe Improve bridge 2026-07-08 16:30:06 +08:00
世界 aaa1289e5c Bump version 2026-07-08 00:34:32 +08:00
世界 c7fe778cae Add bridge outbound 2026-07-08 00:34:26 +08:00
世界 f2dd4bfd75 Imrpove flow tracking & sniff action 2026-07-07 18:37:18 +08:00
世界 c4c11b1b1b Bump version 2026-07-07 18:37:18 +08:00
世界 e6419b945f Add L3 forwarding support 2026-07-06 21:13:33 +08:00
世界 585d3e639e Bump version 2026-07-05 12:47:42 +08:00
世界 5af56d2cfd Add snell protocol 2026-07-05 12:47:42 +08:00
Leadaxe 38bda198ff docs: move lx docs out of upstream docs/ into docs-lx/
docs/ is an upstream-owned tree (it arrives wholesale from SagerNet on
every rebase). Our three downstream docs lived inside it — lx-config.md,
lx-changelog.md, lx-release-runbook.md — mixing fork files into the
upstream surface against CONSTITUTION principle #1 (thin layer / minimal
diff). Move them to a dedicated root-level docs-lx/ so the boundary
between our docs and upstream's is explicit.

- git mv preserves history.
- Updated every reference (docs/lx-* -> docs-lx/lx-*): README.md/.ru.md,
  SPECS/{003,004,005,009,020,README}, transport/wireguard/endpoint.go
  comments, lx-ci.yml, and lx-release.yml (the release-notes extractor +
  fallback URL now read docs-lx/lx-changelog.md).
- Fixed the now-relative links inside the moved files that pointed at
  upstream docs/ siblings: lx-config.md -> ../docs/configuration/outbound/
  urltest.md; lx-changelog.md -> ../docs/changelog.md (x2).

Verified: all relative + external links resolve, both workflows are valid
YAML, the release-notes awk path is docs-lx/, go vet clean on the touched
package. No release feature — folds into the next tag naturally.
2026-06-30 18:55:26 +03:00
Leadaxe c35ccd0ea7 fix(build): restore with_clash_api on desktop/CLI — drop is AAR-only
SPEC 014 dropped with_clash_api because LxBox (Android) drives the core
over the native libbox CommandClient, making the Clash REST server dead
weight in the AAR. But the drop landed in the shared Makefile.lx LX_TAGS,
which also feeds every desktop/CLI release build (mac/windows/linux-musl
via `make -s lx-print-tags`). A CLI binary has no CommandClient channel —
it is managed by external dashboards (yacd/MetaCubeXD) over the Clash REST
API — so every desktop release since rc.1 shipped with no way to manage
the core; a config with experimental.clash_api failed fast. CI stayed
green (lx-ci BASE_TAGS kept the tag), so it was invisible in CI.

Restore with_clash_api to the desktop LX_TAGS; leave build_libbox (AAR)
unchanged. The two tag sets now diverge by design: desktop = with Clash
API, AAR = without.

Verified: desktop binary builds with with_clash_api in Tags; `check`
accepts an experimental.clash_api config; the Clash REST server comes up
live (endpoints answer 401 security-middleware, not the stub's fail-fast).

Docs: Makefile.lx comment, SPEC 014 (§2/§3.1 scoped to AAR + new §3.4),
lx-release.yml tag comment + notes line, changelog rc.17.
2026-06-30 13:23:53 +03:00
Leadaxe ab29eb1bb0 docs(lx-changelog): rc.16 — SPEC 002 v2 full XHTTP param support 2026-06-30 01:59:57 +03:00
Leadaxe 6dc83fc109 Merge upstream/testing (bump version, fix linux ping) into lx-1.14 2026-06-30 01:57:50 +03:00
世界 b2d51f6ec3 Bump version 2026-06-29 11:43:26 +08:00
Leadaxe a26f2a6c3f docs: mark round_robin (SPEC 019) device-verified end to end
The rc.15 domain fix was confirmed on a real device: with the default
sticky_hash ["process","domain"] and no dest_ip workaround, browser traffic
spreads across the pool (on-device per-domain uniformity ~0.27 -> 0.95+).
Update README + lx-config.md status from "not yet device-verified" to
device-verified.
2026-06-29 02:43:41 +03:00
Leadaxe b28c689cb9 docs: document observability (SPEC 014-018) + round_robin (SPEC 019) across lx docs
The lx feature docs had drifted: README (en/ru) and docs/lx-config.md still said
"currently XHTTP + AWG2" and covered only SPEC 002/003/009 — the observability
layer (SPEC 014-018) and round_robin load balancing (SPEC 019) were undocumented
in the lx overview, and urltest.md still described the pre-rc.15 domain behaviour.

- docs/lx-config.md: new "## 3. round_robin load balancing" (mode/balancer,
  pool/pool_tolerance/sticky_hash, ["none"] sentinel + badjson-[] caveat, slot-hash
  binding, example, status) and "## 4. Observability (CommandClient extensions)"
  (URLTestOutbound/GetRules/GetGroups/GetOutbounds/GetPool/SubscribeDNSQueries +
  Connection.detourList, all behind with_lx_command); Validate&build -> ## 5.
- README.md / README.ru.md: broaden the stale "XHTTP + AWG2" framing; add feature
  rows for observability and round_robin with honest status.
- docs/configuration/outbound/urltest.md: reconcile sticky_hash "domain" with the
  rc.15 fix — domain reads metadata.Domain (survives domain->IP resolve), so it
  works for normal sniffed domain traffic, not only literal-IP destinations; the
  warning is reframed (domain works; dest_ip is an alternative).

Docs-only; no code change.
2026-06-29 02:23:49 +03:00
Leadaxe a531879e02 fix(SPEC 019 v2): three sticky/pool bugs found by device verification
Device verification of round_robin on a real 51-node pool surfaced three bugs,
all fixed here. Listed by impact.

1. sticky key 'domain' was always empty -> all traffic collapsed to one node.
   The router resolves a domain destination to an IP and overwrites
   metadata.Destination before a group's DialContext runs, so destination.Fqdn
   is empty when the balancer builds the key. stickyComponent("domain") read
   that empty Fqdn, so a single process's key was process+NUL for every site
   -> one fixed slot. On device this measured 28/1/1 across a 3-node pool
   (uniformity 0.27). Fix: read metadata.Domain (survives the resolve), fall
   back to destination.Fqdn only for a direct dial. After: spread 0.95+.

2. living pool nodes could change slot index during a health-check, moving
   sticky keys. balancePoolFirstLive compacted with a filtering append (a
   transiently-dead slot shifted every later live node left); planTolerantPool
   did delete(inPool, occupant) (an evicted-but-living node re-entered a later
   slot, cascading); manual URLTest rebuild ran the tolerant planner even at
   pool_tolerance==0. All now replace-in-slot (fixed-length copy(current), only
   dead/empty slots rewritten by index; dedicated planFirstLivePool for the
   tolerance==0 rebuild).

3. stickiness could not be disabled via sticky_hash: [] -- the config decoder
   (badjson.UnmarshallExcludedContext) re-marshals the struct and collapses an
   empty array to nil, indistinguishable from omitted, so the default always
   applied. Disabling now uses the explicit sentinel sticky_hash: ["none"].

Tests: domain-from-metadata + fallback, replace-in-slot survivor/cascade/
first-live regressions (fail against pre-fix code), ["none"] disable + []
defaults + none-mixed error. All green under -race; gofmt clean.
2026-06-28 21:48:31 +03:00
Leadaxe 50efd8f335 fix(SPEC 019 v2): balancer.pool 0 = default, not error (rc.14)
Desktop smoke-test of the rc.13 binary surfaced this: a Go int with omitempty can't tell
`pool: 0` from an omitted field, so `pool: 0` hit the `< 1` validation and rejected a
config that should have defaulted. Now pool 0/omitted → default 3; only a negative pool
errors. Added TestBalancerZeroPoolIsDefault; renamed the negative-pool test. SPEC_V2,
urltest.md, changelog rc.14 updated.

Verified on the rc.13 desktop binary: round_robin pool fill (pool_tolerance:0 tests only
pool-many nodes, >0 tests all), config fail-fast (balancer+least_test, unknown sticky_hash,
unknown mode, negative pool), and live routing through the group.
2026-06-28 18:11:55 +03:00
Leadaxe 5997b1812a lx(1.14): SPEC 019 v2 — round_robin pool, lazy health-check, slot-hash sticky, GetPool
Reworks urltest round_robin to scale to large node lists. v1 rotated over ALL live nodes,
which meant URL-testing every node each interval (unworkable at 1000 nodes). v2:

- Fixed-size pool of slots (balancer.pool, default 3). Slot indices never move; a
  replacement takes the exact slot it evicts. round_robin rotates only within the pool.
- Lazy health-check: pool_tolerance=0 tests no more nodes than needed to keep the pool
  full of live nodes, then stops; pool_tolerance>0 tests all and keeps the fastest with a
  per-slot eviction threshold. Dead pool node keeps its slot until a live replacement is
  found (pool never empties). A dial error never changes the pool — only the health-check.
- sticky = slot-hash (slot[hash(key)%pool], FNV-64a). Binds to a fixed slot index, so a
  living node keeps ALL its keys when other slots churn: strict zero reconnects, zero
  per-key state. Default sticky_hash ["process","domain"]; explicit [] disables.
- Removes v1 jumphash (broke on mid-list eviction), ttl_map, and least_connection (dropped
  from the roadmap — round_robin is statistically even).
- GetPool RPC: CommandClient.GetPool(tag) -> []PoolSlot{slot,tag,delay} so clients can show
  the N nodes actually in rotation. delay clamped 0->1 for live nodes; non-round_robin
  group -> empty. Additive proto/daemon/libbox, behind with_lx_command.

Config moved under a `balancer` object (breaking for the rc.11/12 round_robin shape; no
prod configs, tests only). least_test (default) is byte-for-byte unchanged.

Tests: newBalancer validation/defaults, rotation distribution, slot-hash stable +
living-node-keeps-keys-across-other-slot-churn, empty-key fixed slot, planTolerantPool
top-N / keep-in-tolerance / evict-beyond / dead-slot-replace. go build (+with_lx_command),
go test -race ./protocol/group/, gofmt all clean. Not yet device-verified.
2026-06-28 17:50:43 +03:00
Leadaxe feab497fe4 lx(1.14): SPEC 019 Now() cold-start fallback to Select()
Before the first URL-test fills the delay history, urltest's selectedOutbound* is
nil but traffic already flows via the Select() fallback (first usable outbound).
Now() returned "" in that window, so the UI showed no server while connections were
live. Now() now falls through to Select(tcp)/Select(udp) and reports the exact node
the next DialContext will pick — same source of truth as the dial path, not a guess.

Only least_test (default) affected; round_robin/ttlmap already report the last-picked
tag (lastSelected) and are untouched. Added TestSelectColdStartFallback /
TestSelectColdStartNoOutbounds. SPEC + changelog rc.12. go build (+with_lx_command),
go test -race ./protocol/group/, gofmt all clean.
2026-06-28 11:00:17 +03:00
Leadaxe 5954e50b58 docs(SPEC 019): rc.11 changelog — drop "not device-verified", note live run
The TEST_REPORT landed after the tag was cut, so the as-tagged notes still said
"not device-verified" and base alpha.35. Feature was live-verified on 5 vless nodes;
base is alpha.36 after the pre-rc merge. Published GitHub release notes edited to match.
2026-06-28 01:28:06 +03:00
Leadaxe 061b5f4cca docs(SPEC 019): add TEST_REPORT (live-verified) + dest_ip stickiness caveat
Live run on 5 vless nodes (3 instances, one per mode): round_robin rotates strictly
across the live set and skips dead nodes; both sticky strategies pin deterministically;
bad config is rejected at start; -race clean on units and live. Feature is now
device-verified, not just isolated.

The run surfaced a config caveat (not a bug, by design): dest_ip is empty until the
destination is resolved, so a sticky key of only source_ip/dest_ip/dest_port collapses
to "" for domain traffic and pins everything to one node. Documented in urltest.md —
use `domain` in `hash` for domain-based traffic.
2026-06-28 01:23:45 +03:00
Leadaxe ffa3b65427 lx(1.14): rename urltest_balance -> _lx suffix for CI gofmt coverage
The lx-ci gofmt-lint step only checks files matching the lx-owned glob
(_xhttp|_awg|_lx.go|_command_lx); the new SPEC 019 files fell outside it. Rename
to the _lx.go convention so CI gofmt-checks them, and fix the changelog reference.
No code change.
2026-06-28 01:15:58 +03:00
Leadaxe 645b8253cb Merge upstream/testing (v1.14.0-alpha.36) into lx-1.14
Pre-rc.11 sync. Upstream changes: darwin local DNS refactored to a raw
mDNSResponder call, iOS deb upload fix, version bump. No overlap with lx files
(protocol/group, option, constant untouched).
2026-06-28 01:13:25 +03:00
Leadaxe 5ebff914fc lx(1.14): SPEC 019 urltest mode + sticky load-balancing
Add a `mode` to the urltest group so it can distribute traffic instead of only
picking the lowest-delay node, with optional per-flow stickiness.

- mode: least_test (default, unchanged) | round_robin (rotate across live nodes)
  | least_connection (reserved, phase 2 — rejected at config time).
- round_robin selects once per connection over the tag-sorted live set (nodes with
  a fresh URL-test result supporting the network); UDP/QUIC sessions stay on one
  node; first usable outbound is the fallback when nothing is live. The legacy
  selectedOutbound* cache path is untouched — balancing is a separate branch in
  DialContext/ListenPacket.
- sticky {mode, timeout, cap, hash}: binds one flow to one node. hash components
  process|domain|source_ip|dest_ip|dest_port concatenate in order; absent -> "",
  all-empty key -> one fixed node (keyless flows never rotate). mode jumphash
  (default, stateless consistent hash — ~1/n remap on node-set change) or ttlmap
  (key->node table, lazy + ticker eviction, 2000 LRU cap, 10m TTL, dead-node re-pin).

Reuses the existing urltest health ticker/history as the single liveness source;
no new probing. Now() reports the last-picked tag in balanced modes.

Tests (go test -race, 15 cases): distribution, dead-node skip, all-dead fallback,
jumphash stability + empty-key fixed node, ttlmap stick/expire/cap/dead-repick,
key building, validation. The race detector caught a real bug in the sticky
sweeper (read t.ticker unlocked while close() nilled it) — fixed by passing the
channels into the goroutine, mirroring URLTestGroup.loopCheck.

Also folds the SPEC 016 connections-map mutex (ebf9cc07) into the rc.11 changelog
section, which had not yet shipped in a release.
2026-06-28 01:10:17 +03:00
世界 156c4f5ceb Bump version 2026-06-27 17:48:32 +08:00
Leadaxe 1e86fdd52b docs(release): runbook — check upstream drift + merge before any release tag
Codify the rule: before cutting any lx release/prerelease tag, check whether
upstream/testing moved ahead of our last merge and, by default, merge it in
first — then build/gofmt/lx-check, then changelog, then tag.

- docs/lx-release-runbook.md: pre-release gate checklist, drift-check commands,
  the manual `git merge upstream/testing` flow (replaces SPECS/004 auto-rebase
  while upstream is v1.14.*-alpha), conflict zones (.pb.go, wireguard-go submodule,
  build_libbox marker, observability files), and the one-liner sequence.
- SPECS/004 SPEC.md: pointer to the runbook + note that manual merge superseded
  auto-rebase on this branch.
2026-06-27 01:18:17 +03:00
Leadaxe 3e4c178339 lx(1.14): SPEC 018 — DNS server + outbound in stream, subscriber-gated
LxBox feedback: DnsQuery lacked which DNS server / outbound channel the query went
through. A DNS rule selects a server (matchDNS by action.Server), not an outbound;
the channel is the server's own detour, fixed at config time. Add to DnsQueryEvent:
- dnsServer/dnsServerType = transport.Tag()/Type() (transport is the Exchange param,
  so available on all emit paths incl. failures);
- outbound = the server's detour tag (TransportAdapter.OutboundTag() from
  DialerOptions.Detour), with a selector expanded to its live node via Now()
  server-side (like Connection.Detour), empty on cached/optimistic.

Also gate event construction on HasSubscribers(): with no profiler attached the DNS
hot path builds nothing (no event/answers/outbound lookup) — previously every
resolution built an event just to be dropped for lack of a listener. The Now()
resolution therefore never touches the hot path.

Wire: additive proto fields + OutboundTag() on DNSTransport (embedded adapter
satisfies it). libbox DnsQuery.DNSServer/DNSServerType/Outbound(). Changelog rc.10.
2026-06-27 00:42:29 +03:00
Leadaxe 26469ee657 fix(SPEC 018): attribute DNS queries + bare rdata (§180-2)
DNS attribution was empty (0/119 on device): TUN+DNS hijack returns on a fast-path
(route.go:91/226) BEFORE matchRule, and searchProcessInfo — which fills
metadata.ProcessInfo — lives inside matchRule (:416). So fast-path DNS (most DNS on
a VPN) reached the SubscribeDNSQueries emit with nil ProcessInfo. Fix: call
r.searchProcessInfo(ctx, &metadata) before both fast-path hijacks (stream+packet);
idempotent + cached, one lookup per flow. Corrects SPEC 018 пункт 3 (the earlier
'cached attribution correct' claim checked ctx consistency, not that ProcessInfo
was populated before the resolve).

Also: DnsAnswer.rdata was the full RR string ('google.com. 29 IN A 1.2.3.4'); strip
the header prefix so clients get the bare value ('1.2.3.4' / CNAME target).

No proto/wire change. LxBox §180 needs no client change. Changelog rc.9.
2026-06-26 20:32:50 +03:00
Leadaxe 0a8311cb92 fix(SPEC 018): dnstrack Manager registry key mismatch — DNS stream was dead (§180)
SubscribeDNSQueries returned Unimplemented on device and emitted nothing: the
dnstrack.Manager is registered via MustRegisterPtr (key *dnstrack.Manager) but
read via service.FromContext[*dnstrack.Manager] (key **dnstrack.Manager), so the
lookup always found nil. Server -> Unimplemented; emit sites -> silent drop.

Fix all three readers to service.PtrFromContext[dnstrack.Manager] (the pair of
MustRegisterPtr, as trafficManager does in daemon/instance.go). Verified the
manager resolves to the exact pointer box.go registered. No proto/wire change;
rc.7 contract intact. LxBox §180 needs no client change.

Changelog rc.8.
2026-06-26 19:34:46 +03:00
Leadaxe cffbfcbfce lx(1.14): SPEC 018 SubscribeDNSQueries — structured DNS-query stream
Hijacked DNS (the norm on an Android VPN) is answered before a connection becomes
a traffic tracker, so DNS queries never reach the connections stream — the only
egress was the text log, which carries no app attribution. Add common/dnstrack
(a Subscriber[QueryEvent] mirror of trafficcontrol) emitting one event per
resolution from dns/client.go, attributed via adapter.ContextFrom(ctx).ProcessInfo
(same ctx on cache-hit and miss, so cached queries are attributed too).

Failures are first-class: timeout/loopback/rejected-cached/SERVFAIL-reject emit
failed=true + error + rcode=-1 (no response) — without this the stream is blind to
DNS failures, the primary throttling signal. CNAME chains preserved: with
includeAnswers, each event carries the full response.Answer in wire order (CNAME
hops + final A/AAAA, not filtered to IPs).

Wire: rpc SubscribeDNSQueries(SubscribeDNSQueriesRequest) returns (stream
DnsQueryEvent) + DnsAnswer; event-driven server stream (no ticker); libbox
SubscribeDNSQueries(includeAnswers, handler). Tag-less core -> Unimplemented.
Detour/Chain and other streams unchanged.

Docs: SPECS/018, lx-changelog rc.7.
2026-06-26 16:26:09 +03:00
Leadaxe b8ff5c7836 docs(lx-changelog): rc.6 also carries upstream alpha.35 merge + device-verify notes 2026-06-26 15:00:06 +03:00
Leadaxe 7804bf9d85 Merge remote-tracking branch 'upstream/testing' into lx-1.14
# Conflicts:
#	box.go
#	cmd/internal/build_libbox/main.go
#	common/certificate/store.go
#	common/trafficcontrol/tracker.go
#	daemon/managed_service.pb.go
#	daemon/managed_service_grpc.pb.go
#	daemon/started_service.pb.go
#	daemon/started_service.proto
#	daemon/started_service_grpc.pb.go
#	docs/changelog.md
#	go.mod
#	go.sum
#	service/oomkiller/service.go
#	service/oomkiller/service_darwin.go
2026-06-26 14:27:59 +03:00
Leadaxe c12ee663b1 lx(1.14): SPEC 017 Connection.Detour — transport detour tail of final outbound
chain omits the final outbound's own detour by design (upstream loop only
unwinds OutboundGroup via Now() and breaks on the first non-group), so a node
detouring through e.g. WARP never shows in the routing chain. Add Detour
[]string to TrackerMetadata, unwound from the final outbound's Dependencies()
(= its detour for a non-group outbound), descending into groups via Now()
against the same atomic snapshot, with a seen-guard against cycles.

Wire: additive 'repeated string detourList = 23' on the Connection proto
message (hand-applied to keep the generated diff minimal — no toolchain churn),
mapped in connectionToProto, surfaced on libbox Connection as Detour()
StringIterator. Chain / Clash-API unchanged.

Docs: SPECS/017, lx-changelog rc.6.
2026-06-26 14:14:34 +03:00
Leadaxe 9c55f96aa9 lx(1.14): SPEC 015 §3.6 URLTestOutbound cancel-fix (ctx-bind) + docs
Parent the per-node delay test to the gRPC per-call ctx instead of the
long-lived boxService.ctx, so cancelling the call aborts the in-flight
dial before C.TCPTimeout without tearing down the connection. Restores
the granular per-node cancel the Clash API had implicitly via r.Context()
(there was never a cancelDelays endpoint).

Mass-cancel is unblocked client-side on the existing gomobile binding
via a separate ping CommandClient + Disconnect() (no native-surface
change, no server batch RPC) — closes the LxBox feedback.

Docs: SPEC 015 §3.6 (cancellation), SPEC 014 (#4240 deleted upstream →
seam-removal criterion switched to upstream-code), lx-changelog rc.5.
Ignore test/cache.db.
2026-06-26 11:03:14 +03:00
世界 ecc4776034 Bump version 2026-06-25 17:39:58 +08:00
世界 0794d645af Add iOS jailbreak release 2026-06-25 17:39:16 +08:00
世界 4d5c2a03d6 documentation: Add USB/IP server and client 2026-06-25 17:39:08 +08:00
世界 f4061770bb Fix remote control when Clash server is unavailable 2026-06-25 17:38:56 +08:00
世界 3035af688e Add dashboard support for API service 2026-06-25 17:38:56 +08:00
世界 95c37c138a Add sing-box API service 2026-06-25 17:38:53 +08:00
世界 dcbb8271f8 platform: Add tailscale device name and logout 2026-06-25 17:38:52 +08:00
世界 f18b01b7fe tailscale: Add tailssh server 2026-06-25 17:38:51 +08:00
世界 d0ef5c028d hysteria2: Add gecko obfs 2026-06-25 17:38:51 +08:00
世界 23a676ac8a tailscale: Revert dialer deprecation and remove control_http_client 2026-06-25 17:38:25 +08:00