Credential registry: value templates and verify commands replace the format and probe enums #24
No reviewers
Labels
No labels
blocked
bug
decision
duplicate
enhancement
handoff
help wanted
invalid
landed?
question
ready-to-merge
stale
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/secrets!24
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/secret-value-templates"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Nothing changes on a running machine: this PR changes the public secrets template's registry contract and its check, and no deployment reads this template's registry. It replaces the three hand-named credential formats and the verify-probe enum with one declared shape: a credential's non-secret text is a
value.templatewith exactly one{secret}placeholder (or novaluewhen the plaintext is the secret itself), an optionalvalue.encodedrawn from the newlib.credentialEncodingsexport, and oneverifycommand string per target. The public example credential is migrated to that shape. During the private migration a credential may still be wholly legacy (formatplus structuredverify.type), never a mixture, and the newcredential-registrycheck enforces all of that with one sabotage witness per rule;lib.forgejoTokenGroupsnow validates at its export seam so a bad registry fails every consumer, not onlynix flake check. Merge this after the archetypes PR (whose check must already accept the new example) and before the tools PR. If it is wrong, revert it: the legacy shape stays valid everywhere until the tools PR lands, and no ciphertext is touched.What changes
flake.nix:lib.credentialEncodings = [ "rclone-obscure" ]exported;credentialRegistryDiagnosticsandvalidateCredentialRegistryimplement the contract (exactly one{secret}, encoder membership, non-empty one-lineverifyon every target, at least one target per credential and one credential per group, legacy-or-new but never both on one credential, one encoding shared by a group's new-shape credentials);lib.forgejoTokenGroupsis validated at the export seam.checks.<platform>.credential-registry: validates the shipped registry, a positive legacy-plus-new coexistence fixture, a positive legacy-plus-encoded fixture, and one sabotage fixture per rule, each proven to trip only its own rule.forgejo-token-groups.json: the public example moves fromformat = "credential-store-url"tovalue.templateand averifycommand, byte-identical to the example in allod/secrets#23.README.md: the export table gainslib.credentialEncodingsand the check; a "Forgejo credential registry schema" section states the contract, the coexistence rule, and the example verification commands that replace the former probe names.Risk
R3 in the plan (shared secrets schema and transition compatibility). Residual after the check: a rule that accepts an input the tools renderer or archetypes consumer rejects, or the reverse; both consumers fail loud on such an entry, and the private registry is not read by this template. Rollback is a revert; legacy entries and
rotate-tokenremain valid until the tools PR closes the issue.Validation
nix flake check .in the worktree (plain path pernix.md): ``all checks passed!, exit 0git diff --check:no output, exit 0the check itself now asserts that each of its 20 sabotage fixtures produces exactly its own diagnostic, so a vacuous fixture is a red check; with the encoder rule removed it fails withunexported-encoder wanted [value.encode is not an exported encoding] got [], and likewise for the mix rule (worker-run, captured output read by the overseer). Export seam, run by the overseer: with{secret}removed from the public template,nix eval .#lib.forgejoTokenGroupsexits 1 witherror: credential-registry: value.template must contain exactly one {secret}; the file was restored byte-for-byteclaude-opus-5through thepirunner on providernullsink-claudeat thinkinghigh(2 blockers, 4 gaps, 1 simplify: vacuous encoder and mixed-shape sabotage fixtures, legacy credentials counted as an encoding, vacuous empty-targets acceptance, four unwitnessed guards, the unvalidated export, constant assertion messages) and ``claude-fable-5-1as a fresh Claude Code subagent at default effort (2 blockers, 3 gaps, 1 simplify, 2 questions: the same two vacuous fixtures, no witness for a missing or multi-lineverify, the legacy-encoding rule, an undocumented extra-fields rule, the unvalidated export, blank commands and empty targets, and the merge order). All accepted findings are fixed in this diff. The author of the original diff was a Codex model, so both reviewers are cross-family.Refs allod/secrets#23
A credential's non-secret text is value.template with exactly one {secret} placeholder, or no value when the plaintext is the secret; value.encode is drawn from the new lib.credentialEncodings export; each target carries one verify command string. The credential-registry check enforces the contract and the legacy-or-new coexistence rule with one sabotage fixture per rule, each asserted to trip exactly its own diagnostic; lib.forgejoTokenGroups validates at its export seam. The public example moves to the new shape. Refs allod/secrets#23