Issue Description
In Stalwart 0.16.22, updateRules uses RegistryWrite::insert for all imported object types: SpamRule, SpamTag, SpamDnsblServer, HttpLookup, MemoryLookupKey and SpamFileExtension. PrimaryKeyConflict only increments already_exists; existing objects are not updated.
The official v3.0.0 and v3.0.1 artifacts provide a minimal example: their only difference is the DBL_SPAM score, changed from 6.5 to 4.5. No objects were added or removed. The importer therefore skips the sole change in this release.
This contradicts the documented update behavior for core rules and core DNSBL definitions, which says their contents are overwritten while the local enable setting is preserved.
Verified by source inspection and comparison of the official artifacts. No end-to-end reproduction of the unmodified native update path was performed for this report.
Expected Behavior
Updating the unmodified official ruleset from v3.0.0 to v3.0.1 should change DBL_SPAM from 6.5 to 4.5.
Upstream changes to existing official objects should be applied. For core SpamRule and SpamDnsblServer objects, local enable settings should remain preserved as documented.
Actual Behavior
The importer attempts an insertion, receives PrimaryKeyConflict for the existing DBL_SPAM tag, and counts it as already_exists without updating its score.
The code path therefore leaves the stored score at 6.5 instead of the candidate artifact’s 4.5. Reloading settings cannot apply the intended value because the stored object was never updated.
The same insert-and-skip behavior prevents changes to existing rule conditions, DNSBL definitions and HTTP lookup configurations from being applied.
Reproduction Steps
-
Import the official v3.0.0 ruleset into an instance without existing spam-filter ruleset objects:
https://github.com/stalwartlabs/spam-filter/releases/download/v3.0.0/spam-filter-rules.json.gz -
Read the SpamTag whose tag is DBL_SPAM and confirm score=6.5.
-
Set SpamSettings.spamFilterRulesUrl to:
https://github.com/stalwartlabs/spam-filter/releases/download/v3.0.1/spam-filter-rules.json.gz
Apply ReloadSettings so the importer uses the new URL. -
Run SpamFilterMaintenance with maintenanceType=“updateRules” and wait for completion. Do not delete or manually modify existing objects beforehand.
-
Read DBL_SPAM again.
Expected: score=4.5.
The source code predicts: score remains 6.5 because the existing object is skipped.
Relevant Log Output
No runtime logs are attached. The evidence is the importer’s conflict-handling code and comparison of the official v3.0.0 and v3.0.1 artifacts.
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
Additional Context
Importer:
Documented update behavior:
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on