feat: gate confirm-mode tsm run on biometric presentability, not caller TTY#16
Merged
Merged
Conversation
Adds AuthProvider.canAuthenticate() (canEvaluatePolicy, presents no UI) and exposes it as the auth.can_confirm JSON-RPC method via Vault.canConfirm(). This lets a caller ask whether the daemon can present a Touch ID prompt right now (biometrics enrolled, not locked out, GUI login session present) before requesting a confirm-gated secret β independent of the caller's TTY, since the daemon owns the prompt and presents it on the user's screen regardless of how the caller's stdin is wired.
β¦ caller TTY tsm run previously refused any confirm-gated secret whenever stdin was not a TTY, using caller-TTY as a proxy for 'a human is present'. That proxy misfires for agent harnesses (Claude Code's Bash tool) whose background shells have no TTY but run in a live GUI session where Touch ID works fine β the daemon presents the prompt on the user's screen regardless of the caller's stdin. Replace the term.IsTerminal(stdin) check with a daemon query: when requested secrets are confirm-gated, ask auth.can_confirm. Proceed (daemon prompts) when biometrics can be presented; refuse cleanly only in truly headless contexts (no GUI login session β CI, cron, ssh without a console). Update credential-usage SKILL.md Β§3 to match: confirm-gated secrets now work from non-TTY callers; the agent should warn the user a Touch ID prompt is coming rather than hand off to a separate terminal.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
tsm runpreviously refused any confirm-gated secret whenever stdin was not a TTY, using caller-TTY as a proxy for "a human is present to approve." That proxy misfires for agent harnesses like Claude Code's Bash tool: their background shells have no TTY but run in a live GUI login session where Touch ID works fine. The Touch ID prompt is a system dialog presented by the daemon (which lives in the user's GUI session) β it appears on the user's screen regardless of how the caller's stdin is wired. So the old check blocked a perfectly workable path (verified:canEvaluatePolicyreturnstrue, and a real prompt appears, from a non-TTY context).This replaces the TTY heuristic with a capability check against the daemon.
Changes
Daemon (
0bc528d)AuthProvider.canAuthenticate()βcanEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics), presents no UI.auth.can_confirmJSON-RPC method viaVault.canConfirm()β{"can_confirm": bool}.CLI + skill (
ee6b5d7)tsm rundrops theterm.IsTerminal(stdin)gate. When requested secrets are confirm-gated, it asksauth.can_confirm: proceed (daemon prompts) when biometrics can be presented; refuse cleanly only in truly headless contexts (no GUI session β CI, cron, ssh without a console).credential-usage/SKILL.mdΒ§3 rewritten: confirm-gated secrets now work from non-TTY callers; the agent should warn the user a Touch ID prompt is coming rather than hand off to a separate terminal.Behavior change to note
A confirm-gated secret in an attended GUI session will now also prompt for genuinely unattended automation (it blocks on the dialog until the system timeout, instead of failing fast as the old TTY check did). That's the intended semantics of confirm mode β require a human touch per access β but it is a change from the prior fail-fast.
Testing
testAuthCanConfirmReportsBiometricAvailability.cmdtests pass;tsm runconfirm tests rewritten to driveauth.can_confirm(biometrics available β proceeds; unavailable β refuses).auth.can_confirmover the wire β{"can_confirm":true}.tsm runβ injected via cached unlock, no prompt.tsm runβ Touch ID prompt appeared and was approved, secret injected. (Old code: hardstdin is not a TTYrefusal.)