Stops an active duplication defect. Ships independently of everything else.
Every engine independently classifies the same message as new (existing_message_ids is per-engine), and pending_remote_mutations has no uniqueness constraint. State-mutating actions converge — ten MOVEs produce one net effect. FORWARD and CALL WEBHOOK do not. Ten engines send ten forwards and ten signed webhook POSTs per matched message; an on-call engineer is paged ten times per alert.
generate_rule_id uses OsRng, so the "same" rule has a different id on every engine and no receiver can dedup from rule identity even in principle.
Scope
Per-account filters_enabled, default off — exactly one engine owns filter execution per account.
Make generate_rule_id a content hash of normalized NSQL.
Send Idempotency-Key: hash(rule_key, message_key) on webhooks and a deterministic dedup header on forwards, so receivers can dedup what we cannot make once-only.
Document the semantics: filter execution is at-least-once per engine; MOVE/COPY/FLAG/MARK READ converge under it, FORWARD/CALL WEBHOOK/DELETE do not.
Note
Default-off is a production behavior change — filters stop running until explicitly enabled. That is deliberate: it converts a silent duplication bug into an explicit, documented limitation.
A server-hosted claim (+FLAGS.SILENT (UNCHANGEDSINCE n) (\$NuncioFiltered)) is the eventual answer where CONDSTORE and custom keywords exist; it depends on the conditional-mutation work and is tracked separately.
**Stops an active duplication defect. Ships independently of everything else.**
Every engine independently classifies the same message as new (`existing_message_ids` is per-engine), and `pending_remote_mutations` has no uniqueness constraint. State-mutating actions converge — ten `MOVE`s produce one net effect. **`FORWARD` and `CALL WEBHOOK` do not.** Ten engines send ten forwards and ten signed webhook POSTs per matched message; an on-call engineer is paged ten times per alert.
`generate_rule_id` uses `OsRng`, so the "same" rule has a different id on every engine and no receiver can dedup from rule identity even in principle.
### Scope
- Per-account `filters_enabled`, **default off** — exactly one engine owns filter execution per account.
- Make `generate_rule_id` a content hash of normalized NSQL.
- Send `Idempotency-Key: hash(rule_key, message_key)` on webhooks and a deterministic dedup header on forwards, so receivers *can* dedup what we cannot make once-only.
- Document the semantics: filter execution is at-least-once per engine; MOVE/COPY/FLAG/MARK READ converge under it, FORWARD/CALL WEBHOOK/DELETE do not.
### Note
Default-off is a **production behavior change** — filters stop running until explicitly enabled. That is deliberate: it converts a silent duplication bug into an explicit, documented limitation.
A server-hosted claim (`+FLAGS.SILENT (UNCHANGEDSINCE n) (\$NuncioFiltered)`) is the eventual answer where CONDSTORE and custom keywords exist; it depends on the conditional-mutation work and is tracked separately.
Design: [ADR 0002](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/adr/0002-multi-engine-sync-model.md) · [review evidence](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/reviews/2026-08-10-multi-engine-design-review.md) (PR #385)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Stops an active duplication defect. Ships independently of everything else.
Every engine independently classifies the same message as new (
existing_message_idsis per-engine), andpending_remote_mutationshas no uniqueness constraint. State-mutating actions converge — tenMOVEs produce one net effect.FORWARDandCALL WEBHOOKdo not. Ten engines send ten forwards and ten signed webhook POSTs per matched message; an on-call engineer is paged ten times per alert.generate_rule_idusesOsRng, so the "same" rule has a different id on every engine and no receiver can dedup from rule identity even in principle.Scope
filters_enabled, default off — exactly one engine owns filter execution per account.generate_rule_ida content hash of normalized NSQL.Idempotency-Key: hash(rule_key, message_key)on webhooks and a deterministic dedup header on forwards, so receivers can dedup what we cannot make once-only.Note
Default-off is a production behavior change — filters stop running until explicitly enabled. That is deliberate: it converts a silent duplication bug into an explicit, documented limitation.
A server-hosted claim (
+FLAGS.SILENT (UNCHANGEDSINCE n) (\$NuncioFiltered)) is the eventual answer where CONDSTORE and custom keywords exist; it depends on the conditional-mutation work and is tracked separately.Design: ADR 0002 · review evidence (PR #385)