den.aspects
den.aspects
Section titled “den.aspects”An attribute set of aspects. Each aspect key names an aspect; its value is
an aspect set containing per-class deferred modules and optional includes and provides:
den.aspects = { dns = { nixos.services.resolved.enable = true; darwin.networking.dns = [ "1.1.1.1" ]; includes = [ ./dns ]; };};Auto-generation
Section titled “Auto-generation”Den auto-generates den.aspects entries from den.hosts, den.homes,
and den.users. For every declared host/home/user, an aspect is created
with the appropriate class configurations. You do not need to declare
den.aspects manually unless adding shared aspects.
den.ful
Section titled “den.ful”Type: attrsOf aspectsType
Namespaced aspect collections. Each key is a namespace name, each value
is a full aspectsType. Populated by den.namespace or by merging
upstream denful flake outputs.
den.ful.myns = { some-aspect = { nixos.services.foo.enable = true; };};flake.denful
Section titled “flake.denful”Type: attrsOf raw
Raw flake output for publishing namespaces. Set automatically by
den.namespace; consumed by downstream flakes that import your aspects.
Aspect structure
Section titled “Aspect structure”An aspect is an attribute set with:
| Key | Purpose |
|---|---|
<class> | Config merged into hosts/homes of that class |
includes | List of modules or functions dispatched by context |
__functor | Auto-generated by parametric; drives dispatch |
Static vs parametric includes
Section titled “Static vs parametric includes”Functions in includes receiving { class, aspect-chain } are static —
evaluated once during aspect resolution. Functions receiving context
arguments ({ host }, { user }, etc.) are parametric — evaluated
per context during pipeline resolution.
meta.adapter (deprecated — use handleWith)
Section titled “meta.adapter (deprecated — use handleWith)”An aspect can declare a subtree adapter via meta.adapter. The adapter
is a function that receives the inherited adapter and returns a new one,
enabling composition — a parent’s filter cannot be overridden by children.
Prefer handleWith for new code — it provides the same subtree transformation
capability with clearer semantics and composability.
meta.provider
Section titled “meta.provider”Tracks the structural origin of an aspect as a path. Top-level aspects
have meta.provider = []. An aspect provided by foo (via
foo.provides.bar or foo._.bar) has meta.provider = ["foo"].
Deeply nested providers accumulate: foo._.bar._.baz has
meta.provider = ["foo" "bar"].
The meta.provider list can be used to distinguish aspects by origin
during pipeline resolution.
den.provides (aliased as den._)
Section titled “den.provides (aliased as den._)”This is the place for Den built-in batteries, reusable aspects that serve as basic utilities and examples.
See Batteries Reference.
Cross-context forwarding
Section titled “Cross-context forwarding”Entities (hosts, users, homes) expose .resolved — the aspect produced
by their context pipeline. Forwards can use this to pull configuration
from one entity into another without manually wiring context calls.
When den._.forward is called without fromAspect, it defaults to
item.resolved, resolving the source entity through its own context
pipeline:
# Collect SSH host keys from all other hostsden.aspects.iceberg.includes = [ ({ host }: den._.forward { each = lib.filter (h: h != host) (lib.attrValues den.hosts.${host.system}); fromClass = _: "ssh-host-key"; intoClass = _: host.class; # "nixos" or "darwin" intoPath = _: [ ]; } )];Each host in each is resolved via its .resolved attribute, and the
ssh-host-key class content is forwarded into the target’s OS config.
host.class is the OS class name ("nixos", "darwin"), not the
context type.
Class resolution
Section titled “Class resolution”Resolution is handled internally by the fx pipeline. den.lib.aspects.resolve still exists but is not a public API — call it directly only if you are building custom pipeline stages.
When the pipeline resolves aspects for an entity, it:
- Collects all aspects referenced by the entity
- Compiles each aspect into an effectful computation (
fx.send "resolve") - Evaluates static includes and defers parametric includes until context widens
- Walks the policy graph to fan out into derived stages
- Extracts the class-specific config (e.g.,
nixosfor NixOS hosts) - Merges everything into the entity’s
evalModulescall