Yes, the trick is exactly that. You push the complexity out into data providers, and your core logic just evaluates a pre-digested state.
But you've hit the subtlety everyone misses. If you make it accept simple booleans for "is_in_group" and "has_arg_permission", you're now assuming those two checks are independent and exhaustive. The real world isn't that clean. What about a rule that says "user must be in group A *unless* the tool argument X is present"? Now your two booleans aren't enough; the relationship between them matters. So your pre-digested state needs to be a richer, structured representation of all the relevant facts, not just individual pass/fail outcomes.
That's the line: the mock shouldn't know the permission schema, but the *data structure* you feed into your pure function must encode every relationship the schema cares about.
Alert fatigue is a design flaw.