Commit Graph

9 Commits

Author SHA1 Message Date
Vlad Doloman
1d059db083 Guard --reissue against unknown CNs and leftover build files
Code review findings on the "skip revoke when .crt is missing" migration
path:

- CliRunner._issue() took the skip path whenever has_issued_cert() was
  False, which is also true for a typo'd/nonexistent CN — it would warn,
  skip the revoke, and go on to build, package, and email a brand-new
  certificate for a CN nobody asked to renew. The skip now only fires when
  the CN has a current index.txt entry (via _load_current_certs()); an
  unknown CN prints an error and exits 1 with nothing built. The TUI's
  _process_cert() doesn't need the same guard — renewal there always opens
  on an existing row (cn_readonly pins the CN), so a typo'd CN can't reach
  the branch.

- Skipping the revoke leaves pki/reqs/<CN>.req and pki/private/<CN>.key in
  place (normally revoke-issued archives both), which makes EasyRSA's
  build-client-full abort. Both CliRunner._issue() and
  CursesApp._process_cert() now check for those leftovers before building
  and fail fast with the exact paths, rather than surfacing EasyRSA's
  confusing error after the CA passphrase prompt. Neither path touches the
  files itself.

Also: strengthened two under-specified tests (test_main_rejects_bad_days_flag
now checks the resolver's message text, not just "--days", which also
appears in argparse's unrelated error; test_show_cert_form_confirm now pins
the Enter-keypress count so a partial "days" field reversion is caught), and
folded a malformed CLAUDE.md table row into its neighbor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 05:58:32 +03:00
Vlad Doloman
4af7d67bf3 Strengthen test_show_cert_form_confirm to assert result.days
A blank/default days value round-trips as "" even from a reverted
three-field form (CertFormResult.days defaults to ""), so it would not
prove the Days field was traversed. Use a non-blank days="90" instead,
which only survives if the field exists and is validated by _submit().
2026-08-15 05:34:13 +03:00
Vlad Doloman
96664f954c Add Days field to the TUI cert form 2026-08-15 05:30:31 +03:00
Vlad Doloman
2640dbf81d use erase() instead of clear() in per-keystroke TUI redraw loops
clear() forces a full physical screen repaint on the next refresh();
erase() just blanks the buffer content and lets curses diff against
what's already on the terminal, sending only the changed cells. The
main cert list and the cert-entry form both redraw on every keystroke,
so clear() there meant retransmitting the whole screen on every arrow
key / typed character — slow and flickery over a low-bandwidth link
like a serial console.

One-shot dialogs (show_confirm, _msg, _error) draw once and don't
loop-redraw, so they keep clear() as-is — no benefit to changing them
and it's one less thing to get wrong.

Also handle curses.KEY_RESIZE explicitly in the main list loop: force
one real clear() right after a detected resize, since erase()'s diff
against the pre-resize screen model isn't reliable across a genuine
dimension change. Screen-size changes were already picked up on the
next redraw before this (draw() runs unconditionally every loop
iteration), this just guarantees a clean repaint at the moment of the
actual resize instead of trusting the diff engine through it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 17:45:13 +03:00
Vlad Doloman
f7ce56a6d4 fix curses.newwin() crash on narrow terminals in TUI dialogs
show_confirm() sized its window purely from message content, with no
upper bound — a long line (the Cryptgeon password URL in the
post-issuance "send email?" prompt) could easily exceed a narrow
terminal's width (e.g. a serial console), making curses.newwin()
raise "curses function returned NULL" and crash the whole app.
show_cert_form() had the same unguarded newwin() call, just with a
fixed 13x62 size instead of content-driven.

Clamp both windows' height/width to the actual screen size, and wrap
newwin() itself in try/except as a last-resort fallback (declined
confirm / cancelled form) in case clamping still isn't enough.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 16:33:38 +03:00
Vlad Doloman
6ed7f9feef feat: add Continue and Cancel buttons to Certificate Details form
Tab (or Down/Enter on a field) now cycles through the three text fields
and then onto [ Continue ] and [ Cancel ] buttons at the bottom of the
form.  Enter or Space activates the focused button.  Ctrl-G still
confirms immediately from any position.  Escape still cancels.

The form window is trimmed from h=16 to h=13 since the buttons replace
the now-redundant empty space below the password field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 13:53:20 +03:00
Vlad Doloman
567c3e9759 fix: replace Ctrl-S confirm with Ctrl-G in Certificate Details form
Ctrl-S (0x13) is the XOFF flow-control character; terminals intercept it
before curses sees it, causing output suspension in Konsole and others.
Replaced with Ctrl-G (0x07 / BEL) which has no terminal-level meaning.
Updated hint bar and test stub accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 13:47:14 +03:00
Vlad Doloman
565a152243 fix: spec compliance for TUI DIALOGS section
- Rename CertFormResult.cancelled → confirmed (True=submit, False=cancel/Esc)
- Change _FORM_FIELDS from list to tuple
- Update _FORM_LABELS to exact values: CN, Email, Password
- Update _FORM_FIELD_Y to {cn:3, email:5, password:7}
- Add password param to show_cert_form (uses generate_password() if empty)
- Add mask=True to password InputField (both init and F5-regen sites)
- Add ord("Q") to show_confirm false-return condition
- Add KEY_UP/KEY_DOWN navigation in show_cert_form
- Add Ctrl-S (0x13) as immediate submit key in show_cert_form
- Update tests/test_dialogs.py: confirmed=True on submit, confirmed=False on cancel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 00:13:46 +03:00
Vlad Doloman
fefec14929 feat: TUI modal dialogs (confirm Y/N, cert detail form)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 00:07:38 +03:00