Alternate Account Finder
A moderation plugin that keeps a permanent per-account login history keyed by encrypted IP address, and reports accounts that share one.
Two accounts that have connected from the same IP address are probably one person. Alternate Account Finder acts on that inference: it accumulates a login history per account and surfaces accounts whose histories overlap.
What is stored
The plugin keeps one row per (address, account) pair — the address, the player's UUID, a login counter, and the first and last login timestamps for that pair. This is not a last-known-IP field: every distinct address an account has ever connected from keeps its own row, and a repeat login from a known address increments that row's counter and refreshes its last_login.
Nothing removes those rows. The repository offers reads and an upsert and no delete; there is no retention window, purge command, or expiry setting anywhere in the plugin. Login history therefore lives as long as the database does. No comment, migration note, or document in the repository explains that choice, so the reason is not recorded.
Addresses are not stored in plaintext. They are AES-encrypted under a 256-bit key kept in the plugin's data folder, in ECB mode with no IV — deliberately, and the class says why: the lookups are equality comparisons on the stored value, so the ciphertext has to be deterministic. The same comment names the cost, that ECB leaks the pattern of repeated addresses, and scopes the class to this use only. Losing the key makes the history undecryptable, which the plugin warns about loudly on startup.
Finding alts
A query self-joins the table against itself on equal stored addresses and returns the distinct other UUIDs. Because the comparison is on ciphertext and the encryption is deterministic, the join works without decrypting anything. It is a single hop: accounts that share an address directly, not alts-of-alts.
Detection runs on join. The address is read on the main thread — the comment cites issue #65, where it could be null by the time an async task ran — and the write happens off-thread, the same split described in Main Thread Safety. A notification fires only on an account's first login from a given address, so regulars do not re-alert.
Related
Storage is the jOOQ Persistence stack the community uses generally, behind a Repository Pattern boundary. Notifications go through the same optional backend selection as Notification, preferring Mailboxes when installed.