install.sh: verify releases via SSHSIG (ssh-keygen -Y) and drop the minisign prerequisite #23

Closed
opened 2026-10-06 18:51:26 +00:00 by jsutter · 2 comments
Owner

Part of the simplify-first-run-install arc. Motivating incident: a new user's very first install (ditc v3.5.0, macOS 26) stalled at the minisign hard gate — the welcome-page command refused with "Refusing to install: minisign is not installed" and the user had to discover brew install minisign unprompted. dit-client#216 made signature verification MANDATORY because the old shared key was retired and no documented install ever crypto-verified — but #216 mandates the PROPERTY (release bytes anchored to a key the forge cannot forge, fail-closed), not minisign-the-tool.

Proposal

Replace the minisign prerequisite with SSHSIG (ssh-keygen -Y verify), which ships by default on macOS, Linux, and Windows (OpenSSH client) — zero client-side prerequisites on every ditc target.

Scope

  1. Release CI publishes SHA256SUMS.sshsig alongside SHA256SUMS.minisig (new per-tool Ed25519 release key, same CI/secret-store custody as the current minisign key; .minisig keeps shipping during a transition window so already-installed binaries keep self-updating).
  2. install.sh replaces the minisign hard gate with ssh-keygen -Y verify against an embedded per-tool allowed-signers block (identity ditc-release@deepnet — mirrors today's embedded per-tool pubkeys; rotation = add a key line). Missing ssh-keygen → printed per-OS hint + exit ≠0, never auto-install.
  3. Retry-on-verify-fail loop and fail-closed semantics unchanged (#34, #543).
  4. Remove the curl … | bash -s -- usage header from install.sh — it bypasses the welcome line's hash pin and contradicts the script's own D7/SC-3 doctrine.
  5. Correct the in-script attribution: the mandatory-verification gate is dit-client#216, not "dit-releases#216".
  6. Parity: install.ps1 currently vendors minisign 0.11 (#20) so Windows has no external prereq — migrate it to SSHSIG in the same window or explicitly defer with a note; do not leave the two installers on divergent verification primitives past the transition.

Acceptance criteria

  • A pinned install succeeds end-to-end in a debian:12-slim container with NO minisign and NO package installs.
  • The macOS journey requires zero brew (no minisign install step).
  • A tampered .sshsig fails closed (non-zero exit, nothing installed).
  • tests/install-signing.sh proves: absent-minisign gate is gone; absent-ssh-keygen prints the hint and exits non-zero; verified and tampered paths both covered.
Part of the simplify-first-run-install arc. Motivating incident: a new user's very first install (ditc v3.5.0, macOS 26) stalled at the minisign hard gate — the welcome-page command refused with "Refusing to install: minisign is not installed" and the user had to discover `brew install minisign` unprompted. dit-client#216 made signature verification MANDATORY because the old shared key was retired and no documented install ever crypto-verified — but #216 mandates the PROPERTY (release bytes anchored to a key the forge cannot forge, fail-closed), not minisign-the-tool. ## Proposal Replace the minisign prerequisite with SSHSIG (`ssh-keygen -Y verify`), which ships by default on macOS, Linux, and Windows (OpenSSH client) — zero client-side prerequisites on every ditc target. ## Scope 1. Release CI publishes `SHA256SUMS.sshsig` alongside `SHA256SUMS.minisig` (new per-tool Ed25519 release key, same CI/secret-store custody as the current minisign key; `.minisig` keeps shipping during a transition window so already-installed binaries keep self-updating). 2. install.sh replaces the minisign hard gate with `ssh-keygen -Y verify` against an embedded per-tool allowed-signers block (identity `ditc-release@deepnet` — mirrors today's embedded per-tool pubkeys; rotation = add a key line). Missing `ssh-keygen` → printed per-OS hint + exit ≠0, never auto-install. 3. Retry-on-verify-fail loop and fail-closed semantics unchanged (#34, #543). 4. Remove the `curl … | bash -s --` usage header from install.sh — it bypasses the welcome line's hash pin and contradicts the script's own D7/SC-3 doctrine. 5. Correct the in-script attribution: the mandatory-verification gate is dit-client#216, not "dit-releases#216". 6. Parity: install.ps1 currently vendors minisign 0.11 (#20) so Windows has no external prereq — migrate it to SSHSIG in the same window or explicitly defer with a note; do not leave the two installers on divergent verification primitives past the transition. ## Acceptance criteria - A pinned install succeeds end-to-end in a `debian:12-slim` container with NO minisign and NO package installs. - The macOS journey requires zero brew (no minisign install step). - A tampered `.sshsig` fails closed (non-zero exit, nothing installed). - `tests/install-signing.sh` proves: absent-minisign gate is gone; absent-ssh-keygen prints the hint and exits non-zero; verified and tampered paths both covered.
Author
Owner

Critic review amendments (2026-10-06):

  1. DITO PARITY (blocker): install.sh verifies BOTH ditc and dito — the SSHSIG migration must not fail-close the dito path. Design: the installer PREFERS .sshsig (ssh-keygen -Y against embedded allowed-signers carrying BOTH identities, ditc-release@deepnet and dito-release@deepnet); on .sshsig-absent it falls back to minisign verification IF minisign is present (preserves the #216 fail-closed property for pre-transition releases); if neither verifier is available for the available signature, refuse with the per-OS hint. dito pipeline dual-signing is filed as its own dit-operator ticket (#1042).
  2. AC corrected: "debian:12-slim with NO minisign and NO package installs" is unsatisfiable (slim ships neither curl nor openssh-client) — the property to prove is minisign-ABSENCE: debian:12-slim + curl + openssh-client, no minisign.
  3. Per the #298 amendment: the installer also embeds the report-only feedback key + writes the machine_hint failure marker (payload contract in #298/#24).
Critic review amendments (2026-10-06): 1. DITO PARITY (blocker): install.sh verifies BOTH ditc and dito — the SSHSIG migration must not fail-close the dito path. Design: the installer PREFERS .sshsig (ssh-keygen -Y against embedded allowed-signers carrying BOTH identities, ditc-release@deepnet and dito-release@deepnet); on .sshsig-absent it falls back to minisign verification IF minisign is present (preserves the #216 fail-closed property for pre-transition releases); if neither verifier is available for the available signature, refuse with the per-OS hint. dito pipeline dual-signing is filed as its own dit-operator ticket (#1042). 2. AC corrected: "debian:12-slim with NO minisign and NO package installs" is unsatisfiable (slim ships neither curl nor openssh-client) — the property to prove is minisign-ABSENCE: debian:12-slim + curl + openssh-client, no minisign. 3. Per the #298 amendment: the installer also embeds the report-only feedback key + writes the machine_hint failure marker (payload contract in #298/#24).
Author
Owner

Implemented on branch arc/23-24-installer-rescue (unpushed): 25aa547 SSHSIG-prefer verify + minisign fallback (both installers), 74ce636 POST URL alignment. E2E (podman debian:12-slim, 11 scenarios) ALL PASSED incl. minisign-absent install, tampered-sshsig fail-closed, fallback, refusal paths. Pending: SSH release-key mint + placeholder pubkey swap, push/PR.

Implemented on branch `arc/23-24-installer-rescue` (unpushed): 25aa547 SSHSIG-prefer verify + minisign fallback (both installers), 74ce636 POST URL alignment. E2E (podman debian:12-slim, 11 scenarios) ALL PASSED incl. minisign-absent install, tampered-sshsig fail-closed, fallback, refusal paths. Pending: SSH release-key mint + placeholder pubkey swap, push/PR.
Sign in to join this conversation.
No labels
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
deepnet/dit-releases#23
No description provided.