den.policies
See Policies for conceptual background.
den.policies
Section titled “den.policies”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.
Policy effects
Section titled “Policy effects”All constructors are accessed via den.lib.policy. Policies return lists
of these effects.
policy.resolve bindings
Section titled “policy.resolve bindings”Create a new scope with bindings merged into the current context.
policy.resolve { myFlag = true; }Variants:
policy.resolve.shared bindings— shared (non-isolated) fan-outpolicy.resolve.to kind bindings— target a specific entity kindpolicy.resolve.withIncludes includes bindings— attach includes to the new scopepolicy.resolve.to.withIncludes kind includes bindings— both
policy.include aspect
Section titled “policy.include aspect”Inject an aspect into the current resolution:
policy.include { nixos.environment.variables.MARKER = "yes"; }policy.exclude aspect
Section titled “policy.exclude aspect”Remove an aspect via the constraint registry:
policy.exclude den.aspects.unwantedpolicy.deliver spec
Section titled “policy.deliver spec”The user-facing delivery primitive: declare one delivery edge from a source
into a target class at a path, with an explicit mode. route and provide
(below) are sugar shims over deliver.
# Class source — move a class's collected content (the `route` case):policy.deliver { from = "myClass"; # class name → collect that class's bucket to = "nixos"; # target class at = [ "services" "myService" ]; # attrpath ([] = merge at the class root) mode = "nest"; # "merge" | "nest" | "verbatim"}
# Module source — inject a NEW module (the `provide` case):policy.deliver { from = { module = { pkgs, ... }: { ... }; }; to = "nixos";}mode is exhaustive and explicit:
merge(default) — union into the target class bucket (use withat = []).nest— evaluate and place the source atat.verbatim— place the collected module wrappers by reference so a target whose optionmergere-instantiates them (e.g. a microvm guest config) sees the live modules together with its base modules. There is noreinstantiateflag — verbatim is requested bymodedirectly.verbatimapplies only to class sources, not module sources.
deliver deliberately does not expose appendToParent (parent-targeting is
constructor-internal) — use a class source whose to already names the target.
policy.route spec
Section titled “policy.route spec”Route class or quirk content from one scope partition into a target class. A
permanent sugar shim over policy.deliver —
fromClass→from, intoClass→to, path→at, and reinstantiate = true→
mode = "verbatim":
policy.route { fromClass = "myClass"; intoClass = "nixos"; path = [ "services" "myService" ];}policy.provide spec
Section titled “policy.provide spec”Deliver a module directly to a target class, bypassing the aspect tree. A
permanent sugar shim over policy.deliver with a module
source (class→to, module→from.module, path→at; mode is derived
from path — merge at the root, nest under a non-empty path):
policy.provide { class = "nixos"; module = { pkgs, ... }: { ... }; }policy.instantiate entity
Section titled “policy.instantiate entity”Request post-pipeline instantiation of an entity:
policy.instantiate den.hosts.x86_64-linux.igloopolicy.spawn
Section titled “policy.spawn”Request a deferred node spawn, resolved post-walk over the parent
pipeline’s full scope-tree state (host + siblings) so projected content
sees fleet-wide pipe values. classes defaults to the spawning entity’s
classes at the drain site when null:
policy.spawn { }policy.spawn { classes = [ "homeManager" ]; }policy.pipe
Section titled “policy.pipe”See den.quirks reference for the pipe builder API.
policy.pipelineOnly value
Section titled “policy.pipelineOnly value”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.
Activation
Section titled “Activation”Policies are activated by including them in includes lists. The pipeline
distinguishes policies from aspects by the __isPolicy tag.
# For all entities of a kindden.schema.host.includes = [ den.policies.my-policy ];
# For a specific aspect's subtreeden.aspects.igloo.includes = [ den.policies.my-policy ];
# For all entities globallyden.default.includes = [ den.policies.my-policy ];Policies and aspects mix freely in includes.
den.lib.policy.mkPolicy name fn
Section titled “den.lib.policy.mkPolicy name fn”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.
Deactivation
Section titled “Deactivation”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.
Combinators
Section titled “Combinators”den.lib.policy.for entity policyOrList
Section titled “den.lib.policy.for entity policyOrList”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-onlyAccepts 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-setupAccepts a single policy or a list. Identity is preserved.
Composition
Section titled “Composition”Combinators compose:
den.lib.policy.when (ctx: ctx.flag or false) (den.lib.policy.for entity den.policies.my-policy)Built-in policies
Section titled “Built-in policies”Entity traversal (core.nix)
Section titled “Entity traversal (core.nix)”| Policy | From | To | Behavior |
|---|---|---|---|
host-to-users | host | user | One { host, user } per host.users entry |
Flake output traversal (flake.nix)
Section titled “Flake output traversal (flake.nix)”| Policy | From | To | Behavior |
|---|---|---|---|
flake-to-systems | flake | flake-system | One { system } per den.systems entry |
system-to-os-outputs | flake-system | host | One { host } per host + instantiate |
system-to-hm-outputs | flake-system | home | One { home } per home + instantiate |
packages-to-flake | flake-system | — | Route packages class to flake output |
apps-to-flake | flake-system | — | Route apps class to flake output |
checks-to-flake | flake-system | — | Route checks class to flake output |
devShells-to-flake | flake-system | — | Route devShells class to flake output |
legacyPackages-to-flake | flake-system | — | Route legacyPackages class to flake output |
den.lib.policyInspect.inspect
Section titled “den.lib.policyInspect.inspect”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 stringcontext— attrset representing the current pipeline context
Returns an attrset keyed by policy name with resolved targets, routing type, and other metadata.
See also
Section titled “See also”- Policies explanation — conceptual overview
- Policy Activation Deep Dive — registry/activation model, dispatch internals
- den.quirks — pipe builder API (a policy effect type)