Перейти к содержанию

Модель добровольной подписки

Подписка на обновления учебного сайта начинается с обещания, а не с таблицы адресов. Человек должен понимать, что получит, как часто и каким способом сможет прекратить сообщения. В этом уроке создадим модель SUB-01 для ProfessorWeb: добровольная подписка на новые уроки с отдельным состоянием заявки. Результат — карта допустимых переходов, по которой можно решать, кому разрешено готовить письмо.

Вся серия работает локально. Контакты, события и показатели синтетические, домен professorweb.example вымышленный. Никаких почтовых аккаунтов, реальных подписок и отправок нет. В архиве серии, папка lesson-01, находятся редакторские документы. Это модель процесса, не установленный сервис рассылки.

Обещание и назначение

Выберем обещание: «Подборка новых учебных материалов по выбранным темам, не чаще одного раза в неделю». Частота — проектное решение, а не универсальная норма рассылок. Внутри подписки будут темы веб-разработки и SEO. Получение ответа на технический вопрос не означает согласия на эту подборку. Посетитель, написавший редактору, и подписчик имеют разные основания для сообщений.

Назначение данных тоже ограничено. Для модели нужен адрес, выбранные темы, состояние и запись о принятом обещании. Имя, возраст и телефон не обязательны для доставки подборки. Мы принимаем минимизацию, отдельное согласие и простую отписку как требования проекта. Они не заменяют проверки применимого законодательства, территории и условий будущего провайдера; правовые правила нельзя считать одинаковыми для всех сайтов.

Согласие относится к конкретной версии обещания PROMISE-v1. Если редакция позже решит отправлять рекламные предложения вместо уроков, старое действие нельзя автоматически трактовать как согласие на новую цель. В модели такая смена требует отдельного решения и нового подтверждённого выбора. Версия помогает восстановить, какие условия были показаны человеку, а не просто хранить флаг без содержания.

Состояния подписки

Введём состояния pending, confirmed, expired и unsubscribed. Заявка pending означает, что адрес введён, но ещё не подтверждён в нашем процессе. confirmed означает завершённый учебный шаг подтверждения и действующее согласие. expired — срок заявки истёк. unsubscribed — дальнейшая рассылка остановлена. Наличие строки контакта не заменяет эти состояния.

Состояние Подборка уроков Следующее допустимое действие
pending Не включаем Подтверждение по запросу
confirmed Возможна при остальных условиях Проверка тем и запретов
expired Не включаем Новая добровольная заявка
unsubscribed Не включаем Новый явный выбор при возвращении

Даже confirmed не означает безусловную отправку. Может существовать запрет из-за постоянной ошибки адреса, жалобы или административной остановки кампании. Поэтому допустимость вычисляется по нескольким условиям: состояние подтверждено, цель согласована, тема подходит, запрет отсутствует, частота не нарушена. Эти условия будут развиваться в следующих уроках. Сейчас важно не свести всё к одной колонке «есть email».

Отдельно сохраняем состояние коммуникации. Подписка может быть активной, а конкретное письмо ещё не подготовлено. Письмо может быть подготовлено, но подписка уже остановлена. Если смешать эти объекты, повторная задача отправки может проигнорировать новый запрет. В нашей лаборатории реальной отправки нет, но модель должна заранее показывать, где проверяется актуальное право действия.

Контакт и событие

Событие описывает действие: заявка, подтверждение или отписка. Текущее состояние — результат обработки допустимой последовательности. Например, после заявки и подтверждения контакт становится confirmed. Если затем произошла отписка, поздний повтор старого подтверждения не должен вернуть его в список. Такой порядок защищает явный выбор читателя от устаревших операций.

Для учебных событий введём scenario_at, а не настоящий момент получения. Все значения имеют происхождение synthetic. В первом уроке контактов ещё нет: мы задаём правило, по которому они появятся. Отсутствие фактических событий позволяет подготовить структуру без выдуманного отчёта о регистрации посетителей ProfessorWeb. Следующая глава добавит форму и одну модель заявки.

Не покупаем и не импортируем случайный список адресов. В проектной модели основание должно быть восстановимо: версия обещания, способ выбора и подтверждение. Даже если адрес публично встречается в интернете, из этого не следует согласие на нашу подборку. Это правило выбранного процесса. Подробные правовые условия внешнего использования рассматриваются отдельно, а здесь реальных адресов вообще нет.

Идентификатор подписки отличается от адреса. Назначим формат R001, который не содержит персональных сведений. Адрес может измениться, а история выбора должна оставаться связанной с сущностью. При смене адреса потребуется новое подтверждение владения в рамках нашей модели. Не переносим старый подтверждённый статус на произвольную новую строку только потому, что ID прежний.

Проверка допустимости

Рассмотрим мысленный набор: один подтверждённый читатель, один ожидающий подтверждения и один отписавшийся. Только первый становится кандидатом подборки, но ещё проходит проверку темы и запрета. Правильный ожидаемый результат — не три письма, а один кандидат. Мы не отправляем даже его: задача урока состоит в объяснении границы между записью в базе и допустимой коммуникацией.

В artifact.md хранится обещание и карта переходов. after.json добавляет SUB-01, цель lesson_updates, версию условий и правило допустимости. example_execution остаётся not_run, external_actions — ложным. Это состояние редакционного проекта, а не выполненная подписка или готовая инфраструктура почты.

Проверьте модель на позднем событии. Система получила подтверждение, затем остановку и затем повтор старого подтверждения. Если просто выбирать последнее по времени получения, читатель снова станет активным ошибочно. В нашем процессе повтор связан с прежним запросом и не меняет более новое явное прекращение. Для будущей реализации потребуется хранить связь и порядок допустимых действий, а не только последний HTTP-запрос. Эта граница особенно важна при очередях и повторных уведомлениях провайдера. Учебная карта показывает ожидаемое правило, но не доказывает техническую защиту от гонки. Пока готова предметная модель, которую затем можно передать разработчику вместе с изменённым сценарием и критерием результата.

Попробуйте изменить частоту с еженедельной на ежемесячную. Это может быть предпочтением читателя при том же назначении. А смена темы на рекламные предложения меняет обещание и требует отдельного решения. Различайте эти изменения в модели. Тогда будущая форма будет объяснять действие человеку, а система не станет трактовать любое обращение как разрешение рассылать всё содержание проекта.