Skip to content

[fix] an hourly token is not a login's expiry; verify the profile you pressed - #10

Merged
YJack0000 merged 1 commit into
mainfrom
claude/gcloud-auth-config-issues-99d0e8
Aug 14, 2026
Merged

[fix] an hourly token is not a login's expiry; verify the profile you pressed#10
YJack0000 merged 1 commit into
mainfrom
claude/gcloud-auth-config-issues-99d0e8

Conversation

@YJack0000

Copy link
Copy Markdown
Contributor

Five bugs, all of them visible on one gcloud card at the same time.

1. Verifying a profile verified a different profile

The panel's per-row check has always sent the profile id, and verify_profile
in app/src-tauri/src/lib.rs has always thrown it away and asked about
whichever profile was active — GcloudProbe had no verify_profile either, so
there was nothing to call anyway. On a board with two configurations, pressing
"verify" on the inactive one reported the active account's answer under the
inactive one's row. Two rows, one truth, filed under both:

default  ✗ ERROR: (gcloud.auth.print-access-token) There was a problem refreshing…
pathors  ✗ ERROR: (gcloud.auth.print-access-token) There was a problem refreshing…   ← same account, twice

The command now calls Registry::verify_profile, and the probe runs
gcloud auth print-access-token --account=<the account that configuration names>. --account is per-invocation, so checking a profile never activates
it. On a real two-configuration machine:

$ pb verify gcloud --profile default
gcloud: valid    `default` (cerana.mail@gmail.com) minted an access token
$ pb verify gcloud --profile pathors
gcloud: valid    `pathors` (jack@pathors.com) minted an access token

2. Three probes were dating a borrowed hour

gcloud, firebase and neon each stored an OAuth access token's expiry
as the profile's expiry. All three refresh that token silently, so the board
read expired 3d / expired 235d / expired 12d about logins that work,
counted them in the expired tally on every refresh, and — because a token
minted this second is one hour out, well inside the 24h attention window —
meant gcloud could never once reach Connected.

Each now reports no expiry where it has none, and keeps one only where the hour
genuinely is the whole login:

probe keeps the expiry when otherwise
gcloud never — access_tokens.db only ever holds the hourly token unknown + note
firebase no refresh_token beside it in the configstore unknown + note
neon the grant has no offline scope unknown + note

firebase reads that presence through serde::de::IgnoredAny, so it learns the
refresh token is there without ever holding its value — the same guarantee the
probe already made for access_token by never naming it.

What actually ends these sessions — revocation, an org reauthentication policy —
is decided server-side and written nowhere on this machine, so None (unknown)
is the honest answer, and the notes now say what is unknown instead of
apologising for what was shown. az and aws already worked this way; this
brings the other three in line.

3. A failed check was a paste of gcloud's error

gcloud answers a reauth failure with four lines of shell instructions, which the
panel joined into one:

…cannot prompt during non-interactive execution.; Please run:; $ gcloud auth login; to obtain new credentials.; If you have already logged in…

Reauthentication, a revoked credential and a missing credential are now each one
sentence ending in the command that fixes it, for the account it is actually
about. Anything else keeps gcloud's own first line minus the prefix that only
repeats what patchbay just ran. An account with no row in credentials.db is
answered from tier 1 without spawning anything, and a gcloud that is not on
PATH is unsupported rather than an Err.

4. The IAM hint could not be run

It carried <project> and <account> placeholders while patchbay had both
values on the row directly above, and --flatten=bindings[].members was
unquoted — a glob, which zsh answers with no matches found before gcloud ever
starts. Now filled in, quoted, and the report names the account as its subject:

$ pb perms gcloud
hint: gcloud projects get-iam-policy buzz-445414 --flatten='bindings[].members' --filter='bindings.members:jack@pathors.com'

That line, run verbatim, returns the account's five roles.

5. "re-read scopes" for a tool with no scope reader

A second press cannot say anything the first did not. The button stays (it is
still how you ask), but it no longer claims there is something to re-read.

Notes

  • No schema or migration impact. Profile::expires_at was already
    Option<DateTime<Utc>> and already null for az, gh and static aws
    keys; MCP consumers are told expires_at: null means unknown, which is now
    simply true more often.
  • migrate/plan.rs used gcloud as the fixture for "an expired credential is a
    setup task". Moved to an AWS SSO session, which dates a real login.
  • Ships as 0.3.2 — all four version files bumped via scripts/bump-version.sh.

Verification

  • cargo test --workspace --locked — 611 pass (7 new gcloud tests, 2 new
    firebase, 2 new neon)
  • cargo clippy --workspace --all-targets --locked — clean
  • tsc --noEmit — clean
  • pb status / pb verify gcloud --profile … / pb perms gcloud run against a
    real machine with two gcloud configurations, a firebase login and a neon
    grant; every output quoted above is real

… pressed

Five bugs, all visible on one gcloud card.

`verify` on a profile row verified whichever profile was active: the Tauri
command threw the profile id away, and GcloudProbe had no verify_profile at
all. On a board with two configurations both rows reported the same answer,
belonging to one of them. The command now calls Registry::verify_profile and
gcloud runs `auth print-access-token --account=<that config's account>`, which
is per-invocation and never activates what it checks.

gcloud, firebase and neon all stored a refreshable OAuth access token's expiry
as the profile's, so working logins read "expired 3d" / "expired 235d" /
"expired 12d", counted in the board's expired tally — and since a token minted
this second is an hour out, well inside the 24h attention window, gcloud could
never once read Connected. Each now reports no expiry where it has none to
report, and keeps one only where the hour really is the whole login: firebase
when no refresh_token sits beside it, neon when the grant has no offline scope.
gcloud has no such case, so it is always unknown, with a note pointing at
verify.

A failed gcloud check was gcloud's own four lines of shell instructions joined
with `; `. Reauth, revoked and missing-credential are each one sentence ending
in the command that fixes it, for the account it is about.

The IAM hint carried <project>/<account> placeholders while patchbay had both
values on the row above, and its unquoted `bindings[].members` is a glob that
zsh refuses before gcloud starts. Filled in, quoted, subject named.

Release 0.3.2.
@YJack0000
YJack0000 merged commit 2b27782 into main Aug 14, 2026
3 checks passed
@sonarqubecloud

Copy link
Copy Markdown

@YJack0000
YJack0000 deleted the claude/gcloud-auth-config-issues-99d0e8 branch August 14, 2026 09:38
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.

1 participant