This document is the result of thinking about it. It is different from my previous proposals and implementation.
Design Goals
Zero friction for subscribing
If we introduce a email verification step before accepting a subscription, there will be a lot fewer subscriptions. This is well-researched in the industry- any added friction will have a huge impact on "conversion rate", especially for casual readers who might want to subscribe. In comparison, a motivated publisher will probably accept a bit of friction to accomplish their goals.
Spam Avoidance
Our design must make it easy for people to stop receiving emails. This is mandated by law, but also we want to avoid giving users the impression that Seed is "spammy". So it should be possible to adjust your notification settings with some granular settings.
Synced Subscriptions
Once you subscribe on one device, the subscription prompt should go away on all devices where you have a linked identity. Notification settings should match between web and desktop for a given account. Otherwise it will be a confusing experience.
In the future, these subscriptions in the notify service can be used to define the syncing subscriptions and local app inbox.
Streamlined workflows
We should avoid unnecessary UX steps for managing subscription settings, such going round-trip from your desktop app to your email inbox, just to modify notification settings that were established from that same app.
Constraints
For the sake of simplicity, this project supports only one email address per account. In theory an advanced user will want different notifications for different email addresses. Users will be required to create more than one account in that case.
Don't worry, this project is still sufficiently complicated.
Database Schema
Account Table
AccountID (Unique)
Email (Unique)
IsValidated
UnsubscribeAllTime (optional) - set if the user has unsubscribed
Email Auth Token
Subscription Table
Subscriber - ref Account ID
Target - target account ID and path
Recursive - Boolean
SelectedEvents: Mentions, Doc, Comment, Replies
EmailValidations
Email (Unique)
RequestingAccount
Email Auth Token
Send Time
Expire Time
Authentication Methods
You can interface with the email notification server in two distinct auth modes:
Email-authenticated
In this case we know the user has access to a token that was sent to a specific email address.
This can either be a short-term token that the user has provided, that is saved in the EmailValidation table, or it can be a long-term email identification token, saved in the Account table.
Account-authenticated
The user is managing notification settings and they have proven to own the account key (or an authorized agent key).
Each request to get or edit notification settings is a signed blob which includes the notify server host, and a timestamp which the server uses to make sure this account is actually performing the intended action.
Notification Settings
The "settings" include all attributes which configure notifs, mostly the Subscriptions table which specifies what content you are subscribed to.
Workflows
New account with email
The account is created with the private key held locally. The user optionally has the opportunity to input their email.
We explain that if the email address is provided, it will be sent to our server and the user will be subscribed to mentions and replies.
If the user provides their email, it will be sent to the service at notify.seed.hyper.media in a signed message that includes the timestamp and destination host. The notify server can see with certainty that this account is trying to set up email email notifs, but the email address itself is not validated at this point.
Even with a non-validated email, the user will receive notifications for their content. This is fine as long as we offer a "one click" unsubscribe process.
The welcome server creates a new entry in the Account table, and creates a new EmailValidation entry with the same email address.
We send a welcome email that explains the new subscription. It has two buttons: "Validate Email" and "Edit Notification Settings"
The validate link includes the email validation token. When clicked, will cause the isValidated to be set to true on the Accounts table. Then the validation row is deleted.
New email for existing account
This workflow is identical to the new account with email workflow
If the email address conflicts with the email of another account
When a user subscribes to an email address that is already used by another Account row, we have special behavior.
The email field is not set for the new account row, and the previous account row is unchanged.
A new validation row is created, with the email and new account ID.
The email is sent which explains to the user: click this button and your email will be transferred from Account A to Account B.
On confirmation click, the email changes on the new account (verified=true), the email is deleted from the previous account, and the validation row is deleted.
Unsubscribe or change settings from email footer link
Every email includes a secret token which is saved in the Account table, and a "Manage Notifications / Unsubscribe" link which takes you to notify.seed.hyper.media/settings?token=123
This page uses this token to read and write notification settings.
The notification settings page has a one-click button to unsubscribe from all emails. This can only be un-done by clicking this link again- the account has no ability to undo this action.
If the email is validated, this page can edit all notification settings (subscriptions) for this account.
If this email is not validated, it will show all of the accounts who have pending EmailValidation rows for this email. (likely, there is only one). The user can choose which to validate. When the user clicks "Validate" on the account, it gets set to validated, and all pending validations for this email are deleted. Then it allows the email-authenticated user to edit subscriptions and settings for that account.
Edit Notification settings from Seed
In the desktop app and Seed web, we use account authentication to fetch and edit notification settings and subscriptions for this account.
This workflow does not allow you to validate an email address, and it does not allow you to set the UnsubscribeAllTime.
Change Account Email
If an account already has an email (validated or not), the user can still edit it from the desktop app or seed web. The previous email is deleted, along with any validations for it which match the account ID.
Now the user continues with the "New email for existing account" workflow
Stray Notes
An email re-authorization workflow
This can be implemented with a long-term token but this is a weak security stance because the user maybe forwarded their email. Or maybe they no longer have access to the account but they still have an old email. So in reality there should be two tokens, and one is short lived. If the short-term token has expired then the email should be revalidated.
"One-Click" Unsubscribe
Mandated by laws that we must have a one-click unsubscribe. But there are two interpretations of this law. Either one click from the email, or one click from the web page, which is really two clicks.
Lots of companies do this thing where it is two clicks, and so do we. Our "Manage Notification Settings" plus the button for "Unsubscribe from all emails" will accomplish this.
I think we are required to use the "unsubscribe" word in the email, when we link to the notification settings.
Self-subscribe data model?
Should an account use a row in the Subscription table to watch its own mentions and replies? Or should that be automatically inferred by the Accounts table?
At the moment I think we should not create all those extra entries in the Subscription table, which will keep our data a bit cleaner.
Email-Driven Unsub must overwrite Account settings
If the account provides an incorrect email, the email owner needs a button that says "this is not me" and will detach the email from the account. There also needs to be a flag on the server that unsubscribes the address from ALL future emails.