Skip to content

[feature] env vault 認得 Infisical 的子路徑 - #23

Merged
YJack0000 merged 2 commits into
mainfrom
feat/env-secret-path
Aug 28, 2026
Merged

[feature] env vault 認得 Infisical 的子路徑#23
YJack0000 merged 2 commits into
mainfrom
feat/env-secret-path

Conversation

@YJack0000

Copy link
Copy Markdown
Contributor

在修什麼

pb env link 只能指定 Infisical 的 project id、account 與環境名稱對應,pb env pull 永遠從根路徑 /。但 Infisical 的 secrets 有資料夾階層,實務上一個 project 底下常常每個服務一個資料夾。

實際卡住的案例:pathorsAI/coldmail 的 secrets 在 project 3ab516bd/outbox 底下,所以那個 repo 完全用不了 env vault,只能退回手動 infisical run --path /outbox -- <cmd>

而且失敗是無聲的:從根路徑拉會成功、回 0 筆、什麼都不說。所以這次除了加路徑,也讓那個症狀說得出話來。

改了什麼

檔案 內容
crates/patchbay-core/src/envs.rs SyncConfig::secret_pathnormalize_secret_path()remote_path() / is_root_path()
crates/patchbay-core/src/env_sync.rs pull 帶 --pathPullOutcome::secret_path;失敗訊息與空結果的 note 都指出路徑
crates/patchbay-cli/src/env.rs pb env link --pathpb env projects 的 SYNC 欄顯示非根路徑
crates/patchbay-mcp/src/envs.rs list_env_projectspull_env 的說明補上 secret_path
docs/env-vault.md 新增〈Which folder of the remote〉,並從〈A project is a name, not a path〉指過來

相容性

#[serde(default = "default_secret_path")]/。欄位永遠序列化(沒有 skip_serializing_if),所以舊檔案在下次寫入時會補上;又因為沒有 deny_unknown_fields,舊版 patchbay 也讀得動新檔案。兩個方向都相容,所以 PROJECTS_FILE_VERSION 維持 1。

測試 test_a_registry_written_before_secret_paths_existed_still_loads 用的是逐字的 0.4 格式 projects.json 字面值(有 sync 區塊、沒有 secret_path),斷言它讀成 / 且下次寫入會補上欄位。

一個容易誤解的地方

這裡的 secret path 是「Infisical 內部的資料夾」,跟 docs/env-vault.md〈A project is a name, not a path〉那節講的「registry 不存檔案系統絕對路徑」是兩回事。那條規則沒有被違反,文件已補上指標避免後人誤讀。

驗證

  • cargo buildcargo test(78 + 643 + 31 + 1 doc,0 failed)、cargo clippy --all-targets -- -D warningscargo fmt --check 全過
  • 沒有網路:全部走既有的 FakeExec + tempdir $HOME + MemoryKeystore
  • 用真 binary 在拋棄式 $HOME 端到端跑過--path 'outbox/' 正規化成 /outbox、registry 寫入正確、pb env projects 顯示 infisical:jack@pathors.com /outbox、手動把 secret_path 從 JSON 刪掉之後仍然 exit 0

幾個判斷點(歡迎推翻)

  1. --path 只在非 / 時才傳給 infisicalinfisical export 本來就預設根路徑,傳 --path / 不改變結果卻會縮小相容的 CLI 版本範圍。副作用:既有使用者觀察到的命令列一個 byte 都沒變。
  2. 空結果的 note 不在原始需求裡,但那正是 coldmail 的症狀(成功、安靜、空的),只加欄位不讓症狀說話感覺是做一半。
  3. pb env link 仍然整包取代 sync 設定,所以不帶 --path 重 link 會重置成 /。這跟 --domain--map 的行為一致,文件已寫明。要改成 merge 語意的話說一聲。
  4. EnvSyncRecord(人類可讀的 manifest)刻意不含 domainenv_map,所以我也沒把 secret_path 加進去;它仍然在加密 payload 裡。

`pb env link` 只吃 project id、account 與環境對應,`pb env pull` 永遠從
Infisical 的根路徑 `/` 拉。但 Infisical 的 secrets 有資料夾階層,實務上
一個 project 底下常常每個服務一個資料夾。

實際卡住的案例:pathorsAI/coldmail 的 secrets 在 project 3ab516bd 的
`/outbox` 底下,所以那個 repo 完全用不了 env vault,只能退回手動
`infisical run --path /outbox -- <cmd>`。而且失敗是無聲的——從根路徑拉
會成功、回 0 筆、什麼都不說。

- SyncConfig 加 secret_path,預設 `/`,寫入時正規化
- `pb env link --path <PATH>`;`pull` 帶上它
- 路徑出現在 `pb env projects`、MCP 的 list_env_projects 與 pull_env
- pull 回 0 筆時,note 講出它讀的是哪個資料夾並提示 --path

相容性:`#[serde(default)]`,舊的 projects.json 讀成 `/`,欄位在下次寫入
時補上;沒有 deny_unknown_fields,所以舊版 patchbay 也讀得動新檔案。
兩個方向都相容,PROJECTS_FILE_VERSION 維持 1。

註:這裡的 secret path 是「Infisical 內部的資料夾」,跟 docs/env-vault.md
〈A project is a name, not a path〉講的檔案系統路徑是兩回事,該節已補指標。
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

✅ SonarQube Quality Gate passed — pathorsAI_patchbay

0 open issues on this PR.

SonarQube 擋下兩個 rust:S3776(認知複雜度 20 與 21,上限 15),兩處都是本來就
接近上限的函式被這次新增的路徑判斷推過線。行為與訊息一字未改,只是把原本就存在
的概念從函式體裡拿出來命名。

env_sync.rs 的 `pull` 拆出三個:

- `preflight` —— 「一次 pull 值得花一個 subprocess 之前必須成立的事」。它本來就是
  一整串連續的 guard clause,四個檢查各自對應一句不同的「你該打哪個指令」,那是
  一個完整的概念而不是四個零散的 if。回傳 `&SyncConfig` 讓呼叫端不用再解一次。
- `export_args` —— 「一次 `infisical export` 的 argv」。這是本模組跟一支不屬於
  patchbay 的程式之間的契約,每個元素都是對別人 CLI 版本面的承諾,測試也逐字斷言
  它,本來就該是可以單獨指著看的一塊。`--path` 只在非根路徑才傳的理由跟著搬過去。
- `index_secrets` —— 「遠端那個陣列摺成 synced layer 的 map,以及摺掉了什麼的
  註記」。跳過的名字與重複的 key 都是記下來而不是拋出去,這條規則本身就是一個
  值得有名字的決定。

env.rs 的 `render_projects` 拆出四個 cell renderer(`roots_cell`、`sync_full`、
`sync_cell`、`envs_cell`)。它們原本就是四個具名 closure,只是被關在函式體裡而
無法單獨閱讀;每一個都是「某一欄的格子怎麼算出來」,其中兩個還各自帶著同一套
「把尾巴的後綴先從寬度裡預留掉,不要交給 truncate 吃掉」的規則。closure 沒有捕捉
外層狀態的必要(只有 `roots_cell` 用到 `roots`,改成傳 `Option<&[PathBuf]>`),
提成 free function 後 `render_projects` 只剩排版本身。

複雜度:`pull` 21 → 約 9,`render_projects` 20 → 約 6。
cargo build / test(753)/ clippy -D warnings / fmt --check 全過。
@YJack0000
YJack0000 merged commit a42f2a2 into main Aug 28, 2026
4 checks passed
@YJack0000
YJack0000 deleted the feat/env-secret-path branch August 28, 2026 03:31
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