PAR-87
Investigate API abuse by a user
A user has been able to spam ingame chat with the disband notification. They claim they can still run commands related to the business, but they don't seem to function fully. Further investigation is needed.

Resources
- commitd6521f5 Fix review findings from the release audit (PAR-87)MCCitiesNetwork/Business
- commit7a95933 Stop disbanded firms from resolving on command paths (PAR-87)MCCitiesNetwork/Business
- PR · merged#6 Release: develop → mainMCCitiesNetwork/Business
Comments
tesks · Jun 5, 2026, 6:59 AM
Root cause confirmed. Two parts:
- Disband-notification spam — already fixed by PAR-24 (disband is now idempotent:
disbandFirmthrows "already disbanded" if archived). Ships with that. - "Can still run commands related to the business" —
FirmServiceImpl.getFirmByNameOrId→FirmMapper.getFirmById/getFirmByNamereturn the firm regardless ofis_archived(no archived filter), so mutating commands resolve a disbanded firm and act on it.
Fix plan: make getFirmByNameOrId active-only (return null when is_archived), so every command path rejects a disbanded firm; switch disbandFirm's "already disbanded" check to an explicit archived-inclusive lookup; keep any admin/info view path on an archived-inclusive resolver. Add a FirmServiceImplTest case (archived firm → resolver returns null) to satisfy the ≥95% coverage gate. Bounded but touches the central resolver — deserves its own focused pass, not a tail-end rush.
tesks · Jun 5, 2026, 7:42 AM
Root-caused and fixed on develop (commit 7a95933).
Cause — getFirmByNameOrId resolved firms regardless of is_archived, so after a disband every command/service path (balance, deposit, withdraw, pay, staff, roles, accounts, requests, tax …) still resolved the firm and partially acted on it. That's the "can still run commands… don't seem to function fully" report.
Fix — made getFirmByNameOrId active-only (returns null for an archived firm). Because ~60 command/service call sites funnel through this one method, that single change centrally rejects disbanded firms everywhere with a clean "not found".
Added getAnyFirmByNameOrId (archived-inclusive) for the handful of places that legitimately need defunct firms:
- public
BusinessApi.getFirm/getFirmByAccountId— consumers may display defunct firms (andgetFirmByAccountIdalready returns null for disbanded firms since thefirm_accountlink is dropped on disband); /firm info— renders the(Defunct)status;- proprietor + admin
disband— so a repeat reports "already disbanded" (idempotent) rather than "not found".
The disband-notification-spam half was already addressed by PAR-24 (Pending Release); this closes the "commands still work on a disbanded firm" half.
Tests: archived→null, active→resolves, getAny→archived; existing API delegate tests updated to the archived-inclusive read. Full suite + ≥95% coverage gate green.
Activity
- ParadauxIO linked a commit — Commit d6521f5 — Fix review findings from the release audit (PAR-87)
- ParadauxIO linked a commit — Commit 7a95933 — Stop disbanded firms from resolving on command paths (PAR-87)
- ParadauxIO changed status to Status → Done
- ParadauxIO linked a pull request — PR #6 merged — Release: develop → main
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- ParadauxIO linked a commit — Commit d6521f5 — Fix review findings from the release audit (PAR-87)
- ParadauxIO linked a pull request — PR #6 open — Release: develop → main
- tesks commented
- tesks changed status to Status → Pending Release
- ParadauxIO linked a commit — Commit 7a95933 — Stop disbanded firms from resolving on command paths (PAR-87)
- tesks commented
- tesks assigned Assigned to rian
- tesks moved to Moved to Business
- RÃan Errity moved this issue — Moved to PAR (PAR-87)
- tesks created the issue