# Pure helpers: catalog → NixOS/HM/SSH shapes (`self.lib.usersMerge lib`). { ... }: { flake.lib.usersMerge = lib: let userHm = user: user.homeManager or { }; userSsh = user: user.ssh or { }; in rec { resolveHomeManagerModule = moduleSpec: let t = builtins.typeOf moduleSpec; in if t == "path" || t == "string" then import moduleSpec else moduleSpec; selectedUsersAttr = { catalog, enabled, hostOverrides }: lib.listToAttrs ( map (name: { inherit name; value = lib.recursiveUpdate catalog.${name} (hostOverrides.${name} or { }); }) enabled ); missingEnabledNames = catalog: enabled: builtins.filter (name: !(builtins.hasAttr name catalog)) enabled; strayHomeUserKeys = homeUsers: enabled: builtins.filter (k: !(builtins.elem k enabled)) (builtins.attrNames homeUsers); mkNixosUser = name: user: { isNormalUser = user.isNormalUser or true; description = user.description or name; extraGroups = user.extraGroups or [ ]; } // lib.optionalAttrs (user ? hashedPasswordFile && user.hashedPasswordFile != null) { hashedPasswordFile = user.hashedPasswordFile; }; hmWiredNames = selectedUsers: lib.attrNames ( lib.filterAttrs (_: user: let hm = userHm user; in (hm.enable or false) && (hm.module or null) != null ) selectedUsers ); rbwOutboundSnippet = name: user: let outboundCfg = ((userSsh user).outbound or { }).rbw or { }; in lib.mkIf (outboundCfg.enable or false) { chiasson.ssh.outbound.rbw.enable = true; chiasson.ssh.outbound.rbw.user = name; chiasson.ssh.outbound.rbw.hosts = if (outboundCfg.hosts or "all") == "all" then [ "all" ] else outboundCfg.hosts; }; mkHmUserModule = { name, user, hostExtraModules }: let hm = userHm user; hmModule = resolveHomeManagerModule hm.module; in lib.mkMerge ( [ hmModule (rbwOutboundSnippet name user) ] ++ (hm.extraModules or [ ]) ++ hostExtraModules ); inboundAuthorizedOrNull = user: let inboundCfg = (userSsh user).inbound or { }; in if !(inboundCfg.enable or false) then null else if (inboundCfg.authorizedHosts or "all") == "all" then "all" else inboundCfg.authorizedHosts; inboundHostsAttr = selectedUsers: lib.pipe selectedUsers [ (lib.mapAttrs (_: inboundAuthorizedOrNull)) (lib.filterAttrs (_: v: v != null)) ]; }; }