Skip to content

feat(cli): mix cert status, measured against a live handshake (T53) - #37

Merged
haiquang9994 merged 8 commits into
masterfrom
t53-cert-status
Aug 25, 2026
Merged

feat(cli): mix cert status, measured against a live handshake (T53)#37
haiquang9994 merged 8 commits into
masterfrom
t53-cert-status

Conversation

@haiquang9994

Copy link
Copy Markdown
Collaborator

What this adds

mix cert status — the first thing in this repository that measures a padlock rather than
inferring one.

T48 reads an authority off disk, T50 writes a leaf, T51 renders a tls line naming it and T52
replaces it before it expires. Every one of those is a claim about a file. None of them
establishes that the running server presents that file to anything — so the most common TLS fault
of all, a certificate the front end still holds in memory after the file beside it was
replaced
, is invisible to all four and obvious to this one.

How it measures

A real TLS handshake to 127.0.0.1:<https_port>, with the site's name as SNI and never a resolved
address — whether blog.test resolves is mix doctor's question, and a handshake that resolved
would report "TLS failed" on a machine whose only fault is a resolver nobody wired.

The verifier is a real WebPkiServerVerifier rooted at this home's authority alone. It records the
genuine verdict and then returns Ok regardless, so that the certificate a failing server
presented can be reported instead of being replaced by an error message about it.

The TLS port is read from stored settings, never through Generator::generate — that method writes
to disk and can reload a running server, which would destroy the exact state this diagnostic exists
to reproduce.

Ordering

CertProblem is first-match-wins, in the order a person would fix things in: NoCertificate ->
NamesDiffer -> NotServed -> ServedCertificateDiffers -> NotTrusted -> Expiring. The CLI
prints the command to run next.

Security

cert.status carries no private key, and a test asserts it. The CA key is not read by any code on
this path.

Testing

  • 3 unit tests driving a real rustls server on an OS-chosen port (rule 1: no test claims a port
    number that belongs to the machine it runs on)
  • 8 unit tests over the problem-ordering
  • 2 CLI integration tests, including one asserting no key material crosses the wire
  • 2 #[ignore]d end-to-end tests against a real Caddy, covering the trusted handshake and the
    stale-certificate-in-memory case; both pass on macOS and Windows

Cargo.lock gains 4 lines and zero new packages — rustls and tokio-rustls were already reaching the
daemon through mixengine-core -> reqwest.

@haiquang9994
haiquang9994 merged commit d084b35 into master Aug 25, 2026
28 of 30 checks passed
@haiquang9994
haiquang9994 deleted the t53-cert-status branch August 25, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant