let lib = import ; helperNames = [ "getRuntimePath" "getSopsKey" ]; validateLeaf = context: leaf: if builtins.isString leaf || builtins.isPath leaf then # String or path: file path (binary or single-value secret) leaf else if builtins.isAttrs leaf then # Object: must have 'file', may have 'keys' list and optional deployment metadata let _ = if leaf ? file && (builtins.isPath leaf.file || builtins.isString leaf.file) then null else throw "${context}.file must be a path or string."; __ = if !(leaf ? keys) || (builtins.isList leaf.keys && builtins.all builtins.isString leaf.keys) then null else throw "${context}.keys must be a list of strings when provided."; ___ = if !(leaf ? path) || builtins.isString leaf.path then null else throw "${context}.path must be a string when provided."; ____ = if !(leaf ? owner) || builtins.isString leaf.owner then null else throw "${context}.owner must be a string when provided."; _____ = if !(leaf ? group) || builtins.isString leaf.group then null else throw "${context}.group must be a string when provided."; ______ = if !(leaf ? mode) || builtins.isString leaf.mode then null else throw "${context}.mode must be a string when provided."; in leaf else throw "${context} must be a string, path, or an attrset with 'file' key."; validateTree = context: node: if builtins.isAttrs node then lib.mapAttrs (name: value: if lib.elem name helperNames then value else validateTree "${context}.${name}" value ) node else throw "${context} must be an attrset at non-leaf level."; getSecretsConfig = secretsConfig: let _ = if builtins.isAttrs secretsConfig then null else throw "config/secrets.nix must evaluate to an attrset."; __ = validateTree "config/secrets.nix" secretsConfig; in secretsConfig; in rec { inherit getSecretsConfig validateLeaf validateTree; }