Skip to content

feat: gate confirm-mode tsm run on biometric presentability, not caller TTY#16

Merged
tashian merged 2 commits into
mainfrom
feat/confirm-biometric-presentability
May 31, 2026
Merged

feat: gate confirm-mode tsm run on biometric presentability, not caller TTY#16
tashian merged 2 commits into
mainfrom
feat/confirm-biometric-presentability

Conversation

@tashian

@tashian tashian commented May 31, 2026

Copy link
Copy Markdown
Owner

What & why

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 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: canEvaluatePolicy returns true, 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.
  • New auth.can_confirm JSON-RPC method via Vault.canConfirm() β†’ {"can_confirm": bool}.

CLI + skill (ee6b5d7)

  • tsm run drops the term.IsTerminal(stdin) gate. When requested secrets are confirm-gated, it asks auth.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

  • Swift: 124 tests pass, incl. new testAuthCanConfirmReportsBiometricAvailability.
  • Go: all cmd tests pass; tsm run confirm tests rewritten to drive auth.can_confirm (biometrics available β†’ proceeds; unavailable β†’ refuses).
  • Live, from a non-TTY shell against installed binaries:
    • auth.can_confirm over the wire β†’ {"can_confirm":true}.
    • non-confirm tsm run β†’ injected via cached unlock, no prompt.
    • confirm tsm run β†’ Touch ID prompt appeared and was approved, secret injected. (Old code: hard stdin is not a TTY refusal.)

tashian added 2 commits May 30, 2026 20:41
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.
@tashian tashian merged commit da9140b into main May 31, 2026
1 check passed
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