Paradaux
IssuesPAR-103Done
0

Harden LuckPerms reconciliation cron: guard empty-result mass-revocation

Found during the release audit of the explorer-RBAC stack (treasury-api-plugin reconciliation cron, in economy-explorer #8 / economy-schema V10).

Bug (high): GroupReconciliationTask.resolveMembers returns luckPerms.searchAll(node).join().keySet() unguarded. If LuckPerms is degraded (storage mid-load, transient backend error) or the node is mistyped, it resolves to zero members, so apply computes toRemove = current \ ∅ = all and deletes every synced member of the group in one tick — silently stripping that group's explorer access until the next good run.

Fix: in apply, if the resolved set is empty while the group currently has synced members, skip removals and log a warning — the safe failure mode is to briefly over-grant, never mass-revoke. Also added a re-entrancy guard (AtomicBoolean) so overlapping async ticks can't interleave DB writes.

Residual hardening (not blocking, follow-up): partial (non-empty but shrunken) LuckPerms results aren't covered by the empty-guard — a percentage floor would be more robust; and each group's add/remove set isn't wrapped in a single transaction (.join() also has no timeout). Tracked for a later pass.

SQL invariant (only source='luckperms' rows touched, no unfiltered DELETE, INSERT IGNORE can't flip a manual row's source) verified intact during the audit.

Comments

No comments yet.

Activity

  • ParadauxIO changed status to Status → DoneJun 7, 2026, 4:16 PM
  • tesks changed status to Status → Pending ReleaseJun 6, 2026, 11:31 AM
  • tesks created the issueJun 6, 2026, 11:30 AM