feat(suppression): список подавления + per-key send-политика#56
Merged
Conversation
Don't deliver to addresses that hard-bounced or complained. Suppressed recipients block POST /send (422) unless the API key is exempt. - schema: suppressions table (address unique, reason, source, note) + api_keys.suppression_exempt (per-key send policy) + migration 0018 - domain/suppressions: repository (upsert-by-address, findSuppressed) + service (add/remove/filterSuppressed/addFromBounce, address normalizing) - send pipeline: POST /send rejects suppressed recipients with 422 (listing them) unless req.apiKey.suppressionExempt - auto-suppress: BounceService adds hard-bounce recipients to the list (wires #21 → #24); soft bounces are not suppressed - api keys: suppressionExempt at creation + PATCH /admin/api/api-keys/:id toggle; exposed in ApiKeyDTO + UI (column + toggle) - routes: /admin/api/suppressions (list/add/delete), admin-scoped - UI: Suppressions page (en/ru i18n) + nav; MCP: list/add/remove_suppression - tests: suppression integration (CRUD, send blocking incl. multi-recipient, exempt bypass, auto-suppress from hard bounce, per-key PATCH) Closes #24 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что это
Список подавления получателей + per-key send-политика (закрывает #24). Не доставляем на адреса, которые жёстко баунснули или пожаловались. Отправка на подавлённый адрес блокируется на
POST /send(422), если ключ не помечен exempt.Естественно продолжает #21: свежие bounce-данные автоматически наполняют список.
Surfaces: REST API + dashboard + MCP.
Как работает
suppressions(address уникальный, reason: hard_bounce/complaint/manual/unsubscribe, source, note). CRUD на/admin/api/suppressions(admin).POST /send— если любой получатель в списке → 422 со списком suppressed (не доставляем частично); проверка пропускается, если у ключаsuppressionExempt.BounceServiceна жёсткий возврат добавляет получателя в список (reasonhard_bounce). Мягкие возвраты не подавляются.suppression_exemptна api_keys — задаётся при создании и переключается черезPATCH /admin/api/api-keys/:id. Видно в UI (колонка + тумблер).Изменения
suppressions+api_keys.suppression_exempt+ миграция0018.domain/suppressions: repository (upsert по адресу, findSuppressed) + service (add/remove/filterSuppressed/addFromBounce, нормализация адресов) + serialize;SuppressionDTO./send.suppressionExemptв create/serialize/DTO + PATCH-тумблер + UI.admin/suppressions.ts.list_suppressions/add_suppression/remove_suppression.Проверки
typecheck·lint·format:check·vitest(518 ✓) ·ui typecheck/build·mcp typecheck/build— всё зелёное. Паритет ключей en/ru новых неймспейсов проверен.Closes #24
🤖 Generated with Claude Code