src/cli.js — stoke auth tells the truth about a token it cannot revoke, and exits non-zero when there is no session #64
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:ci
scope:cli
scope:docs
scope:manifests
scope:packaging
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/stoke#64
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Two
stoke authsubcommands report a state that is not the state. Both are small, both are in the same command group, and both fail in the same direction: silence read as success.1.
auth logoutsays nothing about a token it cannot revokeauth login -t/--token/--token-filestores a config withtokenId: null— the token was minted elsewhere, so stoke has no id for it (src/cli.jsL225-234). Logout then gates its entire remote-revocation block on that id (L280):For a supplied-token session the whole block is skipped and the user sees one line:
Local credentials removed.Nothing says the credential still authenticates against the forge. The password-login path is careful about exactly this — L296 spells out that the token "stays active" and where to revoke it — so the honest message already exists in the file, and the path that most needs it is the one that never reaches it.The asymmetry matters because it runs the wrong way round: a token stoke created, it offers to revoke; a token the user pasted in — often a longer-lived PAT — it silently abandons while printing a line that reads like completion.
2.
auth statusexits0when there is no sessionL314-318:
returnfrom the action leaves the process at0, sostoke auth status && do-the-thingruns the thing while unauthenticated, andstoke auth status || stoke auth loginnever logs in. A status probe that cannot be branched on is the one use a status probe has. Every other failure in this file exits1;gh auth statusexits1unauthenticated. This is the odd one out.A claim from the same audit that is FALSE — recorded so nobody re-mints it
!21's finding 6 bundled a third claim: that
auth statusprints a phantomUsername:field because "Forgejo's/userhas nousername". Measured against the live instance today (8.0.3+gitea-1.22.0): it does.usernameis present and equalslogin. L328 prints a real value; at worst it duplicates the line above it. Theme.username || me.loginfallbacks at L229/L248 are belt-and-braces, not evidence of absence.Username:is out of scope and no change to it is wanted here — a cosmetic duplicate line is not worth a diff, and re-filing it would put a refuted claim back on the board.Provenance
Finding 4 and half of finding 6 of the six in the closed !21, each re-verified at
2230ca25today. Triage asked @andres on 2026-08-30 (!21 comment 28090) whether that close was hygiene or a verdict; no answer came and both threads carrying the question were closed. Triage decided hygiene and owns the call. That the third claim did not survive re-measurement is the reason each was re-measured.Spec — decisions
Logout — one added branch, no behaviour change anywhere else. When
!options.localOnlyandconfig.tokenIdis falsy, print a message beforeclearConfig()that states three facts:config.url, and where to revoke it —Settings > Applications, the same wording L296 already uses.Do not invent a revocation attempt:
deleteTokenneeds an id and a password, and neither exists on this path. Do not prompt.--local-onlykeeps today's output exactly, because there the silence is what the user asked for.Status —
process.exit(1)on the no-session path. Keep the textNot authenticated.and keep it on stdout; only the exit code changes. With--jsonon that path, print{"authenticated": false}and exit1, so a scripted caller gets a parseable answer instead of prose. The authenticated--jsonshape (the raw/userobject) does not change.One existing test must be edited, deliberately.
test/cli.test.jsL38-45 assertsres.status === 0for--config <missing> auth status. That assertion is incidental to what the test is for — that--configroutes to the given path — so change the expected status to1and keep the/Not authenticated/match and the test's name and intent intact. Do not delete the test.Out of scope
Username:line (refuted above).deleteTokenitself.repo import-batch, which is #65's deliverable in this same file.Tasks
auth logoutper the Spec, beforeclearConfig().auth statusexit1, and emit{"authenticated": false}under--json.--configtest's expected status from0to1, leaving its intent and itsNot authenticatedassertion untouched.test/cli.test.js, using the existingSTOKE_CONFIG_FILE/--configharness.changelog.d/fragment.Refs; aClosesis equally correct here since every criterion is pre-merge.Acceptance criteria
auth logoutagainst a config withtokenId: nulland no--local-onlyprints a message naming all three facts — credentials removed locally, stoke cannot revoke a token it did not create, the token is still valid at the configured URL with where to revoke it — and still exits0.auth logout --local-onlyagainst the same config produces output byte-identical to today's.auth logoutagainst a config with a non-nulltokenIdis unchanged on every path: revoked, warned, and the no-password skip message at L296.auth statuswith no session exits1and still printsNot authenticated.on stdout.auth status --jsonwith no session exits1and prints exactly{"authenticated": false}.auth statuswith a valid session still exits0, and its--jsonoutput is still the raw/userobject — the existing case attest/cli.test.jsL989 passes unmodified.git difftouches exactlysrc/cli.js,test/cli.test.jsand onechangelog.d/*.md.npm testpasses andci / testis green on the PR head.Test plan
npm test, using the local-http-server and temp-config harness already intest/cli.test.js. The cases that must fail:auth statusthat exits non-zero — the change must be scoped to the no-session path, and this is the regression the exit-code edit invites.tokenIdis null.--local-onlylogout whose output changed.--configrouting test instead of amending its expected status: the routing assertion is not this issue's to remove.Dependencies
No blockers.
Blocks #65 — that issue's collision edge, not a prerequisite of its content. Both change
src/cli.js; #288 makes the edge unconditional so thatreadykeeps meaning concurrently claimable, and this issue is the newest open carrier of the file at mint time. Closing this one releases #65.Related: the closed !21 (origin), and #62 / #63, minted from the same audit in the same tick.
Starting work as @codex-bot-andresmgsl.
Design: keep the change inside the existing auth actions. For logout, add only the supplied-token/non-local branch before config deletion, reusing the established Settings > Applications guidance while leaving --local-only and tokenId-backed paths untouched. For status, branch the unauthenticated output on --json and terminate with status 1. I will drive both changes test-first in test/cli.test.js, preserve the existing --config routing test, add the required changelog fragment, and verify the exact three-file diff plus npm test.
codex-bot-andresmgsl referenced this issue2026-09-04 01:55:35 +00:00
glm-bot-andresmgsl referenced this issue2026-09-04 02:11:41 +00:00
kimi-bot-andresmgsl referenced this issue2026-09-04 02:23:01 +00:00