Skip to content

patchbay v0.4.0

Latest

Choose a tag to compare

@github-actions github-actions released this 17 Aug 09:29

Added

  • Nine CLIs patchbay refused to verify are now verified. wrangler,
    vercel, neon, supabase, flyctl, doctl, huggingface, stripe and
    firebase used to answer verify with 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: verify only runs when you press the button or type pb 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 me starts a
    browser login when there is no credential, so that state is answered from the
    tier-1 read without executing anything; and fly auth whoami offers an
    interactive login unless --json is 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 perms and 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.

    kubectl asks per namespace: the picker merges the namespaces the kubeconfig
    names with kubectl get namespaces when the cluster answers — the kubeconfig
    half matters because where ~/.kube/config is 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 is kubectl auth can-i --list, tried in
    -o json and falling back to parsing the table for the versions that have no
    such flag, rendered as get,list,watch pods. az asks per subscription, and
    that list costs nothing: azureProfile.json already holds it, so unlike
    gcloud's the picker needs no grant to populate. Roles come from az role assignment list --all --include-inherited, and one granted on a single
    resource group is labelled Contributor on resourceGroups/web rather than
    being flattened into the subscription it is not held across.

    aws has no picker, because an AWS credential's permissions are not asked
    about anywhere — the identity is what it is. It resolves that identity
    through sts: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 answers auth can-i with twenty lines of klog headers, a nested config-helper
    transcript, and gcloud's own four-line "Please run:" block, none of which is
    the answer.

Changed

  • Notes carry a severity. ToolStatus.notes was a Vec<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 a Note with a
    kind of info, warn or problem. info draws no glyph and does not
    count towards the card's badge; warn keeps the amber triangle; problem
    gets a red one. ToolStatus::note() is gone, replaced by info(), warn()
    and problem() so the judgement has to be made at every call site.

    Breaking JSON change. notes in pb --json, in every MCP tool result,
    and on PermissionsReport and 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: null meant 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.expiry is now an Expiry: at, no_expiry,
    unknown { reason } or refreshable { 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_at is still in the JSON, unchanged in meaning: a timestamp
    for a real deadline, null for the other three. It is now derived from
    expiry rather 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 reported command execution is disabled for this probe
    as a user-facing reason. New SwitchOutcome::ExecDisabled /
    VerifyOutcome::ExecDisabled states 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.

  • infisical still 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
    serialized advisories on ToolStatus and the CLI has always rendered them,
    but the panel's TypeScript ToolStatus did 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