Skip to content

Mint one Ed25519 key per reviewing workstation (public key in the repo, private key in that Bot's secret store) #1111

Closed as not planned

Description

@Birfy

Written-by: Triage

Split out of #1110: the code half is a Bot's, this half needs the owner. Ed25519, one keypair per reviewing workstation (the earlier HMAC wording on this issue is dead — a shared key has to live in Actions, so it is a repository secret that anyone who can start a workflow could use).

What the owner does, exactly

Per workstation, starting with Reviewer and then Reviewer2:

openssl genpkey -algorithm ed25519 -out reviewer.pem
openssl pkey -in reviewer.pem -pubout -outform DER | base64 | tr '+/' '-_' | tr -d '='
  1. Keep the .pem wherever you are comfortable generating keys. It never goes into this repository, this issue, a group message, or any command whose output is posted.
  2. Paste the base64url DER line from the second command into this issue — a public key is safe to post.
  3. Put the private key into that workstation's own secret store through its secure card: DSH_SECRET_VERDICT_KEY_REVIEWER, DSH_SECRET_VERDICT_KEY_REVIEWER2. That is the one channel where the Bot can use the key without printing it.

Why a Bot must not generate its own key

Every Bot runs as the same OS user on the same machine, so a key file written by one Bot is readable by all of them. Only the per-Bot secret store has a boundary, and only the owner can write to it.

Acceptance

  • both public keys are posted here (base64url DER, ~60 characters each);
  • each workstation can sign a throwaway verdict and that signature verifies under its published public key, and under nothing else;
  • Reviewer's key does not verify Reviewer2's signature, and vice versa;
  • no private key, seed, or PEM body ever appears in the repository, this issue, or the group.

Blocking

#1110 must not merge before the two public keys exist: its verifier is fail-closed with no unsigned window, so a verifier on main without keys would freeze every merge at once. Once the keys are in place, #1110 lands and both workstations can sign from that minute.

Activity

  1. added
    enhancementNew feature or request
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    area:automationScheduled tasks and automation
    on Oct 25, 2026
  2. Birfy commented on Oct 25, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    Rewritten for Ed25519 — the HMAC version of this issue is dead (a shared key has to live in Actions, so it is a repository secret). #1110 carries the format; this is the key handoff, and only the owner can do it.

    What the owner does, exactly

    Per workstation (start with Reviewer, then Reviewer2):

    openssl genpkey -algorithm ed25519 -out reviewer.pem
    openssl pkey -in reviewer.pem -pubout -outform DER | base64 | tr '+/' '-_' | tr -d '='
    1. Keep reviewer.pem wherever you are comfortable generating keys — it never goes into a chat, a file in this repo, or a shell command whose output is posted.
    2. Paste the base64url DER line (the second command's output) into this issue — a public key is safe to post.
    3. Put the private key into that workstation's own secret store through its secure card, as DSH_SECRET_VERDICT_KEY_REVIEWER (and …_REVIEWER2). That is the one channel where the Bot gets the key without ever printing it.

    Why not let the Bot generate its own key

    Every Bot runs as the same OS user on the same machine, so a key file written by one is readable by the others — that would put the private half back in a shared place, which is exactly what this issue exists to prevent. The per-Bot secret store is the only storage with a per-Bot boundary, and only the owner can write to it.

    Acceptance

    • Both public keys are posted here (base64url DER, ~60 chars).
    • Each workstation can produce a signature and that signature verifies against its published key — one throwaway PR is enough to prove it, and it must be done before A forged Written-by: Reviewer still merges: the guard cannot tell which workstation wrote a Verdict #1110 merges.
    • A signature made by Reviewer's key verifies under nothing but Reviewer's public key; Reviewer2's key fails on it.
    • Nothing that reaches the repository, this issue, or the group ever contains a private key, a seed, or a PEM body.

    Blocking

    #1110 must not merge before the first two items exist: there is no unsigned compatibility window, so a verifier on main with no keys would freeze every merge at once. Once the keys are in place, #1110 lands and every workstation can sign from that minute.

  3. changed the title [-]Mint one HMAC key per reviewing workstation (Actions secret + each Bot's secret store)[/-] [+]Mint one Ed25519 key per reviewing workstation (public key in the repo, private key in that Bot's secret store)[/+] on Oct 25, 2026
  4. Birfy commented on Oct 25, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    Closed as not planned by the owner's decision (2026-10-25): no signing keys are introduced. The owner was asked for two Ed25519 public keys and said the setup is not worth it — so this issue does not get built, and nobody needs to generate a keypair or paste a secret card.

    What replaces it — the three cheap gates we already run, and nothing more: a conclusion must name the current tip (tip moves → old conclusion is void), one conclusion per tip, and Attestation: as a self-report. Together those catch everything we have actually hit: verdicts written against a stale sha, a verdict replayed on a new tip, and mechanical misjudgements.

    What stays open, stated plainly so it is not forgotten: any Bot holding the shared Birfy account can still write a fake Verdict: PASS. The three gates do not stop deliberate forgery from inside. Closing that would need a per-workstation account or a per-workstation key; both were declined. This is an accepted residual risk, recorded here, not a solved problem.

    Code state: #1137 (signed conclusions) is merged into main and stays, inert. Its switch is the signers list in .github/agent/review-policy.json; that list is null and .github/agent/signers.json does not exist, so behaviour is exactly what it was before the merge. If the call is ever revisited, enabling it is those two config lines plus the keys — no code work. #1110 is merged and is not rolled back.

  5. removed
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:automationScheduled tasks and automationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions