NXX 0.4.0 build information

Prerequisites: Go 1.26.6; Python 3 for prepare.py; .NET SDK 10.0.401 and NSIS
for Windows; Xcode/Swift for macOS. Preserve go.mod and go.sum. New build hosts
need dependency downloads. Set CGO_ENABLED=0 and GOTOOLCHAIN=go1.26.6 for Go.
The included engine is based on Tailscale 1.102.4, upstream revision
bbcd7d1fc2054b9189ebc1531acf74bd880ca0c8. Its NetExperts patches are applied.

Go components
-------------
Use prepare.py shared for Windows/Linux/FreeBSD, or prepare.py mac for macOS.
Run from the prepared directory:
  go test -mod=readonly ./cmd/private-network ./cmd/sdn-agent ./cmd/sdn-migrate ./internal/migration
  go build -mod=readonly -buildvcs=false -trimpath -ldflags "-s -w" -o artifacts/netexperts-private-network ./cmd/private-network
  go build -mod=readonly -buildvcs=false -trimpath -ldflags "-s -w" -o artifacts/netexperts-network-agent ./cmd/sdn-agent
Set GOOS/GOARCH for the intended target: windows/amd64, linux/amd64,
freebsd/amd64, darwin/amd64 or darwin/arm64. Run tests on their native OS.

From upstream/tailscale, build the 0.4 CLI with:
  go build -mod=readonly -buildvcs=false -trimpath -tags ts_omit_clientupdate -ldflags "-s -w -X tailscale.com/version.longStamp=1.102.4-netexperts.0.4.0 -X tailscale.com/version.shortStamp=1.102.4 -X tailscale.com/version.gitCommitStamp=bbcd7d1fc2054b9189ebc1531acf74bd880ca0c8" -o ../../artifacts/nxx ./cmd/nxx
The retained networking engine was built from ./cmd/tailscaled with the same
flags except longStamp=1.102.4-netexperts.0.2.0. Its version is intentionally
different from the 0.4 CLI. Preserve the matching engine/CLI pair.

Windows
-------
Build the helper as NetExpertsSDN.Enrol.exe, agent as NetExpertsSDN.Agent.exe,
engine as NetExpertsSDN.Engine.exe and CLI as nxx.exe. Also build:
  go build -mod=readonly -buildvcs=false -trimpath -ldflags "-s -w" -o artifacts/NetExpertsSDN.Migrate.exe ./cmd/sdn-migrate
Publish the WPF app:
  dotnet publish desktop/NetExpertsSDN/NetExpertsSDN.csproj -c Release -r win-x64 --self-contained true -o artifacts/windows-x64
The signed release used -p:NxxSignedRelease=true; omit that property for an
unsigned local build. Put the Go executables, a tailscale.exe copy of nxx.exe,
the official Wintun 0.14.1 x64 driver and component Licenses directory in the
same output directory. Review installer/NetExpertsSDN.nsi for the complete
payload, then run makensis NetExpertsSDN.nsi from installer/. Signing uses
separate credentials and is not part of the source distribution.

macOS Universal Binary
----------------------
The GUI and service require macOS 13. Build each for arm64-apple-macos13.0 and
x86_64-apple-macos13.0 with the installed MacOSX SDK:
  swiftc -sdk SDK -parse-as-library -O -target TARGET macos/Shared.swift macos/App.swift -o NetExpertsPrivateNetwork
  swiftc -sdk SDK -parse-as-library -import-objc-header macos/Membership.h -O -target TARGET macos/Shared.swift macos/Service.swift -o nxx-service
Combine matching slices with lipo. Package the Swift executables and Go
engine/agent/CLI/helpers into the application bundle. The release uses
Developer ID signing and notarisation, whose credentials are not included.
Swift regression tests use -D NXX_TESTING with APITests.swift (App.swift) or
Tests.swift/ManualTests.swift (Service.swift). Manual installation tests need
an isolated administrator-owned test location.

Linux and FreeBSD
----------------
Build the matching Go targets and include installer/unix-install.sh,
docs/man/nxx.1 and licence notices. The website's DEB, RPM and FreeBSD PKG
installers wrap these binaries with the appropriate service definitions.
Native package recipes are in packaging/. They require dpkg-deb/rpmbuild
on Linux and pkg on FreeBSD, with the matching release payload as input.
Signing services and credentials are not included.

Mac build 11 keeps application version 0.4.0. The service uses the macOS
Directory Services membership API to recognise local administrators. Include
-import-objc-header macos/Membership.h when compiling Service.swift, including
its tests. Run Tests with NXX_TEST_ADMIN_UID set to a real non-root Mac
administrator UID. Root, nobody and unknown UID cases are also checked.
The GUI and Go networking executables are retained from build 10.

Mac build 12 keeps version 0.4.0 and all build11 networking/service executables.
Package macos/LaunchDaemon.plist as
Contents/Library/LaunchDaemons/au.com.netexperts.private-network.service.plist.
It uses ProcessType Standard, matching normal upstream daemon scheduling.
Compile macos/ServiceRegistration.swift for both targets using the same Swift
SDK/flags, combine the slices, and package as Contents/MacOS/nxx-service-registration.
Sign it with identifier au.com.netexperts.private-network.registration and the
app team before sealing and notarizing the containing app. Its refresh command
requires root, the installed /Applications app and an already-approved service.
It uses ServiceManagement unregister/register to update launchd settings while
retaining device state. Existing installations need this registration refresh
or a reboot for the new launchd classification; a signal-only restart is not
sufficient. If macOS requests background approval, use System Settings; do not
reset its approval database or bypass the approval.
