Skip to content

feat: port entity schema to gen-schema#563

Draft
sini wants to merge 29 commits into
denful:mainfrom
sini:feat/entity-gen-schema-port
Draft

feat: port entity schema to gen-schema#563
sini wants to merge 29 commits into
denful:mainfrom
sini:feat/entity-gen-schema-port

Conversation

@sini
Copy link
Copy Markdown
Collaborator

@sini sini commented May 21, 2026

Summary

  • Replace hand-rolled schemaEntryType in options.nix with gen-schema's mkSchemaOption (sidecars: includes, excludes; computed: isEntity)
  • Add flat-form entity declarations alongside legacy two-level form for both hosts and homes
  • Wire _topology and _meta introspection from gen-schema
  • Extract resolvedCtxModule to shared _types.nix for reuse across entity types

Details

Schema port: den.schema now uses gen-schema's mkSchemaEntryType which provides sidecar extraction, computed fields, and __functor wrapping. The resolvedCtxModule (id_hash, resolved, collisionPolicy) is extracted to _types.nix and injected into entity submodule imports.

Flat form: Both den.hosts and den.homes now accept flat declarations:

den.hosts.igloo = { system = "x86_64-linux"; users.tux = { }; };
den.homes."tux@igloo" = { system = "x86_64-linux"; };

A deepMergeAttrs custom type accepts both forms, and apply preprocesses flat entries into the canonical two-level shape via preprocessHosts. All 6 consumers see the unchanged { system.name = entity } shape.

Tests: 18 new tests (843 total, up from 825) covering flat hosts, flat homes, id_hash, freeform attrs, topology, meta introspection, isEntity computed, and schema sidecars.

Test plan

  • All 843 CI tests pass (nix develop -c just ci)
  • Flat host form produces correct two-level shape
  • Flat home form with @-name parsing works
  • Mixed flat + legacy forms coexist
  • Cross-entity host lookup from homes preserved
  • Existing templates (default, minimal, example) unaffected

@github-actions github-actions Bot added the allow-ci allow all CI integration tests label May 21, 2026
sini added 19 commits May 21, 2026 10:18
Replaces hand-rolled schemaEntryType with gen-schema mkSchemaOption.
Sidecars: includes, excludes. Computed: isEntity (structural content only).
Extracts resolvedCtxModule (id_hash, resolved, collisionPolicy) to
_types.nix for entity type reuse. collisionPolicy flows through deferred
module merge to entity instances (not a sidecar) preserving existing
ctx.host.collisionPolicy resolution path.
den.hosts now accepts both forms:
  - Legacy: den.hosts.x86_64-linux.igloo = { ... }
  - Flat:   den.hosts.igloo = { system = "x86_64-linux"; ... }

The outer option type uses a permissive submodule with deepMergeAttrs
freeformType (lib.recursiveUpdate-based merge that avoids the infinite
recursion lib.types.anything causes with cross-option references).
The apply function preprocesses flat entries into two-level form and
re-evaluates through the original attrsOf systemType, so all 6
consumers see the canonical { system.name = hostConfig } shape.
Same pattern as den.hosts: deepMergeAttrs + preprocessHosts + apply.
Cross-entity host lookup and osConfig injection preserved.
Covers: id_hash, freeform, topology, meta introspection,
isEntity computed, schema includes sidecar.
Update flake inputs and references to match the renamed repo
at github:sini/gen-schema.
@sini sini force-pushed the feat/entity-gen-schema-port branch from 6574fac to a370d30 Compare May 21, 2026 22:37
sini added 9 commits May 21, 2026 23:12
Nested aspects from freeform traversal (e.g., den.aspects.disk.zfs-disk-single)
have __provider set by aspectContentType.merge but lack name/meta. Use __provider
to derive the path key, matching how the pathSet stores these entries.
- has-aspect.nix: accept refs with __provider (set by aspectContentType)
- types.nix: annotate nested attrset children in content merger with
  __provider so deeply nested aspects carry provenance
- Only annotate unregistered keys (skip class/pipe/structural keys)
- Tests: nested present/absent, provenance distinct, deeply nested (3 levels)
Unlike pipe.collect which only collects from sibling scopes (same parent),
collectAll searches ALL scopes regardless of parent. Useful for cross-subtree
collection in fleet topologies where hosts span multiple environments.
Flat class-to-class routes (e.g. homeLinux→homeManager) don't need
path nesting, but route/apply.nix requires path to be present. Default
to [] so callers don't need to specify it for simple forwarding.
Covers the pattern where one aspect uses inherit (config.systemd)
network in boot.initrd.systemd alongside services definitions, while
another aspect also defines boot.initrd.systemd.services. Passes in
den's test env but known to fail in complex configs (nix-config) due
to NixOS module evaluation order — mkMerge workaround needed there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

allow-ci allow all CI integration tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant