Skip to content

den.policies

See Policies for conceptual background.

Type: lazyAttrsOf policyFunction

A registry of named policies. Each entry is a function from context to a list of policy effects. The module system wraps bare functions into { __isPolicy = true; name; fn; } records automatically.

den.policies.my-policy = { host, ... }: [
(policy.resolve { enriched = true; })
];

Declaring a policy here only registers it. Activation happens via includes — see Activation.

All constructors are accessed via den.lib.policy. Policies return lists of these effects.

Create a new scope with bindings merged into the current context.

policy.resolve { myFlag = true; }

Variants:

  • policy.resolve.shared bindings — shared (non-isolated) fan-out
  • policy.resolve.to kind bindings — target a specific entity kind
  • policy.resolve.withIncludes includes bindings — attach includes to the new scope
  • policy.resolve.to.withIncludes kind includes bindings — both

Inject an aspect into the current resolution:

policy.include { nixos.environment.variables.MARKER = "yes"; }

Remove an aspect via the constraint registry:

policy.exclude den.aspects.unwanted

Route class or quirk content from one scope partition into a target class:

policy.route {
fromClass = "myClass";
intoClass = "nixos";
path = [ "services" "myService" ];
}

Deliver a module directly to a target class, bypassing the aspect tree:

policy.provide { class = "nixos"; module = { pkgs, ... }: { ... }; }

Request post-pipeline instantiation of an entity:

policy.instantiate den.hosts.x86_64-linux.igloo

See den.quirks reference for the pipe builder API.

Tag a value with collisionPolicy = "class-wins" — when the value collides with a module-system arg (e.g., NixOS provides lib), the class value wins silently.


Policies are activated by including them in includes lists. The pipeline distinguishes policies from aspects by the __isPolicy tag.

# For all entities of a kind
den.schema.host.includes = [ den.policies.my-policy ];
# For a specific aspect's subtree
den.aspects.igloo.includes = [ den.policies.my-policy ];
# For all entities globally
den.default.includes = [ den.policies.my-policy ];

Policies and aspects mix freely in includes.

Create a named policy record for direct use in includes. Use this when defining inline policies that don’t need the den.policies registry:

den.default.includes = [
(den.lib.policy.mkPolicy "host-guards" ({ host, ... }: [
(den.lib.policy.resolve {
isNixos = host.class == "nixos";
isDarwin = host.class == "darwin";
})
]))
];

Returns { __isPolicy = true; name; fn; } — the pipeline recognizes this as a policy and routes it to the dispatch system.

Use excludes to prevent a policy from firing in a subtree:

den.aspects.igloo = {
excludes = [ den.policies.blocked ];
};

Excludes are authoritative — parent excludes cannot be overridden by child includes. The constraint registry uses the policy’s identity for matching.


Wrap a policy to fire only when a specific entity is in context, matched by id_hash:

den.lib.policy.for den.hosts.x86_64-linux.igloo den.policies.igloo-only

Accepts a single policy or a list. Identity is preserved through the wrapper.

den.lib.policy.when predicate policyOrList

Section titled “den.lib.policy.when predicate policyOrList”

Wrap a policy to fire only when a predicate over the current context returns true:

den.lib.policy.when ({ host, ... }: host.wsl.enable) den.policies.wsl-setup

Accepts a single policy or a list. Identity is preserved.

Combinators compose:

den.lib.policy.when (ctx: ctx.flag or false)
(den.lib.policy.for entity den.policies.my-policy)

PolicyFromToBehavior
host-to-usershostuserOne { host, user } per host.users entry
PolicyFromToBehavior
to-systemsflakeflake-systemOne { system } per den.systems entry
to-os-outputsflake-systemhostOne { host } per host + instantiate
to-hm-outputsflake-systemhomeOne { home } per home + instantiate
to-packagesflake-systemRoute packages class to flake output
to-appsflake-systemRoute apps class to flake output
to-checksflake-systemRoute checks class to flake output
to-devShellsflake-systemRoute devShells class to flake output
to-legacyPackagesflake-systemRoute legacyPackages class to flake output

Lightweight inspection utility that calls resolve functions directly without running the full pipeline:

den.lib.policyInspect.inspect {
kind = "host";
context = { host = den.hosts.x86_64-linux.igloo; };
}

Parameters:

  • kind — entity kind string
  • context — attrset representing the current pipeline context

Returns an attrset keyed by policy name with resolved targets, routing type, and other metadata.

Contribute Community Sponsor