Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: denful/den
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.8.0
Choose a base ref
...
head repository: denful/den
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.9.0
Choose a head ref
  • 11 commits
  • 148 files changed
  • 2 contributors

Commits on Feb 13, 2026

  1. readme

    vic committed Feb 13, 2026
    Configuration menu
    Copy the full SHA
    675524f View commit details
    Browse the repository at this point in the history

Commits on Feb 14, 2026

  1. Actualizar README.md

    vic authored Feb 14, 2026
    Configuration menu
    Copy the full SHA
    f9563fa View commit details
    Browse the repository at this point in the history

Commits on Feb 15, 2026

  1. Configuration menu
    Copy the full SHA
    36b571d View commit details
    Browse the repository at this point in the history
  2. feat: forward classes (#164)

    The functionality of `homeManager` itself was generalized into
    `den.provides.forward`, this will pave the road for easily having
    `hjem`, `nix-maid` and most importantly, allow the user to have custom
    defined forward classes.
    
    See discussion at #160
    vic authored Feb 15, 2026
    Configuration menu
    Copy the full SHA
    933a84f View commit details
    Browse the repository at this point in the history

Commits on Feb 17, 2026

  1. Configuration menu
    Copy the full SHA
    2789943 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    5478f8e View commit details
    Browse the repository at this point in the history
  3. Fix usage of obsolete options and remove passthru requirement (#169) (#…

    …171)
    
    Changes:
    - Remove need to define `passthru` attribute for hosts
    - Remove usage of obsolete nixpkgs options
    - Add descriptive error message if `flake`'s attributes are defined
    multiple times
    jhakonen authored Feb 17, 2026
    Configuration menu
    Copy the full SHA
    f8cb8c6 View commit details
    Browse the repository at this point in the history

Commits on Feb 20, 2026

  1. den.ctx. Den declarative context definitions. (#175)

    Related #174 
    
    #  Declarative Context Definitions
    
    This introduces [`den.ctx`](#175), a
    declarative system for defining how context (data) is transformed and
    which aspects are applied at every stage of the configuration pipeline.
    
    ## The Problem
    
    Before this release, `den.default` served two purposes:
    
    - A place to define global or generic includes for `host`, `user`, and
    `home` entities.
    - The backbone of context propagation — moving data from `{ host }` to
    `{ host, user }` to `{ host, user }` in the HM pipeline, etc.
    
    As a consequence, `den.default.includes` was abused by many of us,
    including Den itself, because it was [where context transformation
    happened](https://github.com/vic/den/blob/f8cb8c618e1680e99c165d2bf826600170abb5a2/modules/aspects/dependencies.nix#L28)
    [\[2\]](https://github.com/vic/den/blob/f8cb8c618e1680e99c165d2bf826600170abb5a2/modules/aspects/provides/home-manager/hm-dependencies.nix#L31).
    This "dependency system" — parametric aspects installed unconditionally
    at `den.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
    
    - **Keep `den.default` for what it's good at**: global settings. You can
    still use `den.default.includes`, but there are better alternatives now.
    - **Move the dependency system out of `den.default.includes`**: those
    parametric aspects were not individually testable, and you couldn't
    change how data flows. They were Den's hardcoded backbone.
    - **Declarative data stages**: context transformations are now explicit.
    Given a `host`, you declare how to enumerate users, detect HM support,
    etc.
    - **Named contexts**: previously we identified contexts only by their
    `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.
    - **Extensible context flows**: one core principle of Den is not getting
    in your way. You can create alternative flows, or use Den purely as a
    library.
    
    ## Named Contexts: Transform, Don't Validate
    
    Named contexts carry semantic meaning beyond their structure. `ctx.host
    { host }` and `ctx.hm-host { host }` hold the same data, but `hm-host`
    **guarantees** that home-manager support was validated:
    
    - `inputs.home-manager` exists (or the host has a custom `hm-module`)
    - The host has at least one user with `class = "homeManager"`
    
    You cannot obtain an `hm-host` context 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`, and
    `into`.
    
    ```nix
    den.ctx.foo.desc = "The foo context requires { foo } data.";
    
    den.ctx.foo.conf = { foo }: my-aspects.${foo.name};
    ```
    
    When `ctx.foo` is applied — it works like a function taking `{ foo }` —
    it locates the responsible aspect via `conf`. For example, `ctx.foo {
    foo.name = "bar"; }` uses `my-aspects.bar`. The aspect's owned config,
    static includes, and parametric includes matching `{ foo }` all
    contribute to whatever `ctx.foo` is 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.igloo` is the host itself:
    
    ```nix
    # Nothing NixOS-specific yet — just a graph of dependencies.
    aspect = den.ctx.host {
      host = den.hosts.x86_64-linux.igloo;
    };
    ```
    
    The result of `ctxApply` is a new aspect that includes
    `den.aspects.igloo` plus the entire transformation chain — user
    enumeration, HM detection, defaults.
    
    ```nix
    # This is where things enter the NixOS domain.
    nixosModule = aspect.resolve { class = "nixos"; };
    
    nixosConfigurations.igloo = lib.nixosSystem {
      modules = [ nixosModule ];
    };
    ```
    
    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`:
    
    ```nix
    den.ctx.foo.conf = { foo }: ...;
    den.ctx.moo.conf = { moo }: ...;
    
    den.ctx.foo.into.moo = { foo }: lib.singleton { moo = deriveMoo foo; };
    ```
    
    All `<source>.into.<target>` transformations are taken into account by
    `ctxApply`.
    
    ### Why Lists?
    
    Transformations have the type `source → [ target ]`. This enables:
    
    - **Fan-out**: one host produces many `{ host, user }` contexts (`map`)
    - **Conditional propagation**: zero or one contexts (`lib.optional`)
    - **Pass-through**: identity transformation (`lib.singleton`)
    
    For example, HM detection uses conditional propagation:
    
    ```nix
    den.ctx.host.into.hm-host = { host }:
      lib.optional (isHmSupported host) { inherit host; };
    ```
    
    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`:
    
    ```nix
    # Owned config — only for validated HM hosts:
    den.ctx.hm-host.nixos.home-manager.useGlobalPkgs = true;
    
    # Scoped includes — only for validated HM hosts:
    den.ctx.hm-host.includes = [
      ({ host, ... }: { nixos.home-manager.backupFileExtension = "bak"; })
    ];
    ```
    
    This is like `den.default.includes` **but 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:
    
    ```nix
    den.ctx.hm-host.into.foo = { host }: [ { foo = host.name; } ];
    den.ctx.foo.conf = { foo }: ...;
    den.ctx.foo.includes = [ ({ foo, ... }: ...) ];
    ```
    
    The module system merges these definitions. You can extend the pipeline
    without modifying any built-in file.
    
    ## Custom Context Flows
    
    Each host has a `mainModule` option that defaults to:
    
    ```nix
    (den.ctx.host { host }).resolve { class = "nixos"; }
    ```
    
    You can override `mainModule` to use a completely alternative context
    flow, independent of `ctx.host`. Custom flows can be designed and tested
    in isolation — Den's CI uses a `funny.names` class that has nothing to
    do with NixOS to verify context mechanics independently.
    
    ## What Happened to den.default?
    
    `den.default` stays and is still useful for truly global settings. The
    issue was abusing `den.default.includes` as the context propagation
    backbone.
    
    ### Internal Changes
    
    Previously, all host, user, and home aspects had:
    
    ```nix
    includes = [ den.default ]
    ```
    
    Now they **no longer include `den.default` directly**. Including
    `den.default` explicitly is discouraged.
    
    ### How Defaults Are Applied Now
    
    Each context type transforms into `default`:
    
    ```nix
    den.ctx.host.into.default = lib.singleton;  # passes { host }
    den.ctx.user.into.default = lib.singleton;  # passes { host, user }
    den.ctx.home.into.default = lib.singleton;  # passes { home }
    ```
    
    `den.default` is now an alias for `den.ctx.default`. The data that flows
    into `den.default.includes` comes from these declarative
    transformations, not from direct aspect inclusion.
    
    ### Best Practices
    
    | Instead of | Use |
    |-----------|-----|
    | `den.default.includes = [ hostFunc ]` | `den.ctx.host.includes = [
    hostFunc ]` |
    | `den.default.includes = [ hmFunc ]` | `den.ctx.hm-host.includes = [
    hmFunc ]` |
    | `den.default.nixos.x = 1` | `den.ctx.host.nixos.x = 1` |
    
    `den.default` remains the right place for values that genuinely apply
    everywhere — like `stateVersion`. Use context-specific includes for
    anything that belongs to a particular pipeline stage.
    vic authored Feb 20, 2026
    Configuration menu
    Copy the full SHA
    def3ecf View commit details
    Browse the repository at this point in the history
  2. fix gh-pages

    vic committed Feb 20, 2026
    Configuration menu
    Copy the full SHA
    1691a68 View commit details
    Browse the repository at this point in the history

Commits on Mar 29, 2026

  1. versioned docs

    vic committed Mar 29, 2026
    Configuration menu
    Copy the full SHA
    1fa75bf View commit details
    Browse the repository at this point in the history

Commits on Mar 30, 2026

  1. add versions dropdown

    vic committed Mar 30, 2026
    Configuration menu
    Copy the full SHA
    fec76cd View commit details
    Browse the repository at this point in the history
Loading