Reference 2 of 3
Proving which subscriber is cancelling
If you want an offer applied automatically, we have to know which subscription to apply it to. A visitor typing an ID into a form is a claim, not proof. This is how you turn it into proof — and what that proof does and does not cover.
When the check runs
The check runs once, on the accept. Not when the page opens, not when a reason is chosen. Asking earlier would let anyone probe the difference between “no key configured” and “bad signature”, and that difference is worth more to an attacker than it is to you.
The window
A signature is accepted for twenty-four hours from the timestamp you signed. That window lives in one place, in the worker that serves the page. The database does not read your timestamp at all — it checks the signature and nothing else. If that one line were removed, every signature you have ever issued would be valid forever.
There is no replay protection. Within those twenty-four hours the same signed pair can be presented more than once, and we will verify it every time. We do not keep a register of signatures already used. If that matters for your case, mint a fresh timestamp per visitor rather than reusing one link.
What a failed check looks like
When a signature does not check out, nothing visible happens. The flow continues, the event is written without an identity, and the visitor is never told that anything was checked. What you lose is the automatic part: that acceptance is recorded for you to apply by hand.
How your signing key is stored
Your signing key is not encrypted at rest, and the reason is not neglect. We hold the only copy: it is shown once and no part of the service will show it again. Putting it behind a passphrase would mean that losing the passphrase makes it unreadable, with no reset we could offer you. The Stripe key does not have that problem — it is Stripe's, and you can reissue it in a minute. Different recoverability, different answer. We treat this as an open item, not a settled one.