let lib = import ; net = import ../config/network.nix; end = import ../config/endpoints.nix; endpointValidation = import ../validation/endpoints.nix; networkDevicesValidation = import ../validation/network_devices.nix; localDomain = if net ? local_domain && builtins.isString net.local_domain && net.local_domain != "" then net.local_domain else throw "config/network.nix must define local_domain as a non-empty string."; localIngressIp = if net ? devices && builtins.isAttrs net.devices && net.devices ? self && net.devices.self ? ip && builtins.isString net.devices.self.ip then net.devices.self.ip else throw "config/network.nix must define devices.self.ip as local ingress IP for local endpoint DNS mapping."; endpoints = endpointValidation.validateEndpointsShape end; devices = networkDevicesValidation.getDevices net; localDevices = networkDevicesValidation.getLocalDevices devices; matchesLocalDomain = domain: domain == localDomain || lib.hasSuffix ".${localDomain}" domain; deviceMappings = builtins.listToAttrs (lib.mapAttrsToList (name: device: { name = "${name}.${localDomain}"; value = device.ip; }) localDevices); localEndpointDomains = lib.unique (map (endpoint: endpoint.domain) (lib.filter (endpoint: matchesLocalDomain endpoint.domain) endpoints)); endpointMappings = builtins.listToAttrs (map (domain: { name = domain; value = localIngressIp; }) localEndpointDomains); mergedMappings = deviceMappings // endpointMappings; _localEndpointConflicts = map (domain: if deviceMappings ? ${domain} && deviceMappings.${domain} != endpointMappings.${domain} then throw "DNS mapping conflict for '${domain}' between device-derived and endpoint-derived values." else null ) (builtins.attrNames endpointMappings); in rec { dnsMappings = mergedMappings; }