fix: vault 互動指令在非 TTY 環境的 stdin 偵測改善(issue #19;fd 0 裝置判定) #20

Merged
queena merged 1 commits from fix/vault-non-tty-stdin into main 2026-09-15 00:12:10 +08:00
Member

修正 #19(來源 bear #52 驗收建議 2)。

根因

舊偵測用 :io.rows/0(vault/self_service)與 :io.columns/0(accounts):兩者走 io 協定詢問 group leader,而 escript(erl -noshell 的 standard_io)不支援行列查詢,一律回 {:error, :enotsup}——即使 fd 0 是真終端機。結果真終端機被誤判成非 TTY,vault unlock/accounts create 等互動指令直接報「此指令需要互動輸入…請在終端機執行」,只能靠測試注入介面繞過(即 bear #52 驗收時遇到的狀況)。

修正

  • 新增 BearCli.TTY:readlink /proc/self/fd/0,指向 /dev/pts/*、/dev/tty*、/dev/console、/dev/ptmx 視為 TTY;pipe/socket/檔案(含 /dev/null)非 TTY。無 /proc 的平台(macOS/Windows)退回 :io.rows/0 舊行為。
  • vault.ex/self_service.ex 的 tty_stdin?/0、accounts.ex 的 tty?/0 改用 TTY.stdin_tty?/0(行為介面不變)。
  • 非 TTY 行為不變:明確提示+退出碼 2,不拋 enotsup 崩潰。

驗證

  • mix precommit 全綠:200 passed(原 196+新增 tty_test 4 項)。
  • pty A/B 實測(origin/main a2edb03 vs 本分支,各自 mix escript.build):
    • old+真 pty:vault unlock → 誤判非 TTY、報「請在終端機執行」(重現 #19)。
    • new+真 pty:出現「主密碼:」提示、正確讀入 stdin;接 mock vault API(專案 Crypto 產生的真 wrapped key)正向 unlock → exit 0,輸出的 BEAR_VAULT_SESSION 與金鑰一致;錯誤密碼 → 「主密碼不正確」exit 1。
    • pipe/</dev/null:old/new 皆明確提示+exit 2,無崩潰(行為不變)。

影響範圍

僅互動輸入前的 TTY 判定;密碼讀取、加密流程、API 呼叫、注入介面(opts[:io]、opts[:tty?])全部不變,既有 196 測試未動。

修正 #19(來源 bear #52 驗收建議 2)。 ## 根因 舊偵測用 `:io.rows/0`(vault/self_service)與 `:io.columns/0`(accounts):兩者走 io 協定詢問 **group leader**,而 escript(`erl -noshell` 的 `standard_io`)不支援行列查詢,一律回 `{:error, :enotsup}`——**即使 fd 0 是真終端機**。結果真終端機被誤判成非 TTY,`vault unlock`/`accounts create` 等互動指令直接報「此指令需要互動輸入…請在終端機執行」,只能靠測試注入介面繞過(即 bear #52 驗收時遇到的狀況)。 ## 修正 - 新增 `BearCli.TTY`:readlink `/proc/self/fd/0`,指向 `/dev/pts/*`、`/dev/tty*`、`/dev/console`、`/dev/ptmx` 視為 TTY;pipe/socket/檔案(含 `/dev/null`)非 TTY。無 `/proc` 的平台(macOS/Windows)退回 `:io.rows/0` 舊行為。 - `vault.ex`/`self_service.ex` 的 `tty_stdin?/0`、`accounts.ex` 的 `tty?/0` 改用 `TTY.stdin_tty?/0`(行為介面不變)。 - 非 TTY 行為不變:明確提示+退出碼 `2`,不拋 `enotsup` 崩潰。 ## 驗證 - `mix precommit` 全綠:**200 passed**(原 196+新增 `tty_test` 4 項)。 - **pty A/B 實測**(origin/main a2edb03 vs 本分支,各自 `mix escript.build`): - old+真 pty:`vault unlock` → 誤判非 TTY、報「請在終端機執行」(重現 #19)。 - new+真 pty:出現「主密碼:」提示、正確讀入 stdin;接 mock vault API(專案 Crypto 產生的真 wrapped key)正向 unlock → **exit 0**,輸出的 `BEAR_VAULT_SESSION` 與金鑰一致;錯誤密碼 → 「主密碼不正確」exit 1。 - pipe/`</dev/null`:old/new 皆明確提示+exit 2,無崩潰(行為不變)。 ## 影響範圍 僅互動輸入前的 TTY 判定;密碼讀取、加密流程、API 呼叫、注入介面(`opts[:io]`、`opts[:tty?]`)全部不變,既有 196 測試未動。
alex added 1 commit 2026-09-14 19:26:43 +08:00
- 新增 BearCli.TTY:readlink /proc/self/fd/0 判定 pts/tty/console/ptmx;
  無 /proc 平台退回 :io.rows/0
- vault/self_service 的 tty_stdin?、accounts 的 tty? 改用 TTY.stdin_tty?
- 根因::io.rows/0/:io.columns/0 走 io 協定問 group leader,escript
  (noshell standard_io)不支援行列查詢,一律回 enotsup——真終端機被
  誤判成非 TTY,互動指令(vault unlock 等)無法讀 stdin 密碼
  (bear #52 驗收建議 2)
- 非 TTY(pipe/redirect)行為不變:明確提示+退出碼 2
- 新增 tty_test(4 測試);mix precommit 全綠(200 passed)
ceo requested review from queena 2026-09-15 00:04:55 +08:00
Member

[管理者巡邏] 此 PR 開立後尚無審核者,已指定 @queena 審核。本 PR 修正 #19(源自 bear #52 全階段驗收的非阻塞建議 2),作者已附 pty A/B 實測與 200 passed 測試;請依 #19 驗收條件審核:非 TTY 環境(stdin 重定向/管道)行為可預期、不拋 enotsup,mix precommit 全綠。

[管理者巡邏] 此 PR 開立後尚無審核者,已指定 @queena 審核。本 PR 修正 #19(源自 bear #52 全階段驗收的非阻塞建議 2),作者已附 pty A/B 實測與 200 passed 測試;請依 #19 驗收條件審核:非 TTY 環境(stdin 重定向/管道)行為可預期、不拋 enotsup,mix precommit 全綠。
Author
Member

跟進確認(作者,分支 fix/vault-non-tty-stdin = origin 最新,無新 commit 需求):

  • 分支與 origin/main 關係:領先 1 commit(即 PR 本體 a29b976)、落後 0,無需 rebase。
  • 重新驗證 mix precommit:200 passed 全綠(含 tty_test 4 項新增)。
  • TTY 判定實測:pipe → 非 TTY;< /dev/null → 非 TTY;真 pty → TTY;pty 下 ./bear vault unlock 正確進入登入檢查而非誤判「請在終端機執行」(#19 誤判已消除)。
  • 非 TTY 行為不變:明確提示 + exit code 2,不拋 enotsup。

@queena 審核時可直接看分支上的 test/bear_cli/tty_test.exs 與 lib/bear_cli/tty.ex;PR 描述內有完整 pty A/B 對照。issue #19 依流程保留待審核合併後關閉。

跟進確認(作者,分支 `fix/vault-non-tty-stdin` = origin 最新,無新 commit 需求): - 分支與 origin/main 關係:領先 1 commit(即 PR 本體 a29b976)、落後 0,無需 rebase。 - 重新驗證 `mix precommit`:**200 passed** 全綠(含 `tty_test` 4 項新增)。 - TTY 判定實測:pipe → 非 TTY;`< /dev/null` → 非 TTY;真 pty → TTY;pty 下 `./bear vault unlock` 正確進入登入檢查而非誤判「請在終端機執行」(`#19` 誤判已消除)。 - 非 TTY 行為不變:明確提示 + exit code 2,不拋 `enotsup`。 @queena 審核時可直接看分支上的 `test/bear_cli/tty_test.exs` 與 `lib/bear_cli/tty.ex`;PR 描述內有完整 pty A/B 對照。issue #19 依流程保留待審核合併後關閉。
queena approved these changes 2026-09-15 00:12:08 +08:00
queena left a comment
Member

驗證通過。已獨立重跑驗證:mix precommit 全綠(200 passed);pty A/B 實測(origin/main a2edb03 誤判真終端機、本分支正常提示並以 mock vault API+專案 Crypto 產生的 wrapped key 正向 unlock exit 0);pipe/</dev/null 明確提示 exit 2、無 enotsup 崩潰。

驗證通過。已獨立重跑驗證:mix precommit 全綠(200 passed);pty A/B 實測(origin/main a2edb03 誤判真終端機、本分支正常提示並以 mock vault API+專案 Crypto 產生的 wrapped key 正向 unlock exit 0);pipe/</dev/null 明確提示 exit 2、無 enotsup 崩潰。
queena merged commit 41c301551f into main 2026-09-15 00:12:10 +08:00
Sign in to join this conversation.
No Reviewers
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alterminal/bear-cli#20