Paradaux

PAR-315

0

adminSetProprietor strands the firm's treasury account (PAR-141 sibling: admin-override path + atomicity)

Pending ReleaseHighUnassignedBusinessBug

Problem

Sibling to PAR-141, which reconciled Treasury access on the player transfer path (completeTransferProprietorship) and role-permission edits — but missed the admin-override path.

/firm admin set proprietor <firm> <player>FirmServiceImpl.adminSetProprietorupdateProprietor(...) flips firm.proprietor_uuid_bin only. It never calls reassignAccountsToNewProprietor, never touches Treasury members/authorizers, and writes no firm_transfer_requests row. Result is identical to the PAR-141 bug: the new proprietor is locked out of the firm's corporate account ("you're not an authorizer"), and the previous owner keeps owner-level access.

Evidence (prod, s80037)

3 active firms in this exact state, all with proprietor ≠ account owner, no transfer row, and firm.updated_at == firm.created_at (see note below):

  • GoldmanCapitalBank (firm 3113) — proprietor Planke32, account 117461 owned by Kvalej
  • InnerBanking (firm 3122) — proprietor Planke32, account 117561 owned by _zuq
  • ElytraPayments (firm 3144) — proprietor Planke32, account 117647 owned by poktizoc

(Separately, ~13 firms are stranded via the transfer path because PAR-141 is Pending Release / not yet deployed to this server — those resolve on deploy + the one-time backfill.)

Note — updated_at is not a reliable audit signal

FirmMapper.updateFirm writes updated_at = updated_at, which suppresses the ON UPDATE CURRENT_TIMESTAMP bump, so updated_at stays equal to created_at for a firm's whole life regardless of edits. Flagging separately; not changed here.

Fix (this change, on develop)

  • FirmServiceImpl.adminSetProprietor: now mirrors the transfer-accept flow — resign the new proprietor if they're a current employee, updateProprietor, then reassignAccountsToNewProprietor(firmId, newProprietor). Wrapped in @Transactional (lazy Provider<FirmAccountService> to break the DI cycle).
  • FirmRequestServiceImpl.completeTransferProprietorship: added @Transactional so a reassignment failure rolls back the proprietor change instead of stranding the account (hardens PAR-141 against partial failure).
  • Tests: adminSetProprietor now asserts the account reassignment and covers the resign-when-employee branch. :business:build green incl. the ≥95% coverage gate.

Remediation (data)

One-time SQL backfill reassigns the stranded accounts to their current proprietor (owner + member + authorizer), revoking the previous owner where they're not a current employee. Script prepared (ops/backfill-firm-transfer-accounts.sql) for the 13 transfer-path firms; the 3 admin-path firms above need owner confirmation first (unclear whether Planke32 or the account-owner is the intended owner).

Related

  • PAR-141 (transfer + role-permission reconciliation; Pending Release)
  • PAR-140 (TreasuryApi.reassignOwner)

Resources

Comments

No comments yet.

Activity

  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a pull request — PR #2 open — Last major release
  • ParadauxIO linked a commit — Commit da550d3 — Consolidate firm-account backfill to the re-runnable script (PAR-315)
  • ParadauxIO linked a commit — Commit 87d248d — Audit the /firm admin set proprietor override (PAR-315)
  • ParadauxIO linked a commit — Commit ac6baf5 — Stop freezing firm.updated_at on every firm edit (PAR-315)
  • ParadauxIO linked a commit — Commit a0c4985 — Reassign firm accounts on admin proprietor change; make proprietor-change paths atomic (PAR-315)
  • tesks changed status to Status → Pending Release
  • tesks created the issue