Порядок записи DMS→DB консистентен и в основном корректен, но есть окна расхождения при сбое второй записи.
src/domain/mailboxes/service.ts:74-92 (addEmail): DMS-аккаунт создан → repo.create бросает (напр. unique-гонка) → orphan-аккаунт в DMS. Quota-путь (строки 77-84) уже делает rollback — распространить тот же rollback на insert.
src/domain/aliases/service.ts:66-70 (update): deleteAlias затем addAlias; если add падает — алиас исчез из DMS, но в DB осталась старая строка. Порядок обратный (сначала add нового, потом delete старого) или re-add старого при сбое.
src/http/routes/admin/me.ts:52-55: пароль ящика сменён, затем userService.changePassword — при сбое второго пароли почты и панели расходятся без сигнала. Минимум — обернуть ошибкой, сообщающей, какой из двух сменился (в идеале вынести в SelfServiceService/UserService метод ради атомарности).
src/domain/domains/service.ts:73-77 (delete): удаляет строку; FK-каскад (schema.ts:98-100) молча удаляет строки ящиков, но DMS-аккаунты не удаляются — мгновенное DB↔DMS расхождение, находимое только через sync. Гард: отказывать в удалении при непустом домене (409) либо явно каскадить в DMS.
Фикс
Пройтись по перечисленным местам; где возможно — rollback/компенсация, где нельзя — явный 409-гард (домен с ящиками/алиасами).
Порядок записи DMS→DB консистентен и в основном корректен, но есть окна расхождения при сбое второй записи.
src/domain/mailboxes/service.ts:74-92(addEmail): DMS-аккаунт создан →repo.createбросает (напр. unique-гонка) → orphan-аккаунт в DMS. Quota-путь (строки 77-84) уже делает rollback — распространить тот же rollback на insert.src/domain/aliases/service.ts:66-70(update):deleteAliasзатемaddAlias; если add падает — алиас исчез из DMS, но в DB осталась старая строка. Порядок обратный (сначала add нового, потом delete старого) или re-add старого при сбое.src/http/routes/admin/me.ts:52-55: пароль ящика сменён, затемuserService.changePassword— при сбое второго пароли почты и панели расходятся без сигнала. Минимум — обернуть ошибкой, сообщающей, какой из двух сменился (в идеале вынести вSelfServiceService/UserServiceметод ради атомарности).src/domain/domains/service.ts:73-77(delete): удаляет строку; FK-каскад (schema.ts:98-100) молча удаляет строки ящиков, но DMS-аккаунты не удаляются — мгновенное DB↔DMS расхождение, находимое только через sync. Гард: отказывать в удалении при непустом домене (409) либо явно каскадить в DMS.Фикс
Пройтись по перечисленным местам; где возможно — rollback/компенсация, где нельзя — явный 409-гард (домен с ящиками/алиасами).