Skip to content

patchbay v0.3.0

Choose a tag to compare

@github-actions github-actions released this 14 Aug 05:16
· 14 commits to main since this release
db30862

Added

  • patchbay updates itself — the panel checks the signed release feed a
    couple of seconds after launch and, when a newer build exists, says so in a
    slim banner above the board: update and relaunch, or not now. Applying is
    always a click — patchbay is a thing you open to answer a question about your
    logins, and an update must never be what happens instead — and the banner sits
    in the flow rather than over the board, so the answer you came for is never
    covered. The download is verified against a minisign public key compiled into
    the app before anything is installed, which is the whole reason this is
    allowed to be automatic at all. A failed check is silent: an offline machine
    has no update to offer, and that is not news. not now lasts for the session
    and is written nowhere, because something you have neither accepted nor
    refused should be asked again next launch. pb check-updates gained the
    matching row: patchbay reports its own installed version (the build answering
    the question, not whichever pb is on PATH) against the newest GitHub
    release, on the same 24-hour cache and the same shared rate limit as every
    other tool. Its UPDATE WITH is a human instruction — download the DMG, curl
    the CLI tarball — the way gcloud's is, rather than a command that does not
    exist.

  • The panel writes to the key vaultadd key opens a form (id, provider,
    label, a masked secret field, with purpose, scopes, expiry, endpoint and the
    rotation checkbox folded away), and every row gets a trash affordance behind
    an inline confirm that says what removing does not do: the entry and its
    keychain value go, the credential keeps working until you revoke it at the
    provider. Both commands (key_add, key_remove) are thin wrappers over the
    same KeyRegistry calls the CLI makes, so the registry's rules — duplicate id
    refused unless you are rotating, empty secret refused, both-or-neither writes —
    and its error strings reach the panel verbatim. The vault view no longer tells
    you to go and use the command line. The secret exists in the field, the invoke
    payload and KeyRegistry::add, and nowhere else: it is cleared on submit,
    never logged, never echoed back. The panel still cannot read a value —
    get_secret is not wired up, there is no reveal and no copy, and pb key copy
    remains the only way one leaves the vault. The old CLI-only rule was about
    argv (ps, shell history), and a password field in a native window has
    neither.

  • The project env vault (pb env) — the variables a
    project needs, held the way the key vault holds credentials: names and
    provenance in ~/.config/patchbay/projects.json (0600), values in the macOS
    Keychain, and no plaintext .env anywhere. A project is a portable name,
    not a path: the manifest holds ids, environments and sync config and no
    absolute path at all, so copying it to another machine is the supported way to
    take your projects with you. Each of its environments has two layers: synced,
    which pb env pull replaces wholesale from Infisical, and local, which you
    set by hand and which wins on merge. Those are .env.local semantics, and
    they only hold because patchbay never pushes — there is no code path that
    writes a variable to a remote, so a local override is invisible to the cloud
    by construction rather than by policy, and a pull can never carry your
    container's DATABASE_URL into the team's shared set. Values are stored one
    Keychain item per project × environment × layer (account
    env:<project>/<env>/<local|synced>), holding the whole layer as one JSON
    blob, so an export is one Keychain round trip and not one per variable. No
    last4 is recorded: four characters of true or 5432 is not a hint, it is
    the value. pb env pull also pins the account a project belongs to and checks
    it before spending a subprocess — the Infisical CLI's active login is
    machine-global, and under the wrong one the API answers 403 with "project does
    not belong to your selected organization", which reads like a problem with the
    project rather than with the login; patchbay refuses first and names
    pb use infisical <email> instead.

  • Two ways a directory resolves to a project, in that order. An
    attachment (pb env attach <id> / pb env detach) binds a directory on
    this machine, in ~/.config/patchbay/attachments.json — deepest attached
    ancestor wins, several roots per project, so every worktree and second clone
    shares one vault. A marker — a committed .patchbay.toml holding
    project = "<id>", written by pb env init unless --no-marker — resolves
    a checkout by its content, so a fresh git clone works on any machine whose
    registry holds that project, with no attach step. An attachment always beats a
    marker: a deliberate local act outranks whatever the repo ships, and nothing
    in a repo can take that override back. A marker can only name a project the
    machine already has, and one that names an unknown project is a loud error
    pointing at the machine's projects.json rather than a silent miss. The
    tradeoff, taken deliberately: repo content selects which registered project's
    variables the tooling hands out, which assumes you run repos you trust.

  • Moving to a new machine is therefore: bring projects.json over, clone the
    repo (the marker travels with it), pb env pull. pb export carries that
    manifest inside the bundle and pb import registers what is not here yet, so
    the migration path is the normal route and copying the file by hand is the
    fallback; a project id the destination already has is skipped with a note
    rather than overwritten, because the machine in front of you may be the newer
    one. What does not travel: attachments.json, since those are paths from
    a machine that is not this one; every variable value in either layer; and the
    local layer's variable names along with them, because a name with no value
    behind it would make pb env list promise what pb env run could not
    deliver. SETUP.md, the pb plan checklist and the plan_setup MCP tool
    each carry one pb env pull --project <id> per linked project, marked
    auto: false and naming the pinned account — a pull under the wrong
    machine-global infisical login fails confusingly, so pb use infisical <email> may have to come first. A project the old machine had unlinked but
    with a synced layer is a gap instead: nothing on the new machine can rebuild
    it.

  • pb envinit (registers the project, attaches this directory, leaves
    a marker to commit, picking up .infisical.json), attach, detach,
    link, projects, list, pull, set, unset, import, diff, run,
    export, forget. init in a worktree of a project this machine already
    knows attaches it instead of failing on the duplicate id; forget takes the
    project, its Keychain blobs and this machine's attachments, and leaves
    committed markers alone (rm .patchbay.toml). list and diff answer from
    the name lists alone and never touch the Keychain; set takes its value from
    stdin or a hidden prompt, never argv; run -- <cmd> injects the merged
    environment into one child process and is the blessed read path, with
    export (dotenv or JSON, TTY warning) there for the cases where a file is
    genuinely what you need.
    import <file> bulk-loads an existing .env into the local layer,
    all-or-nothing, reporting a bad line by number and never by content.

  • MCP toolslist_env_projects, list_env_vars, pull_env and
    set_env_var. list_env_projects reports each project's machine-local
    roots alongside its environments, and says what an empty list means, so an
    agent does not read a path there as where the user is working. The first two
    are metadata only; pull_env executes the Infisical CLI but its outcome
    carries counts and names, not values, so it is ungated;
    set_env_var is open like store_key, so an agent that creates a
    project credential registers it. Nothing reads a value back — not even behind
    PATCHBAY_ALLOW_SECRET_READ. An environment is dozens of secrets at once,
    and pb env run in your own terminal is the answer instead.

What's Changed

  • [feature] project env vault: pb env with synced/local layers, pull-only Infisical sync, portable manifest by @YJack0000 in #2
  • [feature] panel: key vault add/remove — masked secret entry, delete with confirm by @YJack0000 in #3
  • [feature] migration: carry the env vault's portable manifest in pb export / import by @YJack0000 in #4
  • [feature] panel self-update via tauri-plugin-updater; pb check-updates reports patchbay itself by @YJack0000 in #5
  • [chore] release 0.3.0 by @YJack0000 in #6

New Contributors

Full Changelog: v0.2.0...v0.3.0