Skip to content

feat(modules): export the Sensorica event profile once (#33) - #59

Merged
Soushi888 merged 4 commits into
mainfrom
feat/event-profile
Sep 28, 2026
Merged

Soushi888 merged 4 commits into
mainfrom
feat/event-profile

Conversation

@Soushi888

Copy link
Copy Markdown
Contributor

SoushAI analysis. Drafted by Soushi's AI assistant, reviewed and posted by @Soushi888.

Closes #33.

Why

The Sensorica workshop event profile (Holochain 0.6 line, three hApps, one network seed) existed twice: examples/sensorica-fleet/flake.nix computed fleetLine/fleetHapps from the root flake's own holochain-0_6/hc-0_6 outputs and happs.nix, and Soushi's private homelab rehearses the same workshop node by importing examples/sensorica-fleet/happs.nix by path and repeating the line, the three hApps and the seed. Two copies drift.

What

  • modules/sensorica-event-node.nix (new): a NixOS module, exported as nixosModules.sensorica-event-node, that sets services.holochain-edgenode's package, hcPackage, happs (hREA, Kando, Requests & Offers, all on network seed sensorica-workshop-2026), installerTimeout (900s) and the two metrics enables (metricsExporter, conductorMetrics), all via mkDefault so a host overrides any one of them with an ordinary assignment. Declares no options of its own. Deliberately not part of nixosModules.default — the other four modules are generic capabilities, and this one is the workshop's opinionated hApp set.
  • modules/sensorica-happs.nix (moved from examples/sensorica-fleet/happs.nix): the three hApp bundles, fetched by hash, hash-and-URL comments intact. Nothing binary entered git before or after.
  • examples/sensorica-fleet: flake.nix now imports nixosModules.sensorica-event-node in fleetModules instead of computing fleetLine/fleetHapps itself; hosts/common.nix dropped the now-redundant package/hcPackage/happs/installerTimeout/metrics settings (kept enable/openFirewall, which stay host-specific); a new input holonix-0_6.follows = "nixos-holochain/holonix-0_6" was added (the profile module resolves its 0.6-line packages through that input, the same way the existing holonix follow serves holochain-edgenode's own default package); flake.lock was relocked for that one new input only (verified: 4-line diff, no repin of nixos-holochain).
  • checks.eventProfileParity (new, in examples/sensorica-fleet/flake.nix): fails evaluation if edgenode-01's effective package, hApp srcs, network seeds, installer timeout or metrics enables ever diverge from the module's own defaults (evaluated fresh via lib.evalModules with _module.check = false, the same trick docs/module-options.md's generator already uses). The assertion is forced while the check derivation is constructed, so nix flake check --no-build — what CI and the review commands run — catches a divergence without building anything.
  • docs/module-options.md: unchanged. The new module declares no options, so a fresh nix build .#options-doc diffs identical to the committed file (verified).

A correctness finding along the way

The first version of the module set happs = lib.mkDefault { hrea = {...}; kando = {...}; requests-and-offers = {...}; }; as one whole-attrset default, on the assumption that NixOS's module system pushes an outer mkDefault recursively down through a nested attribute set (pushDownProperties). Verified empirically (minimal lib.evalModules reproduction, then confirmed against the real modules) that this does not hold for attrsOf (submodule ...): a host overriding just one hApp's networkSeed left that hApp's src "accessed but has no value defined" — the sibling override discarded the whole-set default rather than leaving it in place. Fixed by setting happs.<app>.src and happs.<app>.networkSeed each as their own mkDefault, which does survive a sibling override (reproduced and confirmed both ways). The module's header comment documents this.

How to test

From a checkout of this branch:

nix run nixpkgs#alejandra -- --check .
# → "Congratulations! Your code complies with the Alejandra style." exit 0

nix flake check --no-build --accept-flake-config --show-trace
# → exit 0 (root; nixosModules.sensorica-event-node listed and evaluated)

cd examples/sensorica-fleet
nix flake check --no-build --show-trace --override-input nixos-holochain <path-to-checkout>
# → exit 0; checks.x86_64-linux.eventProfileParity evaluates clean

Falsifier, run and reverted before this PR: added services.holochain-edgenode.happs.hrea.networkSeed = "drifted-seed"; to hosts/edgenode-01/configuration.nix, reran the example's nix flake check --no-build --override-input ...:

error: edgenode-01 diverges from nixosModules.sensorica-event-node on: happs

exit 1, no build attempted. Reverted, reran, exit 0 again.

docs/module-options.md sync also checked directly: diff <(nix build .#options-doc --print-out-paths) docs/module-options.md — no diff, exit 0 (matches what CI's "Option reference is in sync" step checks).

Consumer snippet (external host, e.g. the homelab)

# inputs: holonix-0_6.follows = "nixos-holochain/holonix-0_6";
modules = [nixos-holochain.nixosModules.holochain-edgenode nixos-holochain.nixosModules.sensorica-event-node];

That is the whole profile. Documented in examples/sensorica-fleet/README.md under "Consuming the event profile from another host".

Not covered

  • VM checks: none of the root flake's existing checks.* (vmTest*, conductorMetricsJq, etc.) import nixosModules.sensorica-event-node or nixosModules.default, and this PR doesn't touch holochain-edgenode.nix or any other module those checks exercise, so none needed rerunning. nix build of a VM check isn't possible in this sandbox anyway (no /dev/kvm).
  • docs/architecture.md: scoped to the four generic modules' internal mechanics (systemd units, network config generation); the new module adds no options or units, so left untouched. The consumer-facing documentation lives in the example README per the issue's own "done when" wording.
  • The private homelab repo: not touched, per instructions; this PR only reports the attribute and snippet an external flake would write.
  • CI's explicit VM-build list (.github/workflows/ci.yml's "Build the VM tests" step) wasn't extended to name eventProfileParity: that check lives in the example flake's own checks, not the root flake's, and nix flake check --no-build (already run against the example in the check job) fully exercises it — verified above, since the assertion is forced during evaluation, not during build.

Add nixosModules.sensorica-event-node, exporting the workshop event
profile (Holochain 0.6 line, hREA/Kando/Requests & Offers, one network
seed, the installer timeout and the two metrics options) as a single
NixOS module layered on holochain-edgenode. examples/sensorica-fleet
now imports it instead of computing fleetLine/fleetHapps itself, and
modules/sensorica-happs.nix (moved from examples/sensorica-fleet/happs.nix)
is the one place the three hApp bundles are fetched.

checks.eventProfileParity (examples/sensorica-fleet/flake.nix) fails
evaluation under nix flake check --no-build if edgenode-01's effective
package, hApp srcs, seeds, installer timeout or metrics enables ever
diverge from the module's own defaults.

happs is set leaf by leaf with mkDefault rather than as one
mkDefault {...} attrset: attrsOf submodule merging does not push an
outer mkDefault recursively through a raw nested attribute set, so a
host overriding one hApp's networkSeed left its src undefined until
this was corrected (verified empirically before landing).
The previous commit's happs = mkDefault {...} whole-attrset default was
never actually staged in that form after the empirical fix described
in its own commit message and header comment landed on disk; this
commit is that fix, staged. attrsOf submodule merging does not push an
outer mkDefault recursively through a raw nested attribute set, so a
host overriding one hApp's networkSeed left its src undefined. Each
happs.<app>.src and happs.<app>.networkSeed now carries its own
mkDefault, which does survive a sibling override (reproduced both ways
with a minimal lib.evalModules case and against the real module).
Soushi888 added a commit that referenced this pull request Sep 27, 2026
…a-event-node

Once #59 and #61 are both in, hosts/common.nix no longer reads fleetLine and fleetHapps: the fleet imports nixosModules.sensorica-event-node for them. holoportTarget still passed the old arguments, so the installed system had no hApps, no installer unit, and vmTestHoloportInstall failed ("holochain-happ-installer.service is inactive and there are no pending jobs"). It now imports the module the fleet imports, and the check passes: hrea, kando and requests-and-offers enabled 20 to 43 s after boot.
…stalled = false

A plain happs assignment is merged with the profile's keys, since happs is
attrsOf submodule, so the per-leaf defaults still fill in every workshop
hApp. The module comment and the fleet README claimed otherwise.
@Soushi888

Copy link
Copy Markdown
Contributor Author

SoushAI analysis. Drafted by Soushi's AI assistant, reviewed and posted by @Soushi888.

Review fixes pushed (407b5ff, f047c15)

Blocking item fixed: the false override claim. happs is attrsOf (submodule ...), so a plain happs = { hrea = ...; }; is merged with the profile's keys and the per-leaf mkDefaults still fill in the other apps. The comment at the top of modules/sensorica-event-node.nix and examples/sensorica-fleet/README.md both said a plain reassignment trims the set. Both now say what actually works: happs.<app>.installed = false; to drop one app, or happs = lib.mkForce { ... }; to replace the set. The README keeps the true half of the old sentence, since a single value such as the seed does override with an ordinary assignment. I also removed an em-dash from the module comment paragraph I rewrote.

Evidence, evaluated against edgenode-01 in the example fleet (checkout override) via extendModules:

  • plain happs = { hrea = {}; } gives ["hrea","kando","requests-and-offers"]

  • happs = lib.mkForce { hrea = ...; } gives ["hrea"]

  • happs.kando.installed = false removes kando.happ from the installer's references (1 before, 0 after) and from the toplevel closure (0), so the bundle is never fetched or built, which is what the new comment claims

Merge of origin/main (407b5ff). The PR was conflicting after #62 landed. The one conflict was the nixosModules block in flake.nix: main's holochain-bootstrap and wrapped default (with bootstrapPackage) are kept as main has them, and sensorica-event-node is added after them, still outside default.

Local checks on f047c15:

  • nix flake check --no-build --all-systems (root): exit 0

  • nix flake check --no-build --override-input nixos-holochain <checkout> in examples/sensorica-fleet: exit 0, and checks.x86_64-linux.eventProfileParity built and printed ok

  • toplevel drvPath evaluates for edgenode-01 to 05 and workshop-iso

  • minimal and fleet templates initialised and flake-checked against the checkout: both pass

  • docs/module-options.md matches a fresh .#options-doc build (no option changed)

VM tests were not run locally: neither change touches a module the VM tests exercise.

Not done here, still open from the review: lab commit 92cf87f has to ride with whichever of #59 and #61 merges second. It is not needed on this branch while #61 is unmerged. After this merges, examples/sensorica-fleet/flake.lock needs a relock to main, because the plain nix flake check --no-build without --override-input will not find nixosModules.sensorica-event-node until then.

@Soushi888
Soushi888 merged commit beb1d68 into main Sep 28, 2026
2 checks passed
Soushi888 added a commit that referenced this pull request Sep 28, 2026
…a-event-node

Once #59 and #61 are both in, hosts/common.nix no longer reads fleetLine and fleetHapps: the fleet imports nixosModules.sensorica-event-node for them. holoportTarget still passed the old arguments, so the installed system had no hApps, no installer unit, and vmTestHoloportInstall failed ("holochain-happ-installer.service is inactive and there are no pending jobs"). It now imports the module the fleet imports, and the check passes: hrea, kando and requests-and-offers enabled 20 to 43 s after boot.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

flake: export the event node profile

1 participant