Skip to content

feat(approvals): actionable email/IM notifications — single-use approval tokens #1743

Description

@os-zhuang

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.

PropertyRequirementFailure mode it prevents
Scopeexactly one action on exactly one request (approve areq_x)leaked token ≠ account takeover
Single-useconsumed jti recorded server-sideforwarded email replayed by someone else
TTLshort (e.g. 72h, aligned with SLA)months-old email approving today's request
Identity-boundtoken ↔ approver; audit records the real actoranonymous decisions on the trail
Invalidationdead the moment the request is decided / reassigned / recalledoriginal approver acting from a stale email after handover
Scanner-proofGET must not execute — land on a confirm page whose button POSTsmail-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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions