feat: GDPR compliance — anonymization, unsubscribe, consent tracking
- Add consent_given_at and anonymized_at fields + Alembic migration (002) - Add GET /waitlist/unsubscribe endpoint (HMAC token, anonymizes PII) - Add cleanup.py: cron-able script to anonymize unconfirmed entries after 48h - Clear IP address on email confirmation (no longer needed) - Add unsubscribe link in confirmation email footer - Record consent timestamp on signup - Add 4 new tests (unsubscribe, consent timestamp) - Update .env.example, schemas
This commit is contained in:
@@ -24,7 +24,7 @@ def _headers() -> dict[str, str]:
|
||||
}
|
||||
|
||||
|
||||
async def send_confirmation_email(email: str, confirm_url: str) -> bool:
|
||||
async def send_confirmation_email(email: str, confirm_url: str, unsubscribe_url: str = "") -> bool:
|
||||
"""Send a double opt-in confirmation email. Returns True on success."""
|
||||
if not settings.brevo_configured:
|
||||
logger.warning("Brevo not configured — skipping confirmation email for %s***", email[:3])
|
||||
@@ -37,7 +37,7 @@ async def send_confirmation_email(email: str, confirm_url: str) -> bool:
|
||||
},
|
||||
"to": [{"email": email}],
|
||||
"subject": "Confirm your spot on the adiuvAI waitlist",
|
||||
"htmlContent": _confirmation_html(confirm_url),
|
||||
"htmlContent": _confirmation_html(confirm_url, unsubscribe_url),
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -78,7 +78,7 @@ async def add_contact_to_list(email: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _confirmation_html(confirm_url: str) -> str:
|
||||
def _confirmation_html(confirm_url: str, unsubscribe_url: str = "") -> str:
|
||||
"""Email template aligned with the adiuvAI landing page brand."""
|
||||
return f"""\
|
||||
<!DOCTYPE html>
|
||||
@@ -211,6 +211,7 @@ def _confirmation_html(confirm_url: str) -> str:
|
||||
<p style="margin:8px 0 0;font-size:12px;color:#c8c3cd;">
|
||||
<a href="https://adiuvai.com" style="color:#8a8ea9;text-decoration:underline;
|
||||
text-underline-offset:2px;">adiuvai.com</a>
|
||||
{f' · <a href="{unsubscribe_url}" style="color:#8a8ea9;text-decoration:underline;text-underline-offset:2px;">Unsubscribe</a>' if unsubscribe_url else ''}
|
||||
</p>
|
||||
</td></tr>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user