feat(approvals): actionable approval links — single-use tokens + session-less confirm page (ADR-0043)#1765
Merged
Merged
Conversation
…ion-less confirm page (ADR-0043)
Approvers act straight from a notification without signing in. The
token behind the link is deliberately weakened on every axis of the
ADR-0043 threat table:
- scope: one token = one request + one action + one approver
- storage: SHA-256 hash only (sys_approval_token; a DB leak yields no
usable links); raw 256-bit tokens are returned exactly once
- single-use: consumed BEFORE deciding — a failed decide still burns
the token, replays render "already used"
- TTL: 72h default
- identity: the decision is audited as the bound approver ("Via action
link"), never a system actor or the page visitor
- invalidation: redemption re-checks the live request — decided,
recalled, or reassigned-away slots all answer with explanatory pages
- scanner-proof: GET /api/v1/approvals/act renders the bilingual
confirm page only; the decision happens exclusively on the POST form
(mail-gateway link prefetchers cannot approve)
remind() integrates: per-approver fan-out where each concrete identity
(user id / email) receives its own approve/reject links in the
notification payload; role:* literals keep the plain nudge. Deployments
set publicBaseUrl for absolute links in outbound email.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Summary
Closes #1743. Approvers act straight from an email/IM notification without signing in — implemented exactly along ADR-0043's threat table (
docs/adr/0043-actionable-approval-links.md), every row enforced and tested:sys_approval_token; raw 256-bit tokens returned onceVia action link), never the page visitorGET /api/v1/approvals/actrenders the bilingual confirm page only; the decision happens exclusively on thePOSTformremind()integrates with per-approver fan-out: each concrete identity gets its own approve/reject links in the notification payload (role:*literals keep the plain nudge).publicBaseUrlplugin option for absolute links in outbound email.Test plan
ada@example.com) → clicked Approve → "✅ Approved · 已通过" result page → audit rowapprove by ada@example.com, "Via action link"(NOT the signed-in Dev Admin). Replay → "Already used"; the sibling reject token → "Already decided"; garbage → "Invalid link" ✅🤖 Generated with Claude Code