Revert the NB_LAZY_CONN=false override on the harness client and proxy
containers: with the DNS-time lazy-connection warm-up in place, the
harness resolves the endpoint first, which wakes the proxy peer before
WaitProxyPeer polls for it. Running the suite with lazy connections on
is the point — it exercises the warm-up path end to end.
- Moonshot serves newer platform accounts exactly one model, kimi-k3:
K2-era ids and the kimi-latest alias return resource_not_found_error
on both API surfaces (verified live 2026-07-21). Drop kimi-k2-thinking
from the kimi_api catalog entry and the pricing defaults so the
dashboard doesn't advertise a model that 404s; grandfathered accounts
can still type K2 ids on the provider's model rows.
- Remove the temporary push trigger from agent-network-e2e.yml now that
the branch validated green (run #76); nightly + workflow_dispatch
remain.
- Remove CLAUDE.md from the repository.
- Use netip.Addr instead of string IPs in the local resolver's
PeerConnectivity and PeerActivator interfaces; extract record
addresses as netip.Addr (v4-mapped forms unmapped) and convert to
string only at the peer.Status boundary.
- Scope warm-up to match-only (non-authoritative) zones so the
synthesized private-service records keep warming while plain
peer-name lookups in the authoritative peer zone no longer wake
every idle peer.
- Parse NB_DNS_LAZY_WARMUP_TIMEOUT once in the resolver constructor
instead of on every request, and log invalid values.
- Stop reusing engine.syncMsgMux on the DNS path: ConnMgr.ActivatePeer
is now safe for concurrent use (lazy manager pointer guarded by a
dedicated RWMutex; the manager itself is internally synchronized),
so network-map processing no longer blocks DNS resolution.
- Add SetPeerActivator to the dns.Server interface (no-op on the mock)
and drop the *dns.DefaultServer type assertion in the engine.
- Drop WireGuard wording from dns/local comments; the layer is
transport-agnostic.
Tests: authoritative zones never trigger warm-up; warm-up timeout env
parsing (valid/invalid/non-positive); extractRecordAddr unmaps
v4-mapped record data; dnsPeerActivator skips connected/unknown/
conn-less peers, returns on connect, and releases at the budget when
the peer stays idle; ConnMgr.ActivatePeer races the manager lifecycle
cleanly under -race.
The Moonshot platform serves this account exactly one model — kimi-k3.
kimi-k2-thinking and the kimi-latest alias both return
resource_not_found_error on either API surface, so two concurrent Kimi
provider records would claim the same model and route ambiguously
(the router's path-prefix tiebreak needs the client to author the
/anthropic prefix, which the standard wire shapes don't). Keep the
flagship Claude Code path — kimi-k3 via /anthropic, green in run #74 —
as the live scenario; the OpenAI wire shape stays covered by the other
chat-shaped matrix providers and passed with kimi-k3 in run #73.
## Describe your changes
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [x] Is it a bug fix
- [ ] Is a typo/documentation fix
- [ ] Is a feature enhancement
- [ ] It is a refactor
- [ ] Created tests that fail without the change (if possible)
- [ ] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— **OR** I have discussed it with the NetBird team beforehand (link the
issue / Slack thread in the description). See
[CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first).
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* SSO browser-login popups now open centered on the display where the
cursor is located, and they recenter correctly on subsequent opens.
* Programmatic cleanup no longer triggers “login canceled” behavior;
cancel is emitted only when the user closes the active popup.
* **New Features**
* Added a streamlined “close renewal flow” action that tears down the
session-renewal UI by closing both the login and session-expiration
popups.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kimi-k2-thinking returns resource_not_found_error on both Moonshot
surfaces for this account — K2-era models aren't served to newer
platform accounts — so the OpenAI-shape case rides the always-available
kimi-latest alias instead. kimi-k3 stays on the Anthropic shape, which
passed in run #74. Model strings remain distinct for routing.
Moonshot's Anthropic-compatible /anthropic surface only serves the
current coding flagship: requesting kimi-k2-thinking there returns
resource_not_found_error ('Not found the model kimi-k2-thinking or
Permission denied'), while kimi-k3 works — it's the model Moonshot's
own Claude Code guide configures. Swap the pairing: kimi-k3 rides the
Anthropic shape and kimi-k2-thinking the OpenAI shape (which serves
every platform model). Model strings stay distinct across the two
provider records, keeping routing unambiguous.
The region-prefix fix wasn't sufficient: Bedrock ids also carry a
date/version suffix (…-20251001-v1:0), and AWS rejects the bare form
with 'The provided model identifier is invalid' regardless of region.
Send the id exactly as AWS issues it and mirror the proxy's
NormalizeBedrockModel (prefix + version-suffix strip, not importable
from here) when deriving the guardrail allowlist entry — which is also
precisely the round-trip the normalization change in 82fdfa8 exists to
handle.
The matrix hardcoded the us. cross-region inference profile while the
upstream host follows AWS_REGION, so any non-US region made Bedrock
reject every request with 'The provided model identifier is invalid' —
including the allowlisted call in TestModelAllowlistEnforced, which
asserts a 200. Derive the profile prefix (us/eu/apac/us-gov) from the
region, default the region to eu-central-1 to match the CI credentials,
and strip whichever prefix was chosen when building the guardrail
allowlist.
The nightly agent-network e2e has been red for ~6 days: every scenario
that calls WaitProxyPeer times out with 'client did not see the proxy
peer'. The proxy's overlay peer comes up fine, but the client now puts
it into the lazy connection manager (server-driven feature flag), so no
connection is dialed until traffic flows — and WaitProxyPeer polls
'netbird status' for a Connected peer before sending any traffic.
Set NB_LAZY_CONN=false on the harness client and proxy containers so
the tunnel dials eagerly and status reflects it, restoring the
harness's readiness signal.
724c6a0 introduced the top-level trustedproxy package and the proxy
imports it, but proxy/Dockerfile.multistage enumerates copied
directories and was not updated, so the agent-network e2e harness
failed to build the proxy image (module provides no such package).
The combined and client images COPY the whole tree and are unaffected.
## Describe your changes
Add more information about the current client and GUI versions if the
user is running an older client.
Update the URL to download the latest RC if the user is running any RC
build.
<img width="348" height="497" alt="CleanShot 2026-07-10 at 15 11 54"
src="https://github.com/user-attachments/assets/2579f5f3-5056-4184-96bb-9f93d5860328"
/>
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [ ] Is it a bug fix
- [ ] Is a typo/documentation fix
- [x] Is a feature enhancement
- [ ] It is a refactor
- [ ] Created tests that fail without the change (if possible)
- [ ] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— **OR** I have discussed it with the NetBird team beforehand (link the
issue / Slack thread in the description). See
[CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first).
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
## Describe your changes
Native AWS Bedrock requests carry the model in the URL path as a
cross-region inference-profile id (e.g.
`us.anthropic.claude-haiku-4-5`). The request parser normalizes that to
the catalog key (`anthropic.claude-haiku-4-5`) before the router runs,
but the router matched it against the operator's registered provider
models with exact string equality. So a Bedrock provider registered with
the id Bedrock actually uses (`us.anthropic…`) never matched a
normalized request → the request denied with
`llm_policy.model_not_routable` ("no provider configured for model …").
Only a provider registered with the already-stripped catalog id worked,
which is not how Bedrock ids appear.
Fix: introduce a single shared `llm.NormalizeBedrockModel` (the same
ARN/region-prefix/version-suffix stripping the parser already does) and,
in the router's `routeClaimsModel`, normalize a **Bedrock** route's
candidate models before comparing. Now a Bedrock provider registered
with either the raw inference-profile id or the normalized catalog id
matches the request. Non-Bedrock routes keep exact matching.
Surfaced by the new native-Bedrock e2e (`WireBedrock`,
`/model/{id}/invoke`); the old e2e used the Anthropic body shape, which
never normalized either side and so hid this.
The request parser keeps its own identical normalizer for now;
de-duplicating it onto `llm.NormalizeBedrockModel` is a trivial
follow-up.
## Issue ticket number and link
N/A — follow-up to the Agent Network Bedrock support / model-allowlist
work.
## Stack
<!-- branch-stack -->
### Checklist
- [x] Is it a bug fix
- [ ] Is a typo/documentation fix
- [ ] Is a feature enhancement
- [ ] It is a refactor
- [x] Created tests that fail without the change (if possible)
- [x] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— **OR** I have discussed it with the NetBird team beforehand (link the
issue / Slack thread in the description). See
[CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first).
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
Internal routing correctness fix; no user-facing surface change.
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
## Tests
- `proxy/internal/llm`: `NormalizeBedrockModel` unit cases (region
prefixes, version suffixes, ARN).
- `proxy/internal/middleware/builtin/llm_router`: `routeClaimsModel`
matches a Bedrock route registered with the raw `us.anthropic…` id
against a normalized request model; non-Bedrock routes still match
exactly.
Note: full through-tunnel e2e verification of this (the native-Bedrock
`TestProvidersMatrix/bedrock`) also needs the DNS lazy-connection
warm-up (separate PR) to get the client past the proxy-peer gate; they
converge once both land.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved Amazon Bedrock model matching across ARN formats, regional
prefixes, and version or throughput suffixes.
* Bedrock routes now correctly match equivalent model identifiers even
when requests and route configurations use different formats.
* Non-Bedrock model matching remains exact.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Gated on KIMI_TOKEN (CI: E2E_KIMI_TOKEN, a Moonshot platform key), like
the other provider credentials — the matrix skips Kimi when unset. Two
cases cover Moonshot's two wire shapes through the kimi_api catalog
entry: OpenAI Chat Completions against the bare host with kimi-k3, and
the Anthropic Messages API against the /anthropic path prefix with
kimi-k2-thinking, keeping model->provider routing unambiguous while
both records are enabled.
Adds a first-class kimi_api catalog entry so operators can govern Kimi K3
and K2 Thinking traffic through the Agent Network proxy instead of riding
the generic custom/vllm entry.
ParserID is left empty so the proxy's URL sniffer dispatches both body
shapes Moonshot serves on the same host and key: the OpenAI-compatible
/v1/chat/completions endpoint and the Anthropic-compatible
/anthropic/v1/messages endpoint that Moonshot's official Claude Code
setup uses (same pattern as the Bifrost gateway entry).
Pricing defaults cover both parser surfaces, including the kimi-k3[1m]
model id some Claude Code guides use for the 1M-context alias, so cost
metering doesn't silently skip those requests.
The dashboard's PROVIDER_CATALOG needs a matching entry (separate repo).
## Describe your changes
Adds a Japanese (ja) locale for the desktop UI, following the procedure
in `client/ui/i18n/TRANSLATING.md`.
- New `client/ui/i18n/locales/ja/common.json` — all 441 keys from the
`en` source bundle, `message` only, same key order.
- Registered in `client/ui/i18n/locales/_index.json`: `{"code": "ja",
"displayName": "日本語", "englishName": "Japanese"}`.
Translation notes:
- Placeholders (`{version}`, `{count}`, `{name}`, `{remaining}`, ...),
`\n`, trailing `…`/`...`, the leading space in
`notify.update.enforcedSuffix`, and the `<docs>…</docs>` inline-link
tags are all preserved verbatim.
- Brands kept as-is: NetBird, WireGuard® (® preserved), Rosenpass,
GitHub, NetBird Cloud. Acronyms kept: SSO, DNS, IP/IPv6, ACL, SSH, JWT,
TTL, SFTP, MTU, PSK, LAN, P2P, ICE, IdP.
- Formal register (です・ます); short labels for buttons/tray; quoted UI
labels use Japanese brackets 「」.
No code changes are required: the React frontend auto-loads every
`locales/*/common.json` via `import.meta.glob`, the tray/Go side embeds
the tree via `//go:embed all:i18n/locales`, and the language picker
lists whatever `_index.json` declares.
### Verification
- `go test ./client/ui/i18n/` passes.
- JSON valid; key set and order identical to `en`; no `description`
fields; no empty messages; placeholder/`\n` counts match `en`.
- Built the Windows UI and confirmed the General, Network, Security, and
Troubleshooting settings tabs plus the main window render correctly in
Japanese (language picker shows "日本語 (Japanese)"), with no text
truncation, overflow, or leaked placeholders.
## Issue ticket number and link
N/A
## Stack
<!-- branch-stack -->
### Checklist
- [ ] Is it a bug fix
- [ ] Is a typo/documentation fix
- [x] Is a feature enhancement
- [ ] It is a refactor
- [ ] Created tests that fail without the change (if possible)
- [x] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— adding a shipped UI locale is the documented extension path in
`client/ui/i18n/TRANSLATING.md`.
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change — UI translation
strings only; no user-facing product docs are affected.
### Docs PR URL (required if "docs added" is checked)
N/A
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6790"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with Codesmith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1786742881&installation_id=146802194&pr_number=6790&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6790&signature=a1dcd7faf63ae10071ca2da3639b4daf6505eeb0258790e622222e742a8ebcb6"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with Codesmith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>/codesmith</code> with what you
need. Autofix is disabled.</sup>
<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added Japanese as a supported interface language.
* **Localization**
* Provided full Japanese translations for the UI, covering navigation,
settings, onboarding, desktop/tray notifications, connection and status
messaging, troubleshooting, update/about screens, and
authentication/error dialogs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Eduard Gert <kontakt@eduardgert.de>
## Describe your changes
When loadStateFile fails to unmarshal the state file, log whether the
file is empty (0 bytes) or has malformed content, including the byte
size.
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [ ] Is it a bug fix
- [ ] Is a typo/documentation fix
- [x] Is a feature enhancement
- [ ] It is a refactor
- [ ] Created tests that fail without the change (if possible)
- [ ] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— **OR** I have discussed it with the NetBird team beforehand (link the
issue / Slack thread in the description). See
[CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first).
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
### Docs PR URL (required if "docs added" is checked)
aste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved state-file loading warnings by distinguishing empty files
from files containing malformed content.
* Preserved existing recovery behavior for corrupted state files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Describe your changes
`isValidAccessToken` only decodes the JWT payload and checks the
audience
claim, but its name suggested full token validation. Rename it to
`validateTokenAudience` and document what it does: a client-side
audience/shape
check on a token just obtained from the IdP over TLS. Token authenticity
is
enforced server-side by the management server, which verifies the
signature
against the IdP's JWKS (`shared/auth/jwt/validator.go`) on every
request.
Also harden the parser: a non-empty token lacking the three-part JWT
structure
caused an index-out-of-range panic (`strings.Split(token, ".")[1]`); the
shape
is now validated first. `parseEmailFromIDToken` is documented as
best-effort UX
data (login hint/display), never used for authorization. Added tests for
audience matching, malformed tokens, and the panic regression.
Changes:
- Rename `isValidAccessToken` → `validateTokenAudience`; document that
it does
not verify the signature and that authenticity is enforced server-side.
- Fix an index-out-of-range panic on a non-empty token lacking JWT
structure
(`strings.Split(token, ".")[1]`) by validating the three-part shape
first.
- Document `parseEmailFromIDToken` as best-effort/unverified, used only
for the
login-hint/display UX, never for an authorization decision.
- Add `util_test.go` covering audience matching (string and array),
missing
audience, malformed payloads, and the panic regression.
## Issue ticket number and link
Internal cleanup: rename a misleadingly-named client-side helper and
harden JWT
parsing against malformed input (`client/internal/auth/util.go`).
## Stack
- `0.74.7-branch` - ⚠️ No PR associated with branch <!--
branch-stack -->
- \#6806 :point\_left:
### Checklist
- [x] Is it a bug fix
- [ ] Is a typo/documentation fix
- [ ] Is a feature enhancement
- [ ] It is a refactor
- [x] Created tests that fail without the change (if possible)
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
Internal client-side helper rename plus a panic hardening fix. No public
API,
gRPC, CLI/service flag, or configuration change; token authenticity
enforcement
(server-side JWKS verification) is unchanged.
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from <https://github.com/netbirdio/docs> here:
N/A
<!-- codesmith:footer -->
***
<a
href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6806"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with Codesmith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1786811124&installation_id=146802194&pr_number=6806&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6806&signature=fe45ce9f6df46a609594f84037aaab2a21893621f29d2be48d7f8b347c3c8776"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with Codesmith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>/codesmith</code> with what you
need. Autofix is disabled.</sup>
<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Improved access-token audience validation during device and PKCE
authentication flows.
- Malformed tokens now return clear validation errors instead of risking
runtime failures.
- Added support for validating both string and array audience claims.
- **Tests**
- Added coverage for malformed tokens, invalid claims, missing
audiences, and panic prevention.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Describe your changes
Validate peer-supplied FQDN and hostname before they are written into
the
generated NetBird SSH client config (`client/ssh/config/manager.go`).
These
values originate from remote peers and were previously written verbatim
into
the config; malformed values (e.g. containing unexpected characters)
could
produce a broken or unintended config. FQDN/hostname are now checked
with
`domain.IsValidDomainNoWildcard`, and invalid, non-empty values are
dropped
with a warning. IPs are unaffected (already validated `netip.Addr`).
Added a
test covering malformed hostnames.
## Issue ticket number and link
Internal input-validation hardening for peer-supplied hostnames in the
generated SSH client config (`client/ssh/config/manager.go`).
## Stack
- \#6726 <!-- branch-stack -->
- \#6805 :point\_left:
### Checklist
- [x] Is it a bug fix
- [ ] Is a typo/documentation fix
- [ ] Is a feature enhancement
- [ ] It is a refactor
- [x] Created tests that fail without the change (if possible)
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
Internal client SSH config generation. No public API, gRPC, CLI/service
flag,
or configuration change — only input validation on peer-supplied
hostnames
before they are written to the generated ssh\_config.
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from <https://github.com/netbirdio/docs> here:
N/A
generateFreePort used netip.MustParseAddrPort on the OS-produced
LocalAddr().String(), which panics on address strings that don't parse.
Eliminate the parsing entirely by reading the port from the concrete
*net.UDPAddr that net.ListenUDP returns, and construct the bind address
directly. The probe listener is bound with udp4 so only an IPv4 wildcard
address is ever used.
## Describe your changes
## Issue ticket number and link
## Stack
<!-- branch-stack -->
### Checklist
- [x] Is it a bug fix
- [ ] Is a typo/documentation fix
- [ ] Is a feature enhancement
- [ ] It is a refactor
- [ ] Created tests that fail without the change (if possible)
- [ ] This change does **not** modify the public API, gRPC protocols,
functionality behavior, CLI / service flags, or introduce a new feature
— **OR** I have discussed it with the NetBird team beforehand (link the
issue / Slack thread in the description). See
[CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first).
> By submitting this pull request, you confirm that you have read and
agree to the terms of the [Contributor License
Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md).
## Documentation
Select exactly one:
- [ ] I added/updated documentation for this change
- [x] Documentation is **not needed** for this change (explain why)
### Docs PR URL (required if "docs added" is checked)
Paste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary by CodeRabbit
* **Bug Fixes**
* Improved reliability when selecting an ephemeral UDP port.
* Avoided potential failures when determining the assigned port.
* Preserved existing error handling and diagnostic logging for listener
operations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->