Skip to content

[feature] project env vault: pb env with synced/local layers, pull-only Infisical sync, portable manifest - #2

Merged
YJack0000 merged 3 commits into
mainfrom
claude/local-vault-multi-project-d6b580
Aug 13, 2026
Merged

[feature] project env vault: pb env with synced/local layers, pull-only Infisical sync, portable manifest#2
YJack0000 merged 3 commits into
mainfrom
claude/local-vault-multi-project-d6b580

Conversation

@YJack0000

Copy link
Copy Markdown
Contributor

What

The project env vaultpb env: per-project environment variables managed like .env / .env.local / .env.production, but with no plaintext files, a synced layer pulled from Infisical, and a portable manifest that travels between machines.

cd ~/repos/pathors
pb env init                          # register + attach + write .patchbay.toml
pb env pull                          # synced layer from Infisical
pbpaste | pb env set DATABASE_URL    # local override; value never touches argv
pb env diff                          # what this machine changes — names only
pb env run -- bun dev                # merged env into one child process

Design

flowchart LR
    subgraph portable["portable (travels between machines)"]
        M["projects.json\nids · environments · sync pin\n(no absolute paths — test-enforced)"]
        MK[".patchbay.toml in the repo\nproject = "pathors"\n(committed, resolves any clone/worktree)"]
    end
    subgraph machine["machine-local (stays put)"]
        A["attachments.json\ndir → project overrides"]
        K["Keychain\nenv:<project>/<env>/<layer>\none blob per layer"]
    end
    I[Infisical] -- "pb env pull\n(pull-only, account-guarded)" --> K
Loading
  • Two layers per environment. synced is replaced wholesale by pb env pull; local is hand-set, never pushed, never touched by a pull, and wins on merge.env.local semantics. patchbay has no push code path at all: a local experiment can never be promoted into the team's shared set.
  • A project is a name, not a path. projects.json is a fully portable manifest (a test greps the raw file to prove no machine path leaks in). Directories resolve via machine-local attachments first, then via the committed .patchbay.toml marker — so every clone and every git worktree of a repo shares one project's environments with zero setup. New machine = copy projects.json → clone → pb env pull.
  • Account guard. The infisical CLI's active login is machine-global; each project pins the account it belongs to, and pull refuses under any other login with the exact fix (pb use infisical <email>) instead of surfacing Infisical's misleading wrong-org 403.
  • Storage split as in the key vault. Names/provenance on disk (0600, atomic, versioned), values in the Keychain — one blob per (project, env, layer), one keychain read per export. No last4 for env vars (a last4 of true is the value).
  • MCP: list_env_projects, list_env_vars (tier 1, metadata), pull_env (tier 2), set_env_var (writes the local layer, like store_key). Deliberately no tool returns a valuePATCHBAY_ALLOW_SECRET_READ does not unlock one.

Full rationale: docs/env-vault.md.

Verification

  • cargo test --workspace: 585 passing (481 core / 73 cli / 30 mcp / 1 doctest); cargo clippy --workspace --all-targets -- -D warnings clean; crates/patchbay-mcp/smoke.sh PASS (tool set updated).
  • Real-binary smoke against an isolated PATCHBAY_CONFIG_DIR: init auto-adopts .infisical.json and pins the active account; a copied checkout resolves through the marker from a subdirectory; a "machine B" without the manifest gets the explicit bring-your-projects.json error, and works after copying it; wrong-account pull refuses with the switch hint. No real keychain/network touched.
  • Rebased on main after v0.2.0: instructions renumbered around the migration point, five routers merged, smoke tool set extended.

Follow-up (tracked separately)

pb export should carry projects.json in the migration bundle (attachments and local-layer values deliberately excluded).

@sonarqubecloud

Copy link
Copy Markdown

@YJack0000
YJack0000 requested a review from yui0303 August 13, 2026 16:58
@YJack0000

Copy link
Copy Markdown
Contributor Author

@yui0303 AI check 沒問題(585 tests 綠、clippy -D warnings 乾淨、Sonar pass、MCP smoke PASS),可以 review/merge。CI 三個 check 都已綠;merge 被 org ruleset 的 1-approval 要求擋住,approve 後我這邊會掛 auto merge 讓它自動進。

@YJack0000
YJack0000 merged commit 9037bdc into main Aug 13, 2026
3 checks passed
@YJack0000
YJack0000 deleted the claude/local-vault-multi-project-d6b580 branch August 13, 2026 17:10
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