fix(approval): raise gateway approval timeout to 300s, honest stale-tap UX, offer Always on mixed prompts (#68597)

Three related messaging-approval fixes:

1. approvals.timeout default 60 -> 300. PR #63501 collapsed the gateway
   wait onto the canonical approvals.timeout (previously
   gateway_timeout=300), silently shrinking messaging approval windows
   to 60s. Push-notification approvals routinely arrive later than a
   minute; taps landed after the wait had already failed closed.

2. Stale-tap honesty: adapters resolved the approval AFTER rendering
   '<checkmark> Approved by <user>' (Telegram/Discord/Slack), or ignored a zero
   resolve count (WhatsApp Cloud/Feishu). A tap on an expired prompt
   claimed approval while the command had already been denied. All
   button paths now resolve first and render 'Approval expired -
   command was not run' when nothing was waiting.

3. Mixed-warning prompts (dangerous pattern + tirith finding) now offer
   Always: the persistence layer already permanently allowlists the
   pattern key and downgrades the tirith key to session scope, but the
   UI hid Always whenever ANY tirith warning was present. Pure-tirith
   prompts still withhold Always (content findings are session-max by
   design), and Smart-DENY overrides remain once-only.
This commit is contained in:
Teknium 2026-07-21 05:41:41 -07:00 • committed by GitHub
parent afb7bf6a5a
commit a31a31826c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 219 additions and 75 deletions

View file

@ -2872,6 +2872,22 @@ class FeishuAdapter(BasePlatformAdapter):
"Feishu button resolved %d approval(s) for session %s (choice=%s, user=%s)",
count, state["session_key"], choice, user_name,
)
if not count and choice != "deny":
# The card was already updated synchronously to "Approved" by
# the callback response, but nothing was waiting — the wait
# already timed out (fail-closed deny) or was resolved via
# /approve. Correct the record so the user doesn't believe
# the command ran.
_chat = str(state.get("chat_id", "") or chat_id or "")
if _chat:
try:
await self.send(
_chat,
"⌛ That approval had already expired — the command "
"was not run (it timed out or was resolved elsewhere).",
)
except Exception:
logger.debug("[Feishu] expired-approval notice failed", exc_info=True)
except Exception as exc:
logger.error("Failed to resolve gateway approval from Feishu button: %s", exc)