Move the machine-coverage check into the framework so every deployment's gate runs it #148

Closed
opened 2026-10-21 23:26:37 +01:00 by allod-agent · 0 comments
Member

Move the machine-coverage check from the secrets template into the framework, so every deployment's gate asserts that its inventory machines, host-key table and identities name one set of machines, with no copy of the check in any data repo.

Primary goals:

  • One copy, run everywhere — the check lives in checks/ here, reads the composed data surfaces (machines, secrets.lib.machineHostKeys, the four identity sets) iterated dynamically, and reaches each deployment through the follows redirects its deploy flake already applies to this repository's inputs. A deployment forks the data repos and pins this one, so a check committed to a data repo runs only against the template.
  • Same refusals, each naming the file — a guest with no machine-host-keys.json entry; an entry naming no inventory machine; a machine with no identity; an identity naming no machine; an identity under the attrset of another machine's type (a privacy machine under devVMs, a hypervisor outside hypervisorIdentities); one name in two attrsets. Type placement replaces the primary-hypervisor rule of the secrets version: which hypervisor is primary is not visible from the identity surface this repository consumes, and the two rules refuse the same mistake.
  • Fork-safe by construction — no machine name appears in the check; its fixtures are built inside this repository, and the check passes against checks/fork-fixture/ with all three inputs overridden.
  • The secrets copy goes — once this lands, allod/secrets deletes checks/machine-coverage.nix, its index entry and README row under the deletion rule (testing.md): a cheaper witness, the deploy gate, pins the same property for every deployment instead of one template.

Current state and specifics

allod/secrets carries the check as checks/machine-coverage.nix (landed in allod/secrets#48 for allod/secrets#43). It is correct and green, and it protects only the public template: the secrets repository every deployment builds from is a private fork, and no deployment's gate runs the template's checks. Measured on the dev VM after the merge: the deploy lock bumped to the new secrets commit, and the allod-dev system derivation was byte-identical before and after, as expected for a check, while the fork that actually builds that machine has no such check.

This repository already asserts half of the property at composition (flake.nix, machineConfigurations: identityNames == machineNames) and throws on a guest without a host key when vmFacts is forced (nix/vm-facts.nix, requireHostKeys), which the deploy gate does not force. Both surface late, in the wrong repository, and name no file. The moved check names the file to edit on every refusal.

Shape here: checks/machine-coverage.nix with a diagnostics function over { machines, machineHostKeys, devIdentities, privacyIdentities, serviceIdentities, hypervisorIdentities }, the real data run plus one healthy fixture and one sabotage fixture per refusal, and a runCommand named machine-coverage-check. checks/default.nix gains the entry; flake.nix passes privacyIdentities, serviceIdentities, hypervisorIdentities and secrets.lib.machineHostKeys or null to the check index, which today receives only devIdentities and the merged identities. A null host-key table (a secrets input predating the export) is a refusal with the message nix/vm-facts.nix already uses for it, not a pass.

Validation

  • allod check . in the worktree: every step green, the new check built.
  • nix build .#checks.<system>.machine-coverage with --override-input on secrets, profiles and inventory pointing at checks/fork-fixture/ (the path: form fork-safety.sh uses): green, proving the check names nothing from the template.
  • Each refusal fired once against a sabotaged copy of the template data, and at least one rule disabled inside the check to show its fixture assertion goes red.

Scope

In: the check, its wiring, its README line, here. The secrets deletion is a second pull request in allod/secrets that refs this issue and closes it. Out: the existing machineConfigurations assertion and vm-facts.nix guards, which stay as they are; the private fork's lock bump, which is the owner's.

Move the machine-coverage check from the secrets template into the framework, so every deployment's gate asserts that its inventory machines, host-key table and identities name one set of machines, with no copy of the check in any data repo. Primary goals: - **One copy, run everywhere** — the check lives in `checks/` here, reads the composed data surfaces (`machines`, `secrets.lib.machineHostKeys`, the four identity sets) iterated dynamically, and reaches each deployment through the `follows` redirects its deploy flake already applies to this repository's inputs. A deployment forks the data repos and pins this one, so a check committed to a data repo runs only against the template. - **Same refusals, each naming the file** — a guest with no `machine-host-keys.json` entry; an entry naming no inventory machine; a machine with no identity; an identity naming no machine; an identity under the attrset of another machine's type (a privacy machine under `devVMs`, a hypervisor outside `hypervisorIdentities`); one name in two attrsets. Type placement replaces the primary-hypervisor rule of the secrets version: which hypervisor is primary is not visible from the identity surface this repository consumes, and the two rules refuse the same mistake. - **Fork-safe by construction** — no machine name appears in the check; its fixtures are built inside this repository, and the check passes against `checks/fork-fixture/` with all three inputs overridden. - **The secrets copy goes** — once this lands, `allod/secrets` deletes `checks/machine-coverage.nix`, its index entry and README row under the deletion rule (`testing.md`): a cheaper witness, the deploy gate, pins the same property for every deployment instead of one template. ### Current state and specifics `allod/secrets` carries the check as `checks/machine-coverage.nix` (landed in allod/secrets#48 for allod/secrets#43). It is correct and green, and it protects only the public template: the secrets repository every deployment builds from is a private fork, and no deployment's gate runs the template's checks. Measured on the dev VM after the merge: the deploy lock bumped to the new secrets commit, and the `allod-dev` system derivation was byte-identical before and after, as expected for a check, while the fork that actually builds that machine has no such check. This repository already asserts half of the property at composition (`flake.nix`, `machineConfigurations`: `identityNames == machineNames`) and throws on a guest without a host key when `vmFacts` is forced (`nix/vm-facts.nix`, `requireHostKeys`), which the deploy gate does not force. Both surface late, in the wrong repository, and name no file. The moved check names the file to edit on every refusal. Shape here: `checks/machine-coverage.nix` with a diagnostics function over `{ machines, machineHostKeys, devIdentities, privacyIdentities, serviceIdentities, hypervisorIdentities }`, the real data run plus one healthy fixture and one sabotage fixture per refusal, and a `runCommand` named `machine-coverage-check`. `checks/default.nix` gains the entry; `flake.nix` passes `privacyIdentities`, `serviceIdentities`, `hypervisorIdentities` and `secrets.lib.machineHostKeys or null` to the check index, which today receives only `devIdentities` and the merged `identities`. A null host-key table (a secrets input predating the export) is a refusal with the message `nix/vm-facts.nix` already uses for it, not a pass. ### Validation - `allod check .` in the worktree: every step green, the new check built. - `nix build .#checks.<system>.machine-coverage` with `--override-input` on `secrets`, `profiles` and `inventory` pointing at `checks/fork-fixture/` (the `path:` form `fork-safety.sh` uses): green, proving the check names nothing from the template. - Each refusal fired once against a sabotaged copy of the template data, and at least one rule disabled inside the check to show its fixture assertion goes red. ### Scope In: the check, its wiring, its README line, here. The secrets deletion is a second pull request in `allod/secrets` that refs this issue and closes it. Out: the existing `machineConfigurations` assertion and `vm-facts.nix` guards, which stay as they are; the private fork's lock bump, which is the owner's.
vnprc closed this issue 2026-10-22 00:41:48 +01:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
allod/archetypes#148
No description provided.