Paradaux
0

Players are able to disband firms multiple times spamming chat

An already-disbanded firm can be disbanded again, re-running the disband flow and spamming chat with the broadcast.

Technical notesFirmServiceImpl.disbandFirm has no isArchived() guard, and FirmMapper.getFirmByName/getFirmById return rows regardless of is_archived. Guard disbandFirm with an already-archived check (and surface "firm already disbanded" in FirmCommands.disband) to make disband idempotent; optionally exclude archived firms from the name/id lookups. Confirmed via code read.

Comments

tesks · Jun 4, 2026, 9:24 AM

Code contextbusiness-rian/…/services/impl/FirmServiceImpl.disbandFirm has no isArchived() guard, and FirmMapper.getFirmByName/getFirmById return rows regardless of is_archived, so /firm disband <name> can be re-run on an already-disbanded firm — re-running the archive/withdraw flow and re-broadcasting the disband message (the chat spam).

Fix: guard disbandFirm with an already-archived check (surface "firm already disbanded" in FirmCommands.disband) to make disband idempotent; optionally exclude archived firms from the name/id lookups. Confirmed via code read — dropped the Unconfirmed label.

tesks · Jun 4, 2026, 2:57 PM

Fixed on develop (business-rian @ 0c6024c).

Change — disband is now idempotent:

  • FirmServiceImpl.disbandFirm throws BadCommandException("Firm already disbanded") when firm.getArchived() is true (before any account/archive work).
  • FirmCommands.disband short-circuits with a new localized message business.firm.disband.already before the broadcast fires, so a repeat disband no longer spams chat.

Left the getFirmByName/getFirmById lookups returning archived rows (other read paths — info views, explorer — rely on that); the explicit archived guard is the surgical fix.

Added unit test disbandFirm_alreadyArchived_throws (asserts no re-archive / no account work). FirmServiceImplTest green under JDK 21.

Activity

  • ParadauxIO linked a commit — Commit 0c6024c — Make firm disband idempotent (PAR-24)Jun 7, 2026, 2:49 PM
  • ParadauxIO changed status to Status → DoneJun 7, 2026, 2:49 PM
  • ParadauxIO linked a pull request — PR #6 merged — Release: develop → mainJun 7, 2026, 2:49 PM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 7, 2026, 12:36 AM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 6, 2026, 11:49 PM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 6, 2026, 12:44 PM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 6, 2026, 11:17 AM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 6, 2026, 11:11 AM
  • ParadauxIO linked a pull request — PR #6 open — Release: develop → mainJun 5, 2026, 12:35 PM
  • tesks changed status to Status → Pending ReleaseJun 4, 2026, 2:57 PM
  • tesks commentedJun 4, 2026, 2:57 PM
  • tesks description: Description updatedJun 4, 2026, 9:59 AM
  • tesks commentedJun 4, 2026, 9:24 AM
  • tesks assigned Assigned to rianJun 4, 2026, 9:22 AM
  • tesks updated labels (Labels updated)Jun 4, 2026, 9:22 AM
  • tesks set priority to Priority → HighJun 4, 2026, 9:22 AM