Signature Request Link Expiry Warnings
Signature Request Link Expiry Warnings
Available from v0.1.363
The signatures dashboard now warns agents when a pending signature request link is close to expiry, and blocks sharing of links that have already lapsed.
Background
When a signature request is created, it carries an expiry timestamp (tokenExpiresAt). Before v0.1.363, the signatures dashboard showed the expiry date as plain text alongside a 'Copy link' button — but there was no visual urgency and no check performed at the moment of copying. Agents could (and did) share links that were hours away from — or had already passed — their expiry.
How It Works
At render time, and again at the moment the agent clicks 'Copy link', the dashboard computes:
const hoursUntilExpiry = (tokenExpiresAt - Date.now()) / 3_600_000;
This value drives three distinct UI states for each pending row.
State 1 — Link is healthy (> 24 hours remaining)
No change to the existing behaviour. The expiry date is shown as plain text and the 'Copy link' button works normally.
State 2 — Link is expiring soon (< 24 hours remaining)
-
An amber 'Expiring soon' badge appears alongside the expiry date.
-
The 'Copy link' button remains available.
-
Clicking it copies the link and triggers a toast notification:
'This link expires in 8 hours — consider resending a fresh request.'
(The hour count in the toast reflects the actual time remaining.)
State 3 — Link is critically close to expiry (< 1 hour remaining)
- The 'Copy link' button is removed entirely.
- It is replaced by a 'Resend (expires soon)' button that initiates a fresh signature request.
- Copying the expiring link is blocked to prevent sharing a useless URL.
UI Summary
hoursUntilExpiry | Badge | Copy link | Toast on copy | Resend button |
|---|---|---|---|---|
| ≥ 24 h | None | ✅ | None | — |
| 1 h – 24 h | 🟡 Expiring soon | ✅ | ✅ (with hours remaining) | — |
| < 1 h | 🟡 Expiring soon | ❌ Blocked | — | ✅ |
Implementation Notes
- All logic is client-side (
signatures-dashboard.tsx). No backend or API changes are required. - The expiry check uses
tokenExpiresAtalready present in the pending request payload. - The toast copy adapts dynamically: the message always reflects the real hours (or minutes) remaining at the time of the copy attempt.