Resolution Pipeline
Pipeline overview
Section titled “Pipeline overview”When Den evaluates a host, it runs a resolution pipeline driven by policies and entities. Policies are directed edges that fan context out to downstream entity kinds; each entity kind binds behavior for its resolved context.
flowchart TD
start["den.hosts.x86_64-linux.laptop"] --> host["host {host}"]
host -->|"host-to-users"| user["user {host, user} (per user)"]
host -->|"host-to-hm-users"| hmfwd["forward each homeManager user"]
hmfwd --> fwd["into home-manager.users.alice"]
-
Host resolution
For each entry in
den.hosts.<system>.<name>, the pipeline creates ahostscope. The host’s own aspect is resolved viaden.schema.host.includes, binding owned configs for the host’s class. -
Core policy fans out to users
The one core traversal edge (
modules/policies/core.nix) ishost-to-users, registered as aden.schema.host.includesentry:Policy From To Resolve host-to-usershostuserOne edge per host.usersentryA policy receives the current context and returns a list of downstream resolves.
host-to-usersfans out one{ host, user }pair per user declared on the host (viaresolve.shared). If the host aspect has a freeform key matching a user’s name, that sub-aspect is also included in the user scope. -
Battery policies forward user environments
The home-environment batteries share a factory,
makeHomeEnv(nix/lib/home-env.nix), which produces a host-scope fan-out policy and a user-scope detect policy. The fan-out policy fires when the battery is enabled, the host OS is supported, and the host has at least one user of the battery’s class:Policy Condition Effect host-to-hm-usersHM enabled, host has homeManager-class usersForward each HM user into home-manager.users.<name>hm-user-detectPer homeManager-class userApply user schema includes + forward host-to-hjem-usershjem enabled, host has hjem-class usersForward each user into hjem.users.<name>hjem-user-detectPer hjem-class userApply user schema includes + forward host-to-maid-usersnix-maid enabled (NixOS), host has maid-class usersForward each user into users.users.<name>.maidmaid-user-detectPer maid-class userApply user schema includes + forward Rather than creating a two-stage
*-host→*-userentity-kind chain, the fan-out policy resolves each matching user directly and emits a forward into the target namespace. The battery’s OS module (e.g.home-manager.nixosModules.home-manager) is imported once via a keyed module wrapper, so it fires a single time even when included from multiple user resolves.WSL is the exception:
host-to-wsl-host(modules/aspects/batteries/wsl.nix) does create awsl-hostentity kind (resolve.to "wsl-host") when a NixOS host setswsl.enable, importing the NixOS-WSL module into the host class. -
Deduplication
The pipeline tracks a seen set of include keys, each keyed by
"${scope}/${identityKey}"(the current scope plus the aspect’s identity). The first time a named aspect is included in a scope, the full aspect (owned configs + statics + parametric matches) is resolved. Subsequent includes of the same aspect in the same scope are skipped, so a shared aspect (e.g. one reachable fromden.default) is not applied twice within a scope.Because the key is scope-prefixed, an aspect can still be included in different scopes — entity levels reached through different policies are isolated and each gets its own copy.
-
Home configurations
Standalone
den.homesentries follow a separate path. They are resolved by the flake policies (see step 6) rather than via a host, and their aspect resolves throughden.schema.homeincludes:flowchart TD home["den.homes.x86_64-linux.alice"] --> homestage["home {home}"] homestage --> hmc["homeConfigurations.alice"]Home scopes have no
hostin context, so policies and provides requiring{ host }are not activated. Shared defaults still apply becauseden.defaultis one of thehomeschema includes. -
Output
Flake-level policies (
modules/policies/flake.nix) drive the final assembly.flake-to-systemsfans out oneflake-systemscope per entry inden.systems. For each system,system-to-os-outputsresolves the declared hosts andsystem-to-hm-outputsresolves the standalone homes. Each entity is instantiated by itsinstantiatefunction (defaulting tonixosSystem/darwinSystemfor hosts andhomeManagerConfigurationfor homes, depending on class) and placed at the entity’sintoAttrpath —flake.nixosConfigurations,flake.darwinConfigurations, orflake.homeConfigurations.
See also
Section titled “See also”- Entities and Schema — what entities are and how they feed the pipeline
- Policies — how entities relate
- Quirks & Pipes — structured data flow between aspects
- Fleets & Multi-Host — cross-host resolution and data flow
- Aspects — how entities resolve