refactor: move from den based to flake-parts based

This commit is contained in:
2026-04-21 00:59:54 +02:00
parent d2ab961c48
commit 5bed1336c0
71 changed files with 1832 additions and 2472 deletions
+56 -74
View File
@@ -1,101 +1,83 @@
# Repository Guidelines
## Project Structure & Module Organization
This repository is a Den-based NixOS flake. `flake.nix` evaluates `./modules` through `import-tree`, so normal `.nix` files under `modules/` are auto-imported.
This repository is a simplified `flake-parts` NixOS flake. `flake.nix` imports `./modules` through `import-tree`, so normal `.nix` files under `modules/` are loaded automatically unless their file or directory name starts with `_`.
- `modules/den.nix` imports the Den flake module and the `lux` namespace.
- `modules/defaults.nix` sets repo-wide Den defaults, enables `den._.mutual-provider`, and configures `den.ctx.hm-host`.
- `modules/schema.nix` defines the custom Den host and user schema used by this repo.
- `modules/infra.nix` defines `den.hosts.x86_64-linux.<name>`, each host entity's `users` attrset, and the host/user data attached to those entities.
- `modules/bundles.nix` defines bundle aspects that group other aspects. A bundle aspect may exist only to compose `includes`; `local-session` is an example.
- `modules/hosts/` contains host-specific composition and hardware data for `orion`, `polaris`, and `zenith`.
- `modules/features/` contains reusable aspects. In this repo, "feature" is only a directory label, not a Den primitive.
- `modules/users/` defines per-user aspects.
- `modules/secrets/` wires `sops-nix` and stores the encrypted `secrets.yaml`.
- `.agents/den/` is a local checkout of Den with source, docs, and examples.
- `modules/flake-parts.nix` defines the `flake-parts` setup, formatter, and the exported `nixosConfigurations`.
- `modules/hosts/<name>/default.nix` defines one top-level `flake.modules.nixos.<host>` module and assembles that machine by importing reusable features, user modules, and host-local helpers.
- `modules/hosts/<name>/_*.nix` are private host-local helper modules such as hardware and disk layout files.
- `modules/users/<name>.nix` defines one reusable NixOS user module and the baseline Home Manager imports for that account.
- `modules/features/*.nix` contains reusable NixOS and Home Manager feature modules.
- `modules/features/<feature>/default.nix` is used when a feature needs private helper files, for example `niri/_bindings.nix`.
- `modules/features/services/*.nix` contains reusable service-oriented NixOS modules.
- `modules/secrets/sops.nix` wires `sops-nix` for both NixOS and Home Manager.
- `modules/secrets/secrets.yaml` stores encrypted secrets, with `.sops.yaml` defining SOPS creation rules.
- `modules/_treefmt.nix` configures repository formatting.
Keep host files thin. Shared behavior belongs in `modules/features/` or `modules/bundles.nix`.
When Den behavior is unclear, read `.agents/den/modules/` and `.agents/den/nix/lib/` first. Use `.agents/den/templates/ci/` as example code. Use `.agents/den/docs/` only for design rationale, terminology, and usage guidance.
Do not infer Den behavior from surface symptoms or from where an aspect is included; reason from the actual context pipeline.
Keep host files thin. Shared behavior belongs in `modules/features/` or `modules/users/`. Host files should mainly compose imports and hold host-only settings such as monitor layouts, hardware quirks, boot tweaks, and machine-local firewall or service choices.
## Den Mental Model
Den is aspect-first and context-driven.
## Mental Model
This repo is direct module composition around `flake.modules`, not the old inventory-driven dendritic design.
- Host, user, and home are entity kinds in Den. This repo defines host and user entities; it does not define standalone home entities under `modules/`.
- An aspect is the unit of behavior. A single aspect may define `nixos`, `homeManager`, `darwin`, `user`, or other class fragments for one concern.
- A context stage applies a resolved aspect to a context; Den then follows `into.*` and `provides.*`.
- `homeManager` is a forwarding class.
- Reusable building blocks are exposed as `flake.modules.nixos.<name>` and `flake.modules.homeManager.<name>`.
- Host modules are the composition root. They import the reusable NixOS modules they need, enable Home Manager, and add any host-specific Home Manager imports inline.
- User modules define the Unix user plus that accounts baseline Home Manager setup.
- There is no `config.repo`, inventory schema, profiles layer, or attachment builder anymore.
In practice:
- Including an aspect does not by itself create a forwarding path.
- Parametric matching does not by itself create a forwarding path.
- A class fragment reaches its final option path only if a context stage or forwarding class actually puts it there.
- If you cannot name the context stage and forwarding path, treat the claim as unverified.
- Prefer importing a feature module directly over inventing a repo-local option just to toggle it.
- Put cross-host reusable behavior in `modules/features/`.
- Put account-specific defaults in `modules/users/`.
- Keep private helper files `_`-prefixed so `import-tree` does not expose them as top-level modules.
- Match the existing split between NixOS composition in host modules and Home Manager composition in user or host modules.
## Den Context Stages And Forwarding Mechanisms
These are the mechanisms most relevant to the context pipeline in this repo.
## Current Host Composition
There are three exported hosts:
- `den.ctx.host`: host context stage; applies `fixedTo { host; } host.aspect`
- `den.ctx.user`: user context stage from `den.ctx.host.into.user`; applies `fixedTo { host; user; } user.aspect`
- `den._.mutual-provider`: battery included on `den.ctx.user` in this repo; routes host-to-user and user-to-host through `provides.<name>`, host-to-all-users through `provides.to-users`, user-to-hosts through `provides.to-hosts`, and user-to-other-users on the same host through the same user context pipeline. In Den generally it also has standalone-home behavior, but this repo does not use standalone `den.homes`
- `den.ctx.hm-host` / `den.ctx.hm-user`: derived home-env context stages
- `den._.define-user`: battery included by `den.default` in this repo; defines base OS user fields and base `homeManager.home.username` / `home.homeDirectory` fields
- `homeManager`: forwarding class into `home-manager.users.<name>`
- `den._.os-user`: framework battery forwarding the `user` class into `users.users.<name>`; useful in Den generally, but not used in this repo today
- `den._.forward`: battery for custom class/path forwarding
- `orion`: server-oriented host with `kiri`, SOPS, and service modules such as Caddy, Gitea, Vaultwarden, Radicale, Actual, and OpenSSH.
- `polaris`: graphical desktop host with `kiri` and `ergon`, hardware imports, Niri, Steam, local desktop features, and host-specific monitor layout.
- `zenith`: graphical laptop host with `kiri` and `ergon`, Niri, laptop hardware support, firmware updates, and host-specific monitor layout.
## Den Helper Functions
These are the Den helpers that matter most in this repo.
When adjusting user-facing software, check whether it belongs in:
- `den.lib.perHost`: exact `{ host }` wrapper
- `den.lib.perUser`: exact `{ host, user }` wrapper
- `den.lib.perHome`: exact `{ home }` wrapper; not used by this flake today
- `den.lib.parametric`: explicit parametric wrapper; default matching is `atLeast`
- `den.lib.parametric.exactly`: explicit exact-match wrapper
- a user baseline in `modules/users/<name>.nix`
- a reusable Home Manager feature in `modules/features/*.nix`
- a host-local extension inside `modules/hosts/<name>/default.nix`
## Den Forwarding Proof Obligation
When making or reviewing any Den forwarding change, do not infer behavior from where code is declared or included.
You must identify all four of these explicitly:
1. Source: which aspect actually owns the class fragment?
2. Context stage: which `den.ctx.*` stage applies it?
3. Destination: which final evaluated option path should contain the result?
4. Mechanism: which `into.*` transition reaches the context stage, and which class application, `provides.*`, forwarding class, or `den._.forward` step places it at the destination?
If any of those answers are missing, unclear, or based on analogy, treat the claim as unverified.
Before presenting a forwarding claim as a recommendation or review finding, verify it at the evaluated destination with `nix eval`.
Minimum checks:
- host-selected `homeManager` behavior: inspect `nixosConfigurations.<host>.config.home-manager.users.<user>`
- OS user forwarding via `user` class: inspect `nixosConfigurations.<host>.config.users.users.<user>`
- mutual host/user forwarding through `provides.<name>`, `provides.to-users`, or `provides.to-hosts`: inspect the final destination option, not the declaration site
- custom forwarding through `den._.forward`: inspect the exact target path created by the forwarder
Be careful not to move host-specific Home Manager imports into a user baseline unless that behavior should apply on every host that imports that user module.
## Validation And Development Commands
Run commands from the repository root.
- `nix build --no-link --show-trace .#nixosConfigurations.<host>.config.system.build.toplevel`: baseline validation for one host without activation and without creating a `result` symlink.
- `nix build --no-link --show-trace .#nixosConfigurations.orion.config.system.build.toplevel .#nixosConfigurations.polaris.config.system.build.toplevel .#nixosConfigurations.zenith.config.system.build.toplevel`: validate all currently defined hosts in one invocation.
- `nixos-rebuild build --flake .#<host>`: use the standard rebuild path without activation when you specifically want `nixos-rebuild` semantics.
- `nix fmt`: format Nix files using the flake-provided `nixfmt` formatter.
- `nix eval .#nixosConfigurations.<host>.config.<option>`: inspect a single option while iterating.
- `nix build --no-link --show-trace .#nixosConfigurations.<host>.config.system.build.toplevel`: baseline validation for one host.
- `nix build --no-link --show-trace .#nixosConfigurations.orion.config.system.build.toplevel .#nixosConfigurations.polaris.config.system.build.toplevel .#nixosConfigurations.zenith.config.system.build.toplevel`: validate all defined hosts in one invocation.
- `nixos-rebuild build --flake .#<host>`: use when you specifically want `nixos-rebuild` semantics without activation.
- `nix eval --json .#nixosConfigurations.<host>.config.<option>`: inspect a single evaluated option while iterating.
- `nix fmt`: format the repository using the flake-provided formatter from `modules/_treefmt.nix`.
- `nix store diff-closures <old> <new>`: compare built system closures when reviewing refactors for parity or regressions.
This repo does not define a `checks` output or a first-party test suite. Treat evaluation and build-only checks as the baseline. `nix flake check` is therefore not the baseline validation command here. `nixos-rebuild dry-activate` is not a baseline validation command either: it is activation-oriented, applies to the target system being rebuilt, and its own help text says the reported change set is not guaranteed to be complete.
For Den context-stage or forwarding changes, use the destination checks above.
This repo does not define a first-party `checks` output. Validation is primarily host builds plus targeted `nix eval` checks.
## Coding Style & Naming Conventions
Use two-space indentation and standard Nix attrset formatting. Prefer small `let` bindings, lowerCamelCase local names, and lowercase file names such as `sops-password.nix`. Match the surrounding module style instead of reformatting unrelated code.
Use two-space indentation and standard Nix attrset formatting. Prefer small `let` bindings, lowerCamelCase local names, and lowercase file names.
Prefer Den composition through `includes`; avoid host-specific duplication when a reusable aspect or bundle aspect is clearer.
Keep the configuration aspect-first. When a class fragment must cross context boundaries, express that through an explicit forwarding mechanism instead of relying on implicit host/user propagation.
- Define reusable modules as `flake.modules.nixos.<name>` or `flake.modules.homeManager.<name>`.
- Keep one obvious feature per file or directory.
- Use `default.nix` only when the feature needs private helper files alongside it.
- Match surrounding style instead of reformatting unrelated code.
- Prefer explicit host imports over hidden indirection.
## Commit
Follow the history style: short imperative subjects, optionally with a conventional prefix, for example `refactor: restructure openssh config`. Keep each commit focused on one concern.
Follow the existing history style: short imperative subjects, optionally with a conventional prefix, for example `refactor: simplify host composition`.
## Security & Configuration Tips
Never commit plaintext secrets. Add or update secrets through `modules/secrets/secrets.yaml` and reference them via `config.sops.secrets.<name>.path`. Be explicit about firewall, SSH, disk, boot, or firmware changes; those are the highest-risk edits here.
Never commit plaintext secrets. Add or update secrets through `modules/secrets/secrets.yaml` and reference them via `config.sops.secrets.<name>.path`.
Be explicit and cautious with changes to:
- firewall and OpenSSH settings
- disk layout and boot configuration
- SOPS key handling and admin user access
- firmware, hardware, and authentication settings
- host-vs-user module boundaries, because it is easy to accidentally broaden behavior to the wrong machines