SSH authentication
Guardian and co-guardian SSH keys are optional. They add a cryptographic signature to the
accepted → roadmap transition.
The important distinction:
- comparing a public key with a stored key is identification, not authentication;
- a signature over a fresh nonce proves possession of the private key;
- mdBoard stores only the public key and fingerprint; it never stores a private key.
When the gate is active
| Configuration | Roadmap transition |
|---|---|
| No guardian or co-guardian key | Allowed; low-security hint |
| At least one key | Requires a valid challenge signature |
| Malformed key | Fails closed |
First-time setup
The simplest path is during init:
mdboard init . --ssh-key ~/.ssh/id_ed25519.pub
Or add a key later:
mdboard --actor agent guardian ssh-add \
--email guardian@example.com \
--key ~/.ssh/id_ed25519.pub \
--authorised-by guardian \
--authorization "Add my guardian SSH key."
Show configured keys:
mdboard guardian ssh-show
Remove a key:
mdboard --actor agent guardian ssh-remove \
--email guardian@example.com \
--authorised-by guardian \
--authorization "Remove the guardian SSH key."
Removing the last key disables the gate.
Sign a roadmap transition
Create a challenge for the card:
mdboard --actor agent guardian ssh-challenge '#0042'
It prints a nonce. Save the nonce exactly:
printf '%s' '<nonce>' > /tmp/mdboard-nonce
Sign it with the private key:
ssh-keygen -Y sign -f ~/.ssh/id_ed25519 -n mdboard /tmp/mdboard-nonce
Verify and record:
mdboard --actor agent guardian ssh-verify '#0042' \
--nonce '<nonce>' \
--signature /tmp/mdboard-nonce.sig \
--email guardian@example.com
Then roadmap the card:
mdboard --actor agent roadmap '#0042' \
--authorised-by guardian \
--authorization "Roadmap with a signed guardian transition."
What is audited
- Challenge creation.
- Successful verification: signer e-mail, fingerprint and nonce.
- Failed verification: the error is returned; no verification event is written.
- Key changes: the config change and its owner authorisation.
Failure modes
| Failure | Result |
|---|---|
| No nonce or unknown nonce | Rejected |
| Reused nonce | Rejected |
| Invalid or missing signature | Rejected |
| No key for the signer | Rejected |
| Malformed configured key | Fails closed |
ssh-keygen unavailable |
Rejected with an error |
Low-security mode
When no key is configured, the project still works. The agent should warn the guardian once per pitch session:
- the roadmap commitment is authenticated only by chat authorisation;
- adding an SSH key makes the transition require proof of private-key possession;
- this is optional, not a gate that blocks existing projects.
Limits
- One key per guardian or co-guardian; replacing it is rotation.
- Keys live in
mdboard.toml, which is owner-only. - A signature proves possession of the private key, not the human’s legal identity.
- This is identification plus a fresh signature, layered on the existing human authorisation.