v0.9.0 #177
vic
announced in
Announcements
v0.9.0
#177
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Den v0.9.0 — Declarative Context Definitions and new documentation website!
This release introduces
den.ctx, a declarative system for defining how context (data) is transformed and which aspects are applied at every stage of the configuration pipeline.What's Changed
New Contributors
Full Changelog: v0.8.0...v0.9.0
Context flows (our new dependency system)
Before this release,
den.defaultserved two purposes:host,user, andhomeentities.{ host }to{ host, user }to{ host, user }in the HM pipeline, etc.As a consequence,
den.default.includeswas abused by many of us, including Den itself, because it was where context transformation happened [2]. This "dependency system" — parametric aspects installed unconditionally atden.default.includes— was hard to reason about, hard to document, and hard for people to understand.The symptoms were duplicate configuration values, caused by lax parametric functions matching too many pipeline stages.
What den.ctx Provides
den.defaultfor what it's good at: global settings. You can still useden.default.includes, but there are better alternatives now.den.default.includes: those parametric aspects were not individually testable, and you couldn't change how data flows. They were Den's hardcoded backbone.host, you declare how to enumerate users, detect HM support, etc.attrNames—{ host },{ host, user }. Now they have names:ctx.host,ctx.hm-host. Names allow different contexts with the same structural shape but different semantic guarantees.Context Transformations: Parse don't Validate principle
Named contexts carry semantic meaning beyond their structure.
ctx.host { host }andctx.hm-host { host }hold the same data, buthm-hostguarantees that home-manager support was validated:inputs.home-managerexists (or the host has a customhm-module)class = "homeManager"You cannot obtain an
hm-hostcontext unless these conditions hold. This follows the transform-don't-validate principle.How a Context Type Works
A context type has four components:
desc,conf,includes, andinto.When
ctx.foois applied — it works like a function taking{ foo }— it locates the responsible aspect viaconf. For example,ctx.foo { foo.name = "bar"; }usesmy-aspects.bar. The aspect's owned config, static includes, and parametric includes matching{ foo }all contribute to whateverctx.foois being used to configure.Context types are independent of NixOS. Den can be used as a library for network topologies, declarative cloud infrastructure, or anything describable as data transformations.
How a NixOS Configuration Is Built
The initial data for
nixosConfigurations.igloois the host itself:The result of
ctxApplyis a new aspect that includesden.aspects.iglooplus the entire transformation chain — user enumeration, HM detection, defaults.These two steps can be adapted for any class, for anything Nix-configurable.
Context Propagation
Context transformation is declarative. If your data fans out to other contexts, you specify the transformations using
.into:All
<source>.into.<target>transformations are taken into account byctxApply.Why Lists?
Transformations have the type
source → [ target ]. This enables:{ host, user }contexts (map)lib.optional)lib.singleton)For example, HM detection uses conditional propagation:
Same data, but the named context guarantees validation passed.
Contexts as Aspect Cutting-Points
Contexts are aspect-like themselves. They have owned configs and
.includes:This is like
den.default.includesbut scoped — it only activates for hosts with validated home-manager support.Extending the Context Flow
You can add new transformations to any existing context type:
The module system merges these definitions. You can extend the pipeline without modifying any built-in file.
Custom Context Flows
Each host has a
mainModuleoption that defaults to:You can override
mainModuleto use a completely alternative context flow, independent ofctx.host. Custom flows can be designed and tested in isolation — Den's CI uses afunny.namesclass that has nothing to do with NixOS to verify context mechanics independently.What Happened to den.default?
den.defaultstays and is still useful for truly global settings. The issue was abusingden.default.includesas the context propagation backbone.Internal Changes
Previously, all host, user, and home aspects had:
Now they no longer include
den.defaultdirectly. Includingden.defaultexplicitly is discouraged.How Defaults Are Applied Now
Each context type transforms into
default:den.defaultis now an alias forden.ctx.default. The data that flows intoden.default.includescomes from these declarative transformations, not from direct aspect inclusion.Best Practices
den.default.includes = [ hostFunc ]den.ctx.host.includes = [ hostFunc ]den.default.includes = [ hmFunc ]den.ctx.hm-host.includes = [ hmFunc ]den.default.nixos.x = 1den.ctx.host.nixos.x = 1den.defaultremains the right place for values that genuinely apply everywhere — likestateVersion. Use context-specific includes for anything that belongs to a particular pipeline stage.This discussion was created from the release v0.9.0.
Beta Was this translation helpful? Give feedback.
All reactions