Логическое удаление с источником событий (возможно, с конфиденциальными данными / GDPR)

Я понимаю, что источники событий должны быть неизменяемыми и только добавляться.

Однако мне интересно, как я обрабатываю логическое удаление. Если пользователь нажимает «удалить» в пользовательском интерфейсе и ожидает окончательного удаления, должен ли я включать флаг IsDeleted в свое событие? Здесь есть другие варианты?

Изменить: вопрос представляет особый интерес, когда вокруг есть конфиденциальные данные, которые могут храниться в самом событии, и пользователь ожидает, что они будут полностью удалены из наших систем. Это может относиться к регламенту и законам GDPR ЕС.


person user3603308    schedule 24.06.2018    source источник


Ответы (4)


Вы можете опубликовать событие «удалено», которое удалит / пометит данные как удаленные в вашей базе данных для чтения, но это не жесткое удаление (которое вы указываете в своем вопросе). У вас все еще будут данные в вашем хранилище событий.

Жесткие удаления на самом деле довольно сложны при использовании источников событий. Я предполагаю, что вы работаете с данными о клиентах, полученными из событий? Обычно для этого есть несколько решений, но они не очень хороши:

  • Вы либо не передаете свои конфиденциальные данные о клиентах, а храните их отдельно и просто каким-то образом ссылаетесь на них из своего агрегата.

  • Вы либо удаляете старые события (имейте в виду, что это может сломать больше, чем вам хотелось бы, но это зависит от вашего дизайна/приложения)

  • Вы либо добавляете удаленное событие, либо изменяете существующие события, чтобы удалить конфиденциальные данные.

person Vincent Hendriks    schedule 26.06.2018
comment
Я думаю, что это очень важно в смысле конфиденциальной информации, которая случайно попала в систему. Скажем, например, что вы храните написанные человеком записи CRM, которые телефонный оператор регистрирует во время телефонного разговора с клиентом. Вы бы подумали в { "eventId": 123, "type": "annotation.added", "content": "The customer wants to know if the elephants excursion is still available." }. А что, если оператор напишет что-то вроде "The customer says that his password 'myUsualPasswordInAllSites000' does not work". [продолжение в следующем комментарии] - person Xavi Montero; 22.08.2018
comment
Двойная ошибка: клиент никогда не должен был говорить об этом. Но оператор никогда не должен был это писать. Но будьте уверены, что это ошибка, которую клиент будет винить в нашей компании, если мы ее сохраним, и злоумышленник получит доступ к данным, войдет туда, увидит простой пароль и попробует его на любой другой конфиденциальной учетной записи любой другой компании. (скажем, банковский счет) заказчика, и это работает. Дело не в том, что пользователь набрал это. Это был наш оператор. Мы должны гарантировать, что конфиденциальная информация может быть действительно удалена тем или иным способом. [продолжение в следующем комментарии] - person Xavi Montero; 22.08.2018
comment
То же самое происходит, например, если мы импортируем электронные письма в нашу систему из IMAP. Что, если мы импортируем электронное письмо, содержащее конфиденциальные данные (скажем, парень случайно написал личные вещи одному из наших представителей, но он попал на адрес электронной почты компании, а не на ее личный адрес электронной почты). [продолжение в следующем комментарии] - person Xavi Montero; 22.08.2018
comment
Я решительно поддерживаю первое из предложений Винсента: поместить конфиденциальные данные в отдельное хранилище документов, в котором хранятся данные, вычисляется для них хэш (например, sha1) и используется этот хэш в качестве идентификатора, а затем событие только указывает к данным по его идентификатору. В пределе вы можете удалить документ, но оставить событие нетронутым. Воспроизведение событий просто восстановит какие-то данные, удаленные в проекции, когда он обрабатывает событие, а данные документа отсутствуют. - person Xavi Montero; 22.08.2018
comment
Тем не менее, я бы не стал делать удаление документа простым щелчком мыши. Это должно только добавлять отметки. Это реальное удаление документа должно производиться только системными администраторами после аудита, который действительно показывает, что у нас действительно есть данные, которые мы никогда не должны были сохранять. В остальном просто добавьте события удаления и заставьте ваши перестроители адекватно обрабатывать прогнозы, удаляя строку, если нет нарушения целостности, или оставляя ее помеченной как удаленную, если вам нужны ссылки на нее. - person Xavi Montero; 22.08.2018
comment
вы также можете хранить конфиденциальные данные в виде отдельного потока событий, если вы действительно хотите вести журнал аудита, но также хотите иметь возможность удалить поток. просто используйте один и тот же идентификатор для обоих потоков. вы всегда можете удалить весь поток, но не отдельные события. - person Vincent Hendriks; 22.08.2018
comment
но это не поможет для комментариев, подобных приведенным выше. это зависит от ситуации, конечно :) - person Vincent Hendriks; 22.08.2018
comment
то, что вы предлагаете пометить для удаления, — это именно то, что я предложил здесь для нашего текущего решения. вы также можете оставить данные до определенного момента времени (gdpr), а затем удалить их навсегда - person Vincent Hendriks; 22.08.2018
comment
Хммм... звучит интересно... да, возможно, такие события, как xxxx.sensiveData.hardDeletionRequested и xxxx.sensitiveData.hardDeletionAuthorised внутри потока событий... Звучит действительно интересно, безусловно. Эти события могут нести информацию о том, кто проводит аудит и кто авторизует, человек ли это, cron или робот, и так далее... интересный подход! - person Xavi Montero; 22.08.2018

включить ли флаг IsDeleted в мое событие? Здесь есть другие варианты?

Если вы спрашиваете "Могу ли я отменить событие, установив флаг isDeleted?"; нет, обычно мы так не делаем. Вместо этого мы добавляем новое событие, которое «обратит» эффект первого. Иногда вы увидите, что это описывается как компенсирующее событие. В зрелых доменах (например, бухгалтерский учет) часто существует явный протокол для обращения событий.

person VoiceOfUnreason    schedule 24.06.2018

Обычно вы не отображаете события в своем пользовательском интерфейсе, вы отображаете свою модель чтения, которая рассчитывается на основе событий.

Например, у вас могут быть события

TASK_CREATED "один"

TASK_CREATED "два"

TASK_CREATED "три"

TASK_DELETED "два"

В коде обновления вашей модели чтения (списка задач) вы просто добавляете элементы в событие TASK_CREATED и удаляете его в событии TASK_DELETED, поэтому результирующий список будет таким:

"один"

"три"

Итак, если пользователь нажимает «удалить» в пользовательском интерфейсе, он отправляет команду DELETE_TASK агрегату, агрегат публикует событие TASK_DELETED, и это событие применяется к модели чтения (удаление элемента из списка). Теперь, когда вы запрашиваете модель чтения, из нее будет удален один элемент.

person Roman Eremin    schedule 25.06.2018

Как сказал @Vincent Hendriks: «Вы можете опубликовать событие« удалено », которое удалит / пометит данные как удаленные в вашей базе данных для чтения».

Вот очень хороший пример, демонстрирующий эту концепцию: http://next.belus.com/Demos/Events

В демо нажмите ссылку «Изменить» и нажмите кнопку «Удалить». В нижней части страницы см. событие, которое создается.

person Sandy    schedule 28.06.2018