When a firm is disbanded, its chestshops are orphaned and nobody can break the signs to remove them.
Technical notes — Breaking a firm shop sign flows ChestShop-3 SignBreak.canDestroyShop → NameManager.canUseName → AccountAccessEvent → TreasuryListener.onAccountAccess, which grants access only if businessApi.staff().hasPermissionForAccount(accountId, player, RolePermission.CHESTSHOP). A disbanded firm's account is archived and members lose their roles, so that check fails for everyone. Fix: on the destroy path, also allow removal when the firm/account is archived (fall back to the former proprietor or a ChestShop admin), or special-case disbanded-firm shops.
Code context — Breaking a firm shop sign flows ChestShop-3 SignBreak.canDestroyShop → NameManager.canUseName → AccountAccessEvent → TreasuryListener.onAccountAccess, which grants access only if businessApi.staff().hasPermissionForAccount(accountId, player, RolePermission.CHESTSHOP). When a firm is disbanded its account is archived and members lose their roles, so that check returns false for everyone — the orphaned shops can't be removed.
Fix: on the destroy path, also allow removal when the firm/account is archived (fall back to the former proprietor or a ChestShop admin), or special-case disbanded-firm shops so they can be cleaned up.
Verified state (Planned is correct — not done): no code or commit in ChestShop-3 handles removing a shop whose firm account no longer exists (disbanded). The legacy b:<FirmName> → B:<accountId> migration self-heals active firm shops, but there's no path to break/remove a shop pointing at a now-deleted firm account. Genuinely open.
Root cause (found): removal runs SignBreak.canDestroyShop(player, owner) → NameManager.canUseName(player, OTHER_NAME_DESTROY, owner). The sign owner for a firm shop is the firm account (B:<accountId>, after the legacy b:<FirmName> migration). When the firm is disbanded its account + membership rows are gone, so canUseName can't match the player as owner/member → returns false → even the original proprietor can't break the now-orphaned shop.
Fix plan (keep it in the DC integration, not upstream core — vendored fork): in the firm-account resolution path (Events/AccountQueryEvent + the DC listener that resolves B:<id> → owner/members), detect "firm account no longer exists" and treat the shop as orphaned → permit destruction by the sign placer / an op / a chestshop.admin-style perm, so orphaned firm shops are cleanable. Confirm whether the owner→member resolution flows through AccountQueryEvent or a NameManager hook before patching, and add a test in the DC listener. Files: Listeners/Block/Break/SignBreak.java, Events/AccountQueryEvent.java, the DC firm-resolution listener, Database/Migrations.java.
Implemented (compiles, BUILD SUCCESS) — pending a branch decision.
Fix in TreasuryListener.onAccountAccess (the DC integration layer, not upstream core): when the Business plugin is present and the player isn't firm staff, also grant access if businessApi.firms().getFirmByAccountId(accountId) == null — i.e. no live firm owns the account. Disband archives the account and removes its firm_account link (FirmServiceImpl.disbandFirm), so getFirmByAccountId returns null only for a genuinely orphaned (disbanded-firm) account. This lets players remove the abandoned shop instead of it being stuck.
Trade-off worth noting: this grants access (not just destroy) to orphaned shops, so anyone can break/claim an abandoned firm shop. Since the firm is gone and the account archived (can't transact), that's reasonable cleanup, but flag if you want it scoped to break-only.
Blocked on: where to land it. ChestShop-3 is the vendored fork using master (not develop), and is currently on WIP branch feat/block-free-shops. The change shouldn't go on that unrelated WIP branch — needs to land on master (per rule 1, not auto-switching).
Non existent shop holders = sign kil?