Skip to content

The account that publishes a ban never folds it into its own banlist (follow-up to #85) #86

Description

@derekross

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

  1. As a member with BAN, ban an account in a v2 community.
  2. Read communities.banlist from the banner's own sqlite.
  3. Join the same community as a fresh identity; read its folded banlist.
  4. The banned npub is present for the fresh identity, absent for the banner.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions