Context
The biggest lever on approval latency: approvers act straight from an email or DingTalk/Feishu card without signing in. The notification pipeline already exists — thread interactions (#1740) emit through the messaging service, which has an email channel and outbox-backed webhook delivery (sys_http_delivery) with retry/dead-letter. What's missing is what sits behind the Approve/Reject buttons in the message.
Proposal
A single-use approval token: a deliberately weakened, self-contained credential embedded in the notification's action links, plus a redemption endpoint.
| Property | Requirement | Failure mode it prevents |
|---|
| Scope | exactly one action on exactly one request (approve areq_x) | leaked token ≠ account takeover |
| Single-use | consumed jti recorded server-side | forwarded email replayed by someone else |
| TTL | short (e.g. 72h, aligned with SLA) | months-old email approving today's request |
| Identity-bound | token ↔ approver; audit records the real actor | anonymous decisions on the trail |
| Invalidation | dead the moment the request is decided / reassigned / recalled | original approver acting from a stale email after handover |
| Scanner-proof | GET must not execute — land on a confirm page whose button POSTs | mail-gateway link prefetchers (Outlook SafeLinks etc.) approving requests |
The last row is the classic real-world trap: enterprise mail security pre-fetches every link in a message. A GET-executes design gets requests approved by robots.
Scope
- Token issue (on notification emit) + redemption endpoint + consumed-token store
- Minimal session-less confirm page (request summary + confirm button)
- Email/IM templates wiring the links; deep link fallback to the Console inbox
- Independent security review of the threat model before merge — this is a deliberate bypass lane around the auth system
References
🤖 Generated with Claude Code
Context
The biggest lever on approval latency: approvers act straight from an email or DingTalk/Feishu card without signing in. The notification pipeline already exists — thread interactions (#1740) emit through the
messagingservice, which has an email channel and outbox-backed webhook delivery (sys_http_delivery) with retry/dead-letter. What's missing is what sits behind the Approve/Reject buttons in the message.Proposal
A single-use approval token: a deliberately weakened, self-contained credential embedded in the notification's action links, plus a redemption endpoint.
approve areq_x)jtirecorded server-sideThe last row is the classic real-world trap: enterprise mail security pre-fetches every link in a message. A GET-executes design gets requests approved by robots.
Scope
References
ApprovalMessagingSurface/notify()in plugin-approvals (feat(approvals): thread interactions — reassign, remind, request-info, comment + SLA & step progress #1740)@objectstack/service-messaging(email-channel),sys_http_deliveryoutbox🤖 Generated with Claude Code