Added
-
Nine CLIs patchbay refused to verify are now verified.
wrangler,
vercel,neon,supabase,flyctl,doctl,huggingface,stripeand
firebaseused to answerverifywith an excuse and a command to paste —
"the CLI is node-based and slow to start", "that is a network call". Slow is
not a reason:verifyonly runs when you press the button or typepb verify. Each now runs the tool's own check and reports the identity it
answers with, so you can hold it against what the board claimed: the
Cloudflare accounts behind a wrangler token, the Vercel username, the Neon
account and plan, the Supabase projects and org, the Fly and DigitalOcean
accounts, the Hub user and orgs, the Stripe account and key expiry, the
firebase-tools accounts.Failures say one actionable sentence rather than pasting the tool's error
paragraph, and they distinguish three states that used to be one: logged out,
credential rejected, and the network was unreachable — the last of which is
no longer reported as a bad login, because nothing about the credential was
established. Where a check is local rather than a round trip (stripe and
firebase have no read-only command that both names the account and exercises
the credential) the answer says so instead of letting a tick imply more than
it proved.Two hazards are handled rather than discovered later:
neon mestarts a
browser login when there is no credential, so that state is answered from the
tier-1 read without executing anything; andfly auth whoamioffers an
interactive login unless--jsonis passed, so it is. -
kubectl, az and aws answer what a credential can do. The scoped
permissions seam gcloud opened is now filled by three more probes, and
because the panel,pb permsand the MCP tools discover the capability from
the probe rather than from a list, all three arrive with a picker and a
reading and no wiring of their own.kubectlasks per namespace: the picker merges the namespaces the kubeconfig
names withkubectl get namespaceswhen the cluster answers — the kubeconfig
half matters because where~/.kube/configis a directory of per-cluster
files, kubectl's own loader refuses it and patchbay's parse is the only thing
that still has the list. The reading iskubectl auth can-i --list, tried in
-o jsonand falling back to parsing the table for the versions that have no
such flag, rendered asget,list,watch pods.azasks per subscription, and
that list costs nothing:azureProfile.jsonalready holds it, so unlike
gcloud's the picker needs no grant to populate. Roles come fromaz role assignment list --all --include-inherited, and one granted on a single
resource group is labelledContributor on resourceGroups/webrather than
being flattened into the subscription it is not held across.awshas no picker, because an AWS credential's permissions are not asked
about anywhere — the identity is what it is. It resolves that identity
throughsts:GetCallerIdentity, which needs no permission, then reads the
attached and inline policies. When that read is refused the report says so
exactly: the identity is known, and listing its policies needs
iam:ListAttachedUserPolicies, which is itself a permission most keys lack.
An empty list would have read as "this credential can do nothing", which is
the opposite of what is known. An SSO or assumed-role identity is named as
the role it is instead of being asked a user-policy question it cannot
answer.Every failure on these paths comes back as one actionable sentence. That is
not cosmetic: a GKE context whose gcloud login has gone stale answersauth can-iwith twenty lines of klog headers, a nestedconfig-helper
transcript, and gcloud's own four-line "Please run:" block, none of which is
the answer.
Changed
-
Notes carry a severity.
ToolStatus.noteswas aVec<String>— an
untyped dumping ground that the panel rendered one way: every line behind the
same amber warning triangle. So "docker has no active registry (normal for
docker)" looked exactly like "credentials.db is unreadable", and a board of
healthy tools read as a wall of complaints. Each note is now aNotewith a
kindofinfo,warnorproblem.infodraws no glyph and does not
count towards the card's badge;warnkeeps the amber triangle;problem
gets a red one.ToolStatus::note()is gone, replaced byinfo(),warn()
andproblem()so the judgement has to be made at every call site.Breaking JSON change.
notesinpb --json, in every MCP tool result,
and onPermissionsReportand the MCP-client report, is now an array of
{"kind": "info"|"warn"|"problem", "text": "…"}rather than an array of
strings. There is deliberately no back-compat shim: a consumer that keeps
treating notes as strings should fail loudly rather than print[object Object]. -
Expiry carries its own state.
expires_at: nullmeant three unrelated
things — this never expires, this expires but the timestamp is somewhere
patchbay will not read, and this expires but the CLI renews it silently — and
thirteen probes each wrote their own paragraph of prose explaining which one
applied.Profile.expiryis now anExpiry:at,no_expiry,
unknown { reason }orrefreshable { access_token_expires }. The panel
shows "no expiry", "expiry unknown" or "auto-renewed" accordingly, with the
reason as the chip's tooltip, and only a real deadline takes a colour.Profile.expires_atis still in the JSON, unchanged in meaning: a timestamp
for a real deadline,nullfor the other three. It is now derived from
expiryrather than stored beside it, so the two can never disagree. -
"This tool has no active X" is a property, not a note. New
ToolStatus.active_concept. rclone, npm, docker, ssh, stripe, flyctl, op and
supabase say it once, in the type; the panel renders an em dash with the
explanation as a tooltip instead of eight tools each filing a warning about
working as designed. -
patchbay's own execution switch no longer surfaces as a caveat about your
login. Five sites reportedcommand execution is disabled for this probe
as a user-facing reason. NewSwitchOutcome::ExecDisabled/
VerifyOutcome::ExecDisabledstates instead: the panel greys the button and
explains in a tooltip, and the CLI prints one short line. -
Notes that only restated something already on the row are gone: profile
counts, tunnel-name counts, MCP-server counts, "AWS_PROFILE is not set, so
the default profile is in effect" (inverted — it now speaks up only when the
variable is set), and the neon config-directory trivia the advisory already
covers. -
infisicalstill reports no permissions, but says why in one clause — its
CLI has no command that reports a member's role — instead of sending you off
to click around in a dashboard.
Fixed
-
The panel was silently dropping every advisory. Core has always
serializedadvisoriesonToolStatusand the CLI has always rendered them,
but the panel's TypeScriptToolStatusdid not declare the field — so a tool
that had been removed or abandoned looked identical to a healthy one. The
drawer now has an advisories section above the notes, with the source link
and a louder treatment for the blocking kinds. -
A purely informational MCP message was wearing the red error banner. The
project-scope note in the MCP server drawer explains that patchbay declines
to write another project's config — a deliberate boundary, not a failure. It
now renders as a quiet notice.
What's Changed
- [refactor] notes carry a severity; expiry carries its own state by @YJack0000 in #18
- [feature] nine CLIs that patchbay refused to verify are now verified by @YJack0000 in #16
- [feature] kubectl, az and aws answer what a credential can do by @YJack0000 in #17
- [fix] kubectl offers a namespace picker even when no context is current by @YJack0000 in #19
Full Changelog: v0.3.4...v0.4.0