secret declare: take the host recipient term from the target secrets.nix #275

Closed
allod-agent wants to merge 2 commits from agent/declare-host-recipient into master
Member

allod secret declare no longer writes [ hostKey ] as the start of the new recipient line. It reads the existing publicKeys lines in the target secrets.nix and opens the new line with the term they all open with, so a secrets repo that binds the hypervisor's keys under another name gets a line that evaluates there. If those lines do not agree on one term, or a line opens with something that is not a name or a bracketed list, declare refuses before writing anything and lists what each line starts with. On the template and on any repo whose lines open with [ hostKey ] the output is byte for byte what it was. What proves it: the existing declare tests still produce the same files, a fork fixture with hostKeys and no hostKey gets hostKeys ++ vmKeys "dev-a" and hostKeys;, and three disagreeing fixtures are refused with every file untouched. If it is wrong, revert the one commit; declare writes only text an agent reviews in a PR, and the repo's own checks still gate the ciphertext at create time.

What changed

  • declareHostRecipientTerm reads the leading term of each matched line: a nix name, a dotted name, or one bracketed list, standing alone or followed by ++. One shared term is used; anything else is a refusal naming the file, the count of lines, and what each one starts with.
  • declareSecretsRecipients takes that term instead of a literal.
  • Help text and docs/allod-secret.md say where the term comes from and what is refused.

Noticed, not changed

The public template's secrets.nix now derives every entry (allod/secrets#40 and the forge-key and host-key maps), so it has no top-level "secrets/<name>.age".publicKeys line at all. declare already refuses it with no existing publicKeys line to insert after, before and after this change. That is a separate defect in how declare finds its insertion point and in what the template offers it; this PR does not touch it.

Risk

R1. One command's generated text, in a function with no side effects, gated by the same in-memory validation and same-bytes-on-disk checks as before. No secrets read, no git behaviour changed. Rollback is a revert.

Validation

  • gofmt -l cmd/allod clean; go vet ./... and go vet -tags site,secret ./... clean.
  • go test ./..., go test -tags secret ./cmd/allod/, and go test -tags site,secret ./... pass, run from nix develop.
  • New: a fork fixture binding hostKeys with no hostKey yields the fork's term for a VM target and for the host alone, and the written file never gains the template's name; three refusal fixtures (two terms, VM keys first, a nested list) each name the file and what was found and leave all three files untouched; a table test over the term grammar.
  • Not run: declare against a real fork's secrets.nix followed by nix flake check. The fixture reproduces the shape the issue describes, a list bound under another name with no hostKey.

Closes allod/tools#271

`allod secret declare` no longer writes `[ hostKey ]` as the start of the new recipient line. It reads the existing `publicKeys` lines in the target `secrets.nix` and opens the new line with the term they all open with, so a secrets repo that binds the hypervisor's keys under another name gets a line that evaluates there. If those lines do not agree on one term, or a line opens with something that is not a name or a bracketed list, `declare` refuses before writing anything and lists what each line starts with. On the template and on any repo whose lines open with `[ hostKey ]` the output is byte for byte what it was. What proves it: the existing declare tests still produce the same files, a fork fixture with `hostKeys` and no `hostKey` gets `hostKeys ++ vmKeys "dev-a"` and `hostKeys;`, and three disagreeing fixtures are refused with every file untouched. If it is wrong, revert the one commit; `declare` writes only text an agent reviews in a PR, and the repo's own checks still gate the ciphertext at `create` time. ## What changed - `declareHostRecipientTerm` reads the leading term of each matched line: a nix name, a dotted name, or one bracketed list, standing alone or followed by `++`. One shared term is used; anything else is a refusal naming the file, the count of lines, and what each one starts with. - `declareSecretsRecipients` takes that term instead of a literal. - Help text and `docs/allod-secret.md` say where the term comes from and what is refused. ## Noticed, not changed The public template's `secrets.nix` now derives every entry (allod/secrets#40 and the forge-key and host-key maps), so it has no top-level `"secrets/<name>.age".publicKeys` line at all. `declare` already refuses it with `no existing publicKeys line to insert after`, before and after this change. That is a separate defect in how `declare` finds its insertion point and in what the template offers it; this PR does not touch it. ## Risk R1. One command's generated text, in a function with no side effects, gated by the same in-memory validation and same-bytes-on-disk checks as before. No secrets read, no git behaviour changed. Rollback is a revert. ## Validation - `gofmt -l cmd/allod` clean; `go vet ./...` and `go vet -tags site,secret ./...` clean. - `go test ./...`, `go test -tags secret ./cmd/allod/`, and `go test -tags site,secret ./...` pass, run from `nix develop`. - New: a fork fixture binding `hostKeys` with no `hostKey` yields the fork's term for a VM target and for the host alone, and the written file never gains the template's name; three refusal fixtures (two terms, VM keys first, a nested list) each name the file and what was found and leave all three files untouched; a table test over the term grammar. - Not run: `declare` against a real fork's `secrets.nix` followed by `nix flake check`. The fixture reproduces the shape the issue describes, a list bound under another name with no `hostKey`. Closes allod/tools#271
The recipient line opened with a literal "[ hostKey ]", which evaluates only in a secrets repo that binds that name; a fork binding the hypervisor keys under another name got a line that failed at create time while declare reported success. declare now opens the line with the term every existing publicKeys line in the file opens with, and refuses, naming what each line starts with, when they do not agree on one.

Refs allod/tools#271
Author
Member

Owner request: too many comments. Cutting every comment this diff adds to a contract, a trap, or a pointer, one to three lines each, and deleting the rest.

Owner request: too many comments. Cutting every comment this diff adds to a contract, a trap, or a pointer, one to three lines each, and deleting the rest.
Author
Member

Closed unmerged by the owner's decision. This fixes the symptom at the tool while keeping the cause: declare hand-writes a recipient line into a fork's secrets.nix. The proper fix derives those recipients from the rotation registry inside the secrets repo, after which declare writes no secrets.nix line at all and this code has nothing to parse. The replacement issue is filed on allod/secrets and linked from allod/tools#271.

Closed unmerged by the owner's decision. This fixes the symptom at the tool while keeping the cause: declare hand-writes a recipient line into a fork's secrets.nix. The proper fix derives those recipients from the rotation registry inside the secrets repo, after which declare writes no secrets.nix line at all and this code has nothing to parse. The replacement issue is filed on allod/secrets and linked from allod/tools#271.
allod-agent closed this pull request 2026-10-18 23:00:13 +01:00

Pull request closed

Sign in to join this conversation.
No description provided.