A policy that enforces a management URL refuses any SetConfig or Login whose
URL differs from it. The comparison normalized only the default port, so
three ways of writing the very endpoint the policy names were reported as
conflicts:
policy https://mgmt.example.com vs https://mgmt.example.com/ refused
https://MGMT.example.com refused
https://mgmt.example.com:0443 refused
For an MDM-managed deployment whose stored or command-line URL is spelled
differently from the policy's value, that means every settings update is
refused with an MDMManagedFieldsViolation naming a field the caller did not
change. `netbird up --management-url https://MGMT.example.com` reproduces it.
The rules now live in util.SameServiceURL, and ConflictURL delegates: scheme
and host compared case-insensitively, the effective port normalized
numerically, a trailing slash ignored, and a path otherwise still part of the
identity so /other remains a divergence. Unparseable input falls back to
string equality.
util rather than either caller, because comparing two service URLs is
neither device management nor profile storage, and more than one place does
it: an MDM-enforced management URL against a requested one here, a stored
profile URL against a command-line one in profilemanager and the SSH gate.
Every copy of these rules that drifts turns an equivalent URL into a refused
request, which is how this one arose.
CanonicalURL is left alone: besides comparison it is the canonical value
handed to mdm.Restrictions and to the Android and iOS Preferences getters,
and normalizing what those return is a separate decision.