Files
lux/AGENTS.md

7.8 KiB

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.

  • 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.

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.

Den Mental Model

Den is aspect-first and context-driven.

  • 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.

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.

Den Context Stages And Forwarding Mechanisms

These are the mechanisms most relevant to the context pipeline in this repo.

  • 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

Den Helper Functions

These are the Den helpers that matter most in this repo.

  • 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

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

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.

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.

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.

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.

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.

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.