agent_nodes gains probe_only; getConfig always serves the flag and withholds the sing-box payload (null config, empty hash) for flagged nodes while probe tasks, fast interval, stat iface and update intents ride as usual. The agent gates both core branches when the local agent.json preset or the master flag is on, retires a running core once (best-effort tail flush, switchover bookkeeping untouched so turning the flag off self-heals through the existing hash-current-but-not-running path), and makes the traffic cycle an explicit no-op. Panel: node create/update accept probeOnly, the node view overlays it from the binding, the node form gains a switch (carried into the generated install command), the list shows a probe-only tag in the core-version cell, and install-agent.sh --probe-only writes the preset, skips the core download/self-check and inherits the flag on no-arg reruns.
- 0: sing-box gen overrides fragment listen/port from the inbound row
(empty listen -> "::"), Update/Add recompute the stored fragment;
non-loopback E2E against the real core binary.
- 1: agent fetches the sing-box core from the Gitea release when
missing, self-checks it, and only then latches the switch.
- 2: node list shows the sing-box core version (heartbeat field,
persisted on the node row), xray version as fallback.
- 3: public-page fallback returns 404 to anonymous visitors when the
page is disabled.
- 4: settings restart hint bar removed, dead i18n keys cleaned.
- 5: two PUT calls missing JSON headers fixed (audit: only those two),
batch probe-task creation endpoint + UI.
- 6: cf-probe retirement card and coverage pipeline removed.
- 7: generated vless links no longer carry spx (panel export + sub);
parser still accepts spx; golden fixtures updated.
- probe batch: dedicated probe settings tab (public-page settings,
tasks, per-node meta), retention_days editable, per-node traffic
calibration + stat-interface pinning, runtime metrics split into a
lightweight fast report (default 3s, 1-60s adjustable).
- 8: sing-box core processes start with GOMEMLIMIT=32MiB, GOGC=50.
- 9: dead /getTwoFactorEnable docs entries removed (frontend call and
contract entry already gone at base; verified by grep).
1. per-client links (LinkProvider.LinksForClient) now apply the
inbound's managed Host records with the same precedence as
subscriptions and export-all (host endpoints after fallback
projection); zero-host inbounds keep the legacy output.
2. agent node writes no longer store the form placeholder
address='agent', port=2053: CreateFromRequest/UpdateFromRequest
sanitize it to the node's resolved agent address (update) or
empty (create / unreported), port 0; normalize gains a lenient
endpoint mode for agent writes only.
3. runtime Remote.baseURL refuses the legacy 'agent' placeholder
with a clear no-panel-endpoint error instead of splicing it into
a dialable https://agent:2053 URL.
NodeView carried only the category counts, so the nodes page chips
could hover to nothing but the category title. GetAll/recountByGuid
now emit online/active/disabled/depleted email lists from the same
bucketing pass as the counts (statuses gain the client email;
the online list is the counted set), and the chips pop the list
over with the inbounds page's popover pattern.
NAT'd agents (cloud 1:1 EIP) only ever report their private
interface address in heartbeat telemetry, so the node list showed
an unusable RFC1918 address. The master now records the source
address of every authenticated agent request (CF-Connecting-IP,
else first X-Forwarded-For hop, else RemoteAddr; change-only
writes) on the agent row as seen_ipv4/seen_ipv6, and the node
list resolves the displayed pair via service.ResolveAgentAddresses:
public telemetry wins, else a public observed source, else the
reported address as-is. CGNAT 100.64/10 observed addresses are
never promoted. Telemetry values are kept verbatim; resolution
is read-time only, and agents need no changes.
- nodes: port node-type (traditional/agent) picker back from web-src into
the embedded frontend; backend annotates NodeView.nodeType from
agent_nodes bindings; fix agent-node update path (skip reachability
probe and apiToken requirement for agent-managed nodes); restore i18n
keys in all 13 locales; install command now uses the Gitea mirror
- jobs: expire agent-bound nodes whose agent_nodes.last_seen is older
than max(3x heartbeat interval, 120s) = 180s; last_seen=0 (never
registered) is left untouched; transitions reuse UpdateHeartbeat +
node event broadcast
- config: GetBaseVersion honors ldflags-injected buildVersion; release
builds inject 3.7.0-agent.1 so the panel no longer reports a phantom
update against the Gitea release tag
- logger/server: remove the three log viewers (panel/xray/amneziawg),
their API endpoints and the 10240-entry in-memory log buffer; file
logging via lumberjack unchanged; tests assert via a new optional
logger hook instead of the removed buffer
- server: remove system history and xray metrics modules end to end
(endpoints, sampling appends in RefreshStatus, per-minute persist
cron, gob snapshot/restore, XrayMetricsService); realtime status and
per-node history are untouched
- settings: subPort may be 0/unset - subscription links are generated
without a port while the subscription service keeps binding the
default 2096; the settings form declares the cleared state via
onNumber's new onClear option instead of snapping back to 1