Follow-up to #85. Bans now do accumulate on the wire — every other member folds them correctly — but the account that publishes a ban never folds it into its own communities.banlist. Its banlist_at advances in lockstep with everyone else's, so the version counter looks healthy while the content silently diverges by exactly the set of bans that client published.
A restart plus a full sync_communities() does not heal it.
Environment
vector-core 0.8.0 / vector_sdk 0.9.0 (5a54c98, master 2026-08-31). Concord v2 community (protocol = 2), moderated by a headless bot holding KICK + BAN + MANAGE_MESSAGES.
Evidence
Community ebfc92cee6a665c7e849160f64aab19a5c9ca970be34a4f9b0491e09861675aa, banning client npub1f40xprd66p6j4gc6s3gz73sy7h5a26xks8ul7we0r0uxzpcxjgmqfkww6j.
| moment |
banning client |
a fresh member folding the same plane |
| before |
92 entries @ banlist_at 8 |
— |
| after 2 bans |
92 @ 10 |
94 @ 10 |
| after 1 more |
92 @ 11 |
95 @ 11 |
| after restart + full sync |
92 @ 11 |
— |
| after ~30 more bans |
92 @ 34 |
128 @ 34 |
Same community, same banlist_at, 36 entries apart. The missing entries are exactly the accounts this client banned. Every ban() returned Ok(()).
The "fresh member" column is an ordinary throwaway identity that joined via a public invite link and folded from scratch, read with vector_core::db::community::get_community_banlist. The banning client's column is the same field straight out of its sqlite.
Repro
- As a member with
BAN, ban an account in a v2 community.
- Read
communities.banlist from the banner's own sqlite.
- Join the same community as a fresh identity; read its folded banlist.
- The banned npub is present for the fresh identity, absent for the banner.
- Restart the banner and
sync_communities(); it stays absent.
Why it matters
Enforcement is fine — this is not #85 reopening. But any moderation UI or bot reading its local banlist under-reports by exactly the bans it placed itself, and anything that ever rebuilds an edition from that column would be working from a base missing them. Our bot's !automod status and our test harness's ground-truth check both read as "0 of 34 banned this run are on the banlist" while all 34 were live for every member.
Guess at the cause
4a4cb433 made set_banlist echo the published list into the local cache immediately, which is the mechanism that should cover this. Either that echo is not reached on this path, or a later fold overwrites the echoed value with a base predating the ban. The version advancing while the content does not is more consistent with the second.
Found while building an end-to-end spam-simulation harness against a live community; happy to run further diagnostics on request.
Follow-up to #85. Bans now do accumulate on the wire — every other member folds them correctly — but the account that publishes a ban never folds it into its own
communities.banlist. Itsbanlist_atadvances in lockstep with everyone else's, so the version counter looks healthy while the content silently diverges by exactly the set of bans that client published.A restart plus a full
sync_communities()does not heal it.Environment
vector-core0.8.0 /vector_sdk0.9.0 (5a54c98, master 2026-08-31). Concord v2 community (protocol = 2), moderated by a headless bot holding KICK + BAN + MANAGE_MESSAGES.Evidence
Community
ebfc92cee6a665c7e849160f64aab19a5c9ca970be34a4f9b0491e09861675aa, banning clientnpub1f40xprd66p6j4gc6s3gz73sy7h5a26xks8ul7we0r0uxzpcxjgmqfkww6j.banlist_at8Same community, same
banlist_at, 36 entries apart. The missing entries are exactly the accounts this client banned. Everyban()returnedOk(()).The "fresh member" column is an ordinary throwaway identity that joined via a public invite link and folded from scratch, read with
vector_core::db::community::get_community_banlist. The banning client's column is the same field straight out of its sqlite.Repro
BAN, ban an account in a v2 community.communities.banlistfrom the banner's own sqlite.sync_communities(); it stays absent.Why it matters
Enforcement is fine — this is not #85 reopening. But any moderation UI or bot reading its local banlist under-reports by exactly the bans it placed itself, and anything that ever rebuilds an edition from that column would be working from a base missing them. Our bot's
!automod statusand our test harness's ground-truth check both read as "0 of 34 banned this run are on the banlist" while all 34 were live for every member.Guess at the cause
4a4cb433madeset_banlistecho the published list into the local cache immediately, which is the mechanism that should cover this. Either that echo is not reached on this path, or a later fold overwrites the echoed value with a base predating the ban. The version advancing while the content does not is more consistent with the second.Found while building an end-to-end spam-simulation harness against a live community; happy to run further diagnostics on request.