vault 指令在非 TTY 環境的 stdin 偵測改善(:io.rows() enotsup) #19

Closed
opened 2026-09-14 18:34:40 +08:00 by ceo · 3 comments
Member

來源:bear #52 全階段驗收的非阻塞建議 2(父追蹤項:bear #39)。

背景

#52 驗收時發現:CLI 互動輸入(密碼等)在 stdin 非 TTY 時,Erlang 的 :io.rows() 回 enotsup(本機 escript 環境重現),導致無法直接讀 stdin 密碼,需經官方測試注入介面(opts[:io])繞過。功能面不受影響(驗收以注入介面完成全流程),但非互動環境(CI、管道、腳本)可用性受損。

工作

改善 stdin 互動偵測:不再只依賴 :io.rows(),可考慮偵測 /dev/tty 存在性或其他跨平台方式,讓非 TTY 環境下能正確判定可否互動、給出明確錯誤或改用注入介面。

驗收

  • 非 TTY 環境(stdin 重定向/管道)執行 vault unlock 等互動指令,行為可預期:可互動則正常讀取,不可互動則明確提示,不再拋 enotsup 崩潰;
  • mix precommit 全綠(含既有 196 測試與新增測試)。
來源:bear #52 全階段驗收的非阻塞建議 2(父追蹤項:bear #39)。 ## 背景 #52 驗收時發現:CLI 互動輸入(密碼等)在 stdin 非 TTY 時,Erlang 的 `:io.rows()` 回 `enotsup`(本機 escript 環境重現),導致無法直接讀 stdin 密碼,需經官方測試注入介面(`opts[:io]`)繞過。功能面不受影響(驗收以注入介面完成全流程),但非互動環境(CI、管道、腳本)可用性受損。 ## 工作 改善 stdin 互動偵測:不再只依賴 `:io.rows()`,可考慮偵測 `/dev/tty` 存在性或其他跨平台方式,讓非 TTY 環境下能正確判定可否互動、給出明確錯誤或改用注入介面。 ## 驗收 - 非 TTY 環境(stdin 重定向/管道)執行 `vault unlock` 等互動指令,行為可預期:可互動則正常讀取,不可互動則明確提示,不再拋 `enotsup` 崩潰; - `mix precommit` 全綠(含既有 196 測試與新增測試)。
alex was assigned by ceo 2026-09-14 18:34:40 +08:00
Member

收到,開始處理:改善 stdin 互動偵測,不再只依賴 :io.rows(),讓非 TTY 環境(CI/管道)下 vault 互動指令有可預期行為(明確提示或走注入介面),並補測試、跑 mix precommit 全綠。

收到,開始處理:改善 stdin 互動偵測,不再只依賴 `:io.rows()`,讓非 TTY 環境(CI/管道)下 `vault` 互動指令有可預期行為(明確提示或走注入介面),並補測試、跑 `mix precommit` 全綠。
Member

已完成修正,PR #20(分支 fix/vault-non-tty-stdin,commit a29b976)待審核。

根因::io.rows/0/:io.columns/0 走 io 協定詢問 group leader,escript(erl -noshell 的 standard_io)不支援行列查詢、一律回 enotsup——真終端機被誤判成非 TTY,vault unlock 等互動指令直接報「請在終端機執行」。

修正:新增 BearCli.TTY,改 readlink /proc/self/fd/0 判定 fd 0 實際裝置(/dev/pts/*、/dev/tty*、/dev/console、/dev/ptmx = TTY;pipe/檔案/socket 非 TTY);無 /proc 平台退回 :io.rows/0。vault/self_service/accounts 三處偵測點統一改用。非 TTY 行為不變(明確提示+退出碼 2,不崩潰)。

驗收對應:

  • pty A/B 實測:origin/main 在真終端機下重現誤判;新碼正常出現「主密碼:」提示並讀取 stdin,接 mock API(專案 Crypto 產生的真 wrapped key)正向 unlock exit 0、session 正確;pipe/</dev/null 皆明確提示 exit 2。
  • mix precommit 全綠(200 passed=原 196+新增 TTY 測試 4)。

issue 依流程保留待審核後關閉。

已完成修正,PR #20(分支 `fix/vault-non-tty-stdin`,commit a29b976)待審核。 **根因**:`:io.rows/0`/`:io.columns/0` 走 io 協定詢問 group leader,escript(`erl -noshell` 的 `standard_io`)不支援行列查詢、一律回 `enotsup`——真終端機被誤判成非 TTY,`vault unlock` 等互動指令直接報「請在終端機執行」。 **修正**:新增 `BearCli.TTY`,改 readlink `/proc/self/fd/0` 判定 fd 0 實際裝置(`/dev/pts/*`、`/dev/tty*`、`/dev/console`、`/dev/ptmx` = TTY;pipe/檔案/socket 非 TTY);無 `/proc` 平台退回 `:io.rows/0`。`vault`/`self_service`/`accounts` 三處偵測點統一改用。非 TTY 行為不變(明確提示+退出碼 2,不崩潰)。 **驗收對應**: - pty A/B 實測:origin/main 在真終端機下重現誤判;新碼正常出現「主密碼:」提示並讀取 stdin,接 mock API(專案 Crypto 產生的真 wrapped key)正向 unlock exit 0、session 正確;pipe/`</dev/null` 皆明確提示 exit 2。 - `mix precommit` 全綠(200 passed=原 196+新增 TTY 測試 4)。 issue 依流程保留待審核後關閉。
Member

PR #20 已驗證符合本 issue 要求並合併(merge commit 41c30155),關閉本 issue。

審核驗證(獨立重跑):

  • mix precommit 全綠:200 passed(原 196+新增 tty_test 4 項)。
  • pty A/B 實測:origin/main(a2edb03)在真終端機下 vault unlock 誤判非 TTY、報「請在終端機執行」exit 2(重現本 issue);新碼正常出現「主密碼:」提示,接 mock vault API(以專案 Crypto 產生的真 wrapped key)正向 unlock exit 0、BEAR_VAULT_SESSION 輸出正確;錯誤密碼 →「主密碼不正確」exit 1。
  • 非 TTY(pipe、/dev/null 重定向):新舊皆明確提示+exit 2,無 enotsup 崩潰(行為不變)。
  • 已確認 lib/ 內 :io.rows/:io.columns 僅餘 BearCli.TTY 相關說明註解,三個偵測點(vault/self_service/accounts)皆已改用 TTY.stdin_tty?/0。
PR #20 已驗證符合本 issue 要求並合併(merge commit 41c30155),關閉本 issue。 審核驗證(獨立重跑): - mix precommit 全綠:200 passed(原 196+新增 tty_test 4 項)。 - pty A/B 實測:origin/main(a2edb03)在真終端機下 vault unlock 誤判非 TTY、報「請在終端機執行」exit 2(重現本 issue);新碼正常出現「主密碼:」提示,接 mock vault API(以專案 Crypto 產生的真 wrapped key)正向 unlock exit 0、BEAR_VAULT_SESSION 輸出正確;錯誤密碼 →「主密碼不正確」exit 1。 - 非 TTY(pipe、/dev/null 重定向):新舊皆明確提示+exit 2,無 enotsup 崩潰(行為不變)。 - 已確認 lib/ 內 :io.rows/:io.columns 僅餘 BearCli.TTY 相關說明註解,三個偵測點(vault/self_service/accounts)皆已改用 TTY.stdin_tty?/0。
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alterminal/bear-cli#19