An alternative to #59's gate, or a step before it. The two are in tension and the tension is the point of this issue.
Context
#59 proposes converting anonymous visitors by withholding: reveal two or three findings, lock the rest behind signup. It is a real reversal — today an anonymous audit returns the complete result, and share links are fully public — and it trades goodwill for conversion.
There is a softer instrument that captures the same lead without taking anything away: offer to email the report. The person keeps the full result on screen; some fraction of them hand over an address to keep it. Nothing is hidden, nothing is reversed, and the ones who decline are not worse off than they are today.
We already have the delivery half. The alert work shipped a Resend adapter, a durable outbox, provider retries and one-click unsubscribe.
Scope
In
- An optional email field on the anonymous result: "Email me this report."
- One message containing the audited URL, score, counts by impact, and a link to the existing public result.
- Reuse of the existing outbox and sender rather than a second delivery path.
- Unsubscribe and suppression handling consistent with the alert mail.
Out
This endpoint is an abuse vector, and that shapes the design
An unauthenticated endpoint that sends mail to an arbitrary address is a mail bomb primitive: paste victim@example.com, submit repeatedly, and we are the ones delivering it. Our domain's reputation is the collateral, and reputation lost this way is slow to rebuild.
So the constraints are not optional extras:
- No user-controlled content in the message. The body is our template plus an audit id. No free-text field, no reply-to, no "add a note".
- One send per audit. The message is a receipt for a specific result, not a resend button.
- Rate limited on the address as well as the IP. The existing per-IP buckets bound one source; the thing worth bounding here is how often any single address can be targeted, which is a per-recipient bucket.
makeRateLimit already supports several rules per route — the signup path does exactly this with IP and email.
- Suppression is honoured before sending. Someone who unsubscribed from alerts must not receive this.
Worth saying plainly: if these are inconvenient to build, that is an argument for not shipping the feature, not for shipping it without them.
What this is really asking
Both instruments capture leads; they cost different things.
|
Withholding (#59) |
Email capture (this) |
| What the visitor gets |
Part of the result |
All of it |
| What we get |
An account, or nothing |
An address, or nothing |
| Reverses a shipped decision |
Yes |
No |
| Share-link leak |
Yes — an incognito window defeats it |
No |
| Abuse surface |
None new |
Real, see above |
They are not exclusive. The sequence worth considering is this one first — it is cheaper, reversible, and measurable — with #59 as the harder move if the numbers say the soft one is not enough. Deciding that is the actual value of this issue; the implementation is small.
Acceptance criteria
An alternative to #59's gate, or a step before it. The two are in tension and the tension is the point of this issue.
Context
#59 proposes converting anonymous visitors by withholding: reveal two or three findings, lock the rest behind signup. It is a real reversal — today an anonymous audit returns the complete result, and share links are fully public — and it trades goodwill for conversion.
There is a softer instrument that captures the same lead without taking anything away: offer to email the report. The person keeps the full result on screen; some fraction of them hand over an address to keep it. Nothing is hidden, nothing is reversed, and the ones who decline are not worse off than they are today.
We already have the delivery half. The alert work shipped a Resend adapter, a durable outbox, provider retries and one-click unsubscribe.
Scope
In
Out
This endpoint is an abuse vector, and that shapes the design
An unauthenticated endpoint that sends mail to an arbitrary address is a mail bomb primitive: paste victim@example.com, submit repeatedly, and we are the ones delivering it. Our domain's reputation is the collateral, and reputation lost this way is slow to rebuild.
So the constraints are not optional extras:
makeRateLimitalready supports several rules per route — the signup path does exactly this with IP and email.Worth saying plainly: if these are inconvenient to build, that is an argument for not shipping the feature, not for shipping it without them.
What this is really asking
Both instruments capture leads; they cost different things.
They are not exclusive. The sequence worth considering is this one first — it is cheaper, reversible, and measurable — with #59 as the harder move if the numbers say the soft one is not enough. Deciding that is the actual value of this issue; the implementation is small.
Acceptance criteria
DECISIONS.md.