Skip to content

Setup asks for the Resend key and writes the Credentials - #198

Merged
JacobStephens2 merged 4 commits into
mainfrom
issue-192
Sep 30, 2026
Merged

JacobStephens2 merged 4 commits into
mainfrom
issue-192

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

With Run notifications on, Setup now asks for the Resend API key with input hidden and saves it in the Credentials (~/.thirdshift/credentials.toml, mode 0600). It no longer prints the export RESEND_API_KEY=... shell-profile hint. thirdshift setup and the first Run's Setup offer, answered Yes, ask the same question.

 setup / offer_setup (Yes)
   parse the User config
+  Credentials::read()            # strict parse; broken file → exit 1 before any question
   questions::ask
     merge.always, launch.pull, email.always
     email.to, email.from
-    RESEND_API_KEY unset → print `export RESEND_API_KEY=...` hint
+    RESEND_API_KEY set   → "The Resend API key comes from RESEND_API_KEY."
+    key in Credentials   → "Resend API key (input hidden, Enter keeps the saved one):"
+    no key               → "Resend API key (input hidden, Enter to skip):"
+                           skipped → how to add one later (rerun setup, or RESEND_API_KEY)
+      echo off; trimmed; not re_… → asked again
     test email offer (default No), when a key is found or given
   write the User config
+  write the Credentials, only if a key was given → "wrote the Credentials <path>"
+    new: create 0600 (and ~/.thirdshift); existing: edit resend.key in place, comments kept
   send the test email, if asked
src/
├── resend_key.rs   # + Credentials: read (strict), lookup, save (create 0600 / edit in place)
├── questions.rs    # + hidden key question; EchoOff restores echo on Ctrl-C/SIGTERM/SIGHUP
└── config.rs       # Setup and the offer read the Credentials first, then save a given key

Setup reads and validates the Credentials before it asks anything, even if the user later turns notifications off. This follows #192's "refused before any questions". With notifications off, nothing about a key is asked and the file is never written.

README (Setup step 4 and the Email section), the help text and the Setup glossary entry now describe the key prompt.

Evidence

  • Before: with notifications on and no key, Setup printed export RESEND_API_KEY=re_... and wrote nothing. A Run from cron with email.always = true then stopped for want of a key.
    After: new binary-level tests on a pseudo-terminal (run_on_terminal), all passing:

    tests/setup.rs
      no key: Enter skips → no Credentials, says rerun setup / set RESEND_API_KEY, no export hint
      entered key → credentials.toml 0600 holds it; "wrote the Credentials <path>"; key absent from terminal
      non-re_ input → asked again
      saved key: Enter keeps the file byte for byte
      new key replaces resend.key, comments and trailing comment kept
      Credentials with no [resend] → section appended, no commented-out defaults
      RESEND_API_KEY set → no prompt, says so, saved file untouched
      test email → sent with Bearer <key just entered>, after the Credentials are written
      Ctrl-C at the key prompt → neither file written (and saved Credentials unchanged)
      broken Credentials (unknown key, bad TOML, wrong type) → exit 1 before any question, untouched
      notifications off → nothing about a key asked, saved Credentials unchanged
    tests/setup_offer.rs
      Yes → key asked and saved, the Run's notification goes with it
      Yes with broken Credentials → exit 1 before any question or work
      No / no terminal → no Credentials written
    

    The old key-hint test was rewritten for the new behaviour, not deleted. A manual check on a pty confirmed echo is off during the prompt and back on after Ctrl-C. cargo test passes in full, and cargo clippy --all-targets is clean.

Merge Danger

Door: two-way

Setup only writes a new file, and only when a key is typed. Reverting brings back the hint, and any saved Credentials keep working through the lookup from #191.

Blast Radius: Setup

Only thirdshift setup and the first Run's Setup offer change. Runs, email-test, update, version and help behave as before. Setup from a terminal is now refused by a broken Credentials file, even for a user who will turn notifications off.

Unaddressed findings

Standards

  • Duplicated ask block in setup and offer_setup: it is three lines, and the two callers treat failures after asking differently (error vs warning). A shared helper would add a layer without removing the fork.
  • EchoOff (termios and signal code) lives in questions.rs: the hidden question is its only user, and interrupt.rs is about recording signals for a Run's Failed run path, not terminal state. Kept where it's used.
  • config::replace made pub for the Credentials: reusing the one atomic, permission-keeping write beats copying it. Moving it to a new file-helpers module is a separate refactor.
  • Credentials::lookup vs ResendKey::find both say "environment, else the file": kept deliberately. find must not open the file when RESEND_API_KEY is set (so broken Credentials can't block a Run), while Setup has already read it.

Spec

Closes #192

🤖 Generated with Claude Code

JacobStephens2 and others added 4 commits September 30, 2026 18:42
Closes #192

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the CONTEXT.md conflict on Setup: keep this branch's wording
(the key is asked for only with Run notifications on) and main's
"when a key is entered", since the key prompt can be skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit 8c1e55b into main Sep 30, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-192 branch September 30, 2026 19:14
@JacobStephens2 JacobStephens2 mentioned this pull request Sep 30, 2026
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.

Setup asks for the Resend key and writes the Credentials

1 participant