feat: relative-time timestamp annotations + nil stdin-stat guard - #20
Merged
Conversation
Enrich the iat/exp/nbf annotations with the time remaining or elapsed instead of a bare flag: exp now reads "expires in 14m" / "expired 2h ago" and a future nbf "not yet valid, in 5m". An already-valid nbf stays bare. humanizeDuration renders the largest whole unit (s/m/h/d), truncating toward zero so output is deterministic. Annotations remain display-only and never affect verification or the exit code. Also guard readToken against a nil FileInfo when os.Stdin.Stat() fails (closed or detached stdin): it now falls through to the interactive prompt rather than dereferencing nil and panicking. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the hero terminal example and regenerate og.png so the exp claim shows the new relative-time annotation: a live token reading "expires in 15m" against an iat 15 minutes earlier, paired with the "Signature: VALID" line. The annotation stays green like the rest of the timestamp value, matching the tool's actual output. og.png was re-rendered at 1200x630 from an HTML template via headless chromium, preserving the existing Tokyo Night layout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bsg62
force-pushed
the
feat/relative-time-and-stdin-guard
branch
from
July 25, 2026 19:05
29446d4 to
65b5646
Compare
bsg62
added a commit
that referenced
this pull request
Jul 25, 2026
These docs/superpowers/plans files were untracked local notes swept into PR #20 by an errant `git add -A`; they are not part of the project and are restored to their prior untracked state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements two improvements discussed together.
#3 — Relative-time annotations
The
iat/exp/nbfdisplay annotations now carry the time remaining or elapsed instead of a bare flag:expin the future →expires in 14mexpin the past →expired 2h agonbfin the future →not yet valid, in 5mnbfalready valid → no note (the ordinary active state)humanizeDurationrenders the largest whole unit (s/m/h/d), truncating toward zero so output is deterministic and testable. The annotations stay display-only — verification and the exit code remain purely cryptographic, and the--jsonpath is unchanged (raw numeric claims).#5 — nil stdin-stat guard
readTokendiscarded the error fromos.Stdin.Stat()and dereferenced the result. On a closed/detached stdinStat()can return a nilFileInfo, panicking atstat.Mode(). It now falls through to the interactive prompt in that case.Tests
TestHumanizeDuration(table-driven, incl. boundary rounding and negative magnitude) andTestFormatTimestamps_ExpiredShowsElapsed.formatTimestampstests for the enrichedexp/nbfwording; renamedNoAnnotationWhenCurrentlyValid→InsideValidityWindowand tightened it to assert the new "expires in" note and the bare already-validnbf.Follow-up (not in this PR)
site/index.html's hero example hardcodes(…, expired)and is paired with a generatedog.png. A relative duration would drift on a static page and re-rendering the OG image is a separate concern, so the marketing site is intentionally left untouched here.🤖 Generated with Claude Code