index.txt is append-only: a CN left unrevoked after expiring, then
reissued, accumulates multiple V-status lines. load_expiring_certs()
and load_all_certs() previously returned one CertInfo per line, so
such a CN showed as duplicate rows in the TUI main menu (and in
--list/--list-all).
Extract the existing "last non-revoked entry wins" scan (previously
only in get_email()) into a shared _load_current_certs(), and build
load_expiring_certs()/load_all_certs()/get_email() on top of it. The
date-window filter in load_expiring_certs() now applies to each CN's
canonical (most recent) entry rather than to raw lines, so a stale
duplicate that happens to fall in the "recently expired" window no
longer masks a live reissued cert whose real expiry is outside it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
curses.use_default_colors() raises on terminals (e.g. serial consoles
using TERM=linux/vt100) whose terminfo lacks default-color support;
init_colors() now falls back to an explicit black background and caps
the "disabled" color to 8-color terminals.
--reissue without --email silently sent no mail when the CN wasn't in
openvpncertupdate-metadata.json, even though its email was already
embedded in the cert's index.txt subject (via EASYRSA_REQ_EMAIL) and
the TUI already fell back to it. Since build_client_full() always
writes that subject field whenever an email is known, metadata.json
was a redundant, driftable copy — remove it and have get_email() read
index.txt directly, picking the last non-revoked entry for a CN since
index.txt can contain revoked/duplicate lines for the same CN.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_parse_index_line now extracts the emailAddress segment from the DN
alongside CN, returning a (cn, expiry, email) triple. CertInfo gains an
email field populated by both load functions.
In _main(), RENEW_SELECTED falls back to cert.email when the metadata
store has no entry for the CN — so certs created outside this tool (or
before the metadata store existed) pre-fill the email field correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>