Skip to content

feat(cli): link the login URL, bold the code, and count down to expiry - #96

Merged
thebrandonlucas merged 1 commit into
feat/cli-look-02-spinnerfrom
feat/cli-look-03-login
Oct 23, 2026
Merged

thebrandonlucas merged 1 commit into
feat/cli-look-02-spinnerfrom
feat/cli-look-03-login

Conversation

@thebrandonlucas

@thebrandonlucas thebrandonlucas commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Stack position: 3 of 13 in the look-and-feel stack. Base: feat/cli-look-02-spinner (#91), whose progress line and style::Line this PR extends.

Problem

On a terminal, voltage login printed two plain lines and a spinner that counted up. The person could not tell how long the code stayed valid. The output did not say who had signed in, except in the stdout table.

Behavior

On an interactive stderr:

› Open https://app.voltage.cloud/cli/authorize          ← OSC 8 link, blue underline
› Confirm this code: WDJB-MJHT                          ← code in bold
⠹ Waiting for approval in your browser... 3s · expires in 9:57
✓ Logged in as you@example.com (account: demo)
Element Rule
Link OSC 8 hyperlink. Its visible text is the whole URL, so a link cannot hide its target. It uses the already validated HTTPS verification_url() and passes through scrub_line. With color off, anstream strips the sequence and the plain URL remains.
Code Bold (Role::Emphasis). The code is not respaced, so copying it still works.
Countdown · expires in m:ss to the poll deadline (the server's expires_in, capped at the existing maximum). It rounds up, so it shows 0:00 only when time is up.
Closing line ✓ Logged in as EMAIL, adding (account: NAME) when the name differs. It appears only after the login is saved, and --quiet hides it.

Redirected stderr is unchanged: Open URL and Confirm this code: CODE.

Design notes

  • Progress::show takes an optional expires instant, and Terminal::expiring passes it. StatusLine::text takes the time left as an argument, so tests can check exact output.
  • style::Line gains styled(role, text) for scrubbed text in a style, and link(url). Two new roles: Link (blue, underlined) and Emphasis (bold).
  • The new output lives in two helpers, show_device_code and show_logged_in, to keep login's complexity down (CRAP 14.20).

Validation

  • cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (145 unit and 124 integration tests), and python3 scripts/check-coverage.py all pass.
  • Unit tests check that the countdown rounds up, its ASCII separator, and that a link carries a hostile URL (ESC, OSC, BEL) only in scrubbed form, both as its target and as its text. They also check that a stripped link equals the scrubbed URL and that styled text is scrubbed.
  • The device-approval PTY test now checks the exact OSC 8 sequence, the bold code, the expires in countdown, and the closing ✓ Logged in as person@example.test (account: person). All 22 login tests pass.
  • Tried by hand against a local mock auth service on a pseudo-terminal: the countdown ticks every second from 10:00, and the closing line follows approval.
  • CRAP: 0 of 668 measured functions at or above 20. The highest is 18.00 (src/cli.rs endpoint, untouched).

Docs

docs/guides/login-and-profiles.md, docs/reference/output.md, and CHANGELOG.md.

@tee8z tee8z left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on 9296da7 (base #91 7b13df4). The presentation is safe:

  • OSC 8 and bold appear only when stderr is a terminal, and anstream strips them with NO_COLOR, --color never or TERM=dumb.
  • The verification URL and the code pass through scrub_line, and the link's visible text is its target.
  • The HTTPS-or-loopback check on the URL is kept.
  • The countdown is hidden with --quiet or off a terminal, and its guard clears the line on Ctrl-C.
  • stdout and JSON are unchanged.

P2 (AGENTS.md: test every new early return): the plain paths have no tests. show_device_code (src/auth.rs:711) returns early on redirected stderr with the plain Open URL and Confirm this code: CODE lines. show_logged_in (:732) returns early off a terminal, and its line is hidden with --quiet. The only assertions on these lines run on the decorated terminal, so "Redirected stderr is unchanged" is unproven. Please add a redirected-stderr login that asserts the two plain lines and no closing line, and a terminal login with --quiet that asserts no closing line.

Nonblocking:

  • The countdown overstates the time left. The poll gives up when now + interval >= deadline (auth.rs:269), but the countdown runs to deadline. With the default 5-second interval, the user sees expires in 0:05 or less and then Login expired; run voltage login again, and after slow_down the gap grows. A user who approves at 0:03 gets "expired" while the code is still valid on the server. The countdown never reaches the 0:00 the description promises. Counting down to deadline - interval, or making a last poll at the deadline, fixes it. With expires_in over 600, the countdown is to the CLI's 600-second cap, not to the code's expiry as the docs say.
  • The src/style.rs module doc still says that "Only static labels are painted", but styled() now paints scrubbed untrusted text, and link() writes OSC 8.

Validation on this head, in nix develop: cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (145 unit, 124 integration) and python3 scripts/check-coverage.py passed. CRAP: 668 measured functions, none at or above 20, highest endpoint at 18.00; 179 functions were unmeasured. CI is green.

Comment thread src/auth.rs
Comment thread src/auth.rs
Comment thread src/auth.rs Outdated
On an interactive stderr, voltage login shows the verification URL as an OSC 8
link whose visible text is the whole URL, the device code in bold, a spinner
that counts down to the code's expiry, and a closing "Logged in as" line.
Redirected stderr keeps the plain "Open URL" and "Confirm this code" lines.
@thebrandonlucas

Copy link
Copy Markdown
Contributor Author

Review-body notes, in f9a1096:

  • Countdown: runs to deadline - interval, the last poll (also replied on the thread). The login guide and output.md now say it counts to when the CLI stops waiting: the code's expiry, or 10 minutes at most.
  • style.rs module doc: updated. A Line takes fixed labels and untrusted text and scrubs the text before styling it, so escapes come from the palette or from an OSC 8 link whose text is its target.

@tee8z tee8z left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved f9a1096 against feat/cli-look-02-spinner (#91 2f36b1c). My findings are fixed:

  • The countdown now ends at the last poll (deadline - interval), so it no longer shows time left after the login has expired. The docs say that it counts to the code's expiry or the 10-minute cap.
  • New tests cover redirected stderr (plain Open and Confirm this code lines, with no closing line and no escape) and a --quiet login on a terminal, which keeps the code and drops the closing line.

Validation on this head, in nix develop: cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo machete --with-metadata, cargo test --locked (157 unit, 131 integration) and python3 scripts/check-coverage.py passed. CRAP: 698 measured functions, none at or above 20, highest wait_for_payment at 17.05. CRAP passed on its second run. On the first, the new a_quiet_login_on_a_terminal_still_shows_the_code_but_no_closing_line and #75's a_profile_saved_after_login_keeps_changes_made_while_its_prompt_was_open timed out in the instrumented suite. Both use the pseudo-terminal harness, whose 10-second limits #104 raises to 30 seconds, so this new test adds to that flakiness until #104 merges. CI is green.

@thebrandonlucas
thebrandonlucas merged commit cc7065f into master Oct 23, 2026
8 of 14 checks passed
@thebrandonlucas
thebrandonlucas deleted the feat/cli-look-03-login branch October 23, 2026 15:47
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.

2 participants