refactor(flake): split assembly code #73

Merged
alexion merged 10 commits from refactor/flake-assembly into main 2026-08-29 17:21:41 -04:00
3 changed files with 280 additions and 3 deletions
Showing only changes of commit be4a060e94 - Show all commits

View File

@@ -4,13 +4,16 @@ One flake builds every machine I own.
## Repository Conventions ## Repository Conventions
- Follow `docs/technical-writing.md` for comments, user-facing descriptions, commit prose, pull-request prose, and Markdown documentation. - Use `docs/technical-writing.md` and `docs/dictionary.md` while authoring any file.
Apply them to comments, user-facing descriptions, commit prose, pull-request prose, and Markdown documentation.
- Comments posted to the forge under the operator's account must end with `— Pi`. - Comments posted to the forge under the operator's account must end with `— Pi`.
The sign-off identifies the agent as the author instead of the operator. The sign-off identifies the agent as the author instead of the operator.
- Commit messages follow Conventional Commits, defined in `docs/conventional-commits.md`. - Commit messages follow Conventional Commits, defined in `docs/conventional-commits.md`.
Use a scope for the changed module or host, such as `fish`, `nvim`, or `neogaia`. Use a scope for the changed module or host, such as `fish`, `nvim`, or `neogaia`.
- Keep commit messages about the Git history, not the forge workflow. - Keep commit messages about the Git history, not the forge workflow.
Do not reference issue or pull-request numbers unless the commit itself requires a stable external reference. Do not reference issue or pull-request numbers unless the commit itself requires a stable external reference.
- During pull-request development, add follow-up commits instead of amending existing commits.
Preserve review history until the pull request is ready to merge.
- Use `gitea-axi` for Gitea issues, pull requests, labels, reviews, comments, and milestones. - Use `gitea-axi` for Gitea issues, pull requests, labels, reviews, comments, and milestones.
It resolves this repository from the `origin` remote inside the checkout. It resolves this repository from the `origin` remote inside the checkout.

View File

@@ -45,11 +45,15 @@ Use the simplest accurate word when a term is not listed.
| operator | Agent tooling | The human driving the development process. Use when distinguishing the human from the agent acting on their behalf. | | operator | Agent tooling | The human driving the development process. Use when distinguishing the human from the agent acting on their behalf. |
| guest | dotfiles | A systemd-nspawn container managed by this flake. Use for configured containers under `guests/`. | | guest | dotfiles | A systemd-nspawn container managed by this flake. Use for configured containers under `guests/`. |
| host | dotfiles | A machine with a NixOS configuration built by this flake. | | host | dotfiles | A machine with a NixOS configuration built by this flake. |
| module | dotfiles | In this repository, a self-contained configuration under `modules/`, usually scoped to one program, service, or subsystem. Use `Nix module` for the language-level module-system concept. | | module | dotfiles | In this repository, a self-contained configuration under `modules/`. Use for one program, service, or subsystem. |
| registry | dotfiles | A typed configuration namespace whose entries can be collected across hosts and reused by other configuration. | | registry | dotfiles | A typed configuration namespace whose entries can be collected across hosts and reused by other configuration. |
| Conventional Commits | Git | A commit-message format defined in `docs/conventional-commits.md`. | | Conventional Commits | Git | A commit-message format defined in `docs/conventional-commits.md`. |
| forge | Git | A web service that hosts Git repositories, pull requests, issues, and code review comments. Use when the exact provider does not matter. | | forge | Git | A web service that hosts Git repositories, pull requests, issues, and code review comments. Use when the exact provider does not matter. |
| flake | Nix | A Nix project with pinned inputs and declared outputs. Use for the repository-level build unit defined by `flake.nix`. | | flake | Nix | A Nix project with pinned inputs and declared outputs. Use for the repository-level build unit defined by `flake.nix`. |
| Nix module | Nix | A Nix language unit that declares or sets options through the Nix module system. | | assembly file | Nix | A Nix file under `flake/` that constructs flake outputs or arguments passed to NixOS modules. |
| assembly function | Nix | A project function in `flake/` that creates modules, systems, or output values. |
| library file | Nix | A Nix file that defines reusable project functions instead of a NixOS module or flake output. |
| library function | Nix | A pure project function exposed under `util`. |
| NixOS module | Nix | A Nix file evaluated by `nixosSystem` for a NixOS configuration. |
| overlay | Nix | A function that modifies a Nix package set by adding or replacing packages. | | overlay | Nix | A function that modifies a Nix package set by adding or replacing packages. |
| workspace | Window management | A named or numbered group of windows in a graphical session. Some desktop environments call this a virtual desktop. | | workspace | Window management | A named or numbered group of windows in a graphical session. Some desktop environments call this a virtual desktop. |

270
docs/nix.md Normal file
View File

@@ -0,0 +1,270 @@
# Nix Conventions
This document records local Nix style and design conventions.
Use these conventions when changing this flake.
Read this document with `docs/dictionary.md`.
## Names
### Reserve `lib` for `nixpkgs.lib`
Use `lib` only for the base `nixpkgs.lib` value.
Do not use `lib` for project functions.
Use `util` for library functions passed through module arguments.
Use `flake.mk<Name>` for assembly functions used by flake outputs.
Avoid:
```nix
specialArgs = {
lib = util;
};
```
Use:
```nix
specialArgs = {
inherit util;
};
```
Then call library functions through `util` inside modules:
```nix
{
lib,
util,
...
}:
{
networking.networkmanager.unmanaged = [ "interface-name:${util.bridgeName 10}" ];
}
```
### Name project function namespaces by role
Put pure project functions under `util`.
Put functions that create systems or output values under `flake`.
This keeps data-only functions separate from functions that carry flake context.
Avoid:
```nix
util.mkHosts { root = self + "/hosts"; }
```
Use:
```nix
flake.mkHosts { root = self + "/hosts"; }
```
## File Placement
### Put files in the directory that owns their role
Choose the file location before writing a Nix file.
Put assembly files under `flake/`.
Put library files under `lib/`.
Put modules under `modules/`.
Put host configurations under `hosts/<name>/`.
Put host-side guest wiring under `guests/`.
Put registry definitions under `registry/`.
Keep `flake.nix` focused on inputs and output wiring.
Do not add root-level Nix files other than `flake.nix`.
A module is self-contained configuration under `modules/`.
A module configures one program, service, or subsystem.
Files under `hosts/`, `guests/`, and `modules/` return NixOS modules.
### Use `default.nix` for module directories with support files
Use `default.nix` as the primary module when a module directory owns support files.
Keep sibling files for data or code read by that primary module.
Avoid:
```text
modules/shell/fish/fish.nix
modules/shell/fish/config.fish
```
Use:
```text
modules/shell/fish/default.nix
modules/shell/fish/config.fish
```
### Use non-module `default.nix` files only for directory assembly
Outside `modules/`, use `default.nix` to connect files in its directory.
Do not define primary assembly functions in `default.nix`.
Put primary assembly functions in named files.
Avoid:
```text
flake/default.nix # defines mkHost
```
Use:
```text
flake/default.nix # imports ./host.nix
flake/host.nix # defines mkHosts
```
### Keep assembly files focused on one concept
Give each assembly file under `flake/` one top-level concept.
Keep helper functions private to that file when no other file needs them.
Export the constructor for the concept when another assembly file needs it.
Name that constructor `mk<Concept>`.
Avoid:
```nix
{
inherit collectNixFiles mkHost mkHosts;
}
```
Use:
```nix
{
inherit mkHosts;
}
```
## Function Arguments
### Use closed interfaces for assembly files and library files
Use exact function argument patterns for assembly files and library files.
The caller owns the argument set for these files.
The imported file names each accepted attribute.
The imported file rejects stale or accidental extra attributes.
Avoid:
```nix
{
inputs,
lib,
self,
...
}:
```
Use:
```nix
{
inputs,
lib,
self,
}:
```
### Pass function arguments explicitly
Pass only the values an assembly file or library file needs.
Bind `lib` to the base `nixpkgs.lib` value at the call site.
Use `inherit` only for values that keep the same name.
Avoid:
```nix
import ./flake inputs
```
Use:
```nix
let
inherit (nixpkgs) lib;
in
import ./flake { inherit lib inputs self; }
```
### Keep NixOS module interfaces open
Files under `hosts/`, `guests/`, and `modules/` return NixOS modules.
`nixosSystem` owns their argument shape.
Name each argument the module uses.
Keep `...` so the module accepts standard arguments and special arguments.
Avoid:
```nix
{
config,
lib,
pkgs,
registry,
}:
```
Use:
```nix
{
config,
lib,
pkgs,
registry,
...
}:
```
## `let` Bindings
### Use role-specific binding names
A `let` binding name must explain the value's role in the expression.
Avoid names that describe only the value's type.
Avoid:
```nix
let
names = lib.attrNames hosts;
in
lib.genAttrs names mkHost
```
Use:
```nix
let
hostNames = lib.attrNames hosts;
in
lib.genAttrs hostNames mkHost
```
## Standard Library Calls
### Qualify standard library calls in flake assembly
Use qualified standard library calls inside assembly files.
Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`.
This keeps the source of each function visible.
Avoid:
```nix
let
inherit (lib) mapAttrs;
in
mapAttrs f attrs
```
Use:
```nix
lib.mapAttrs f attrs
```