Custom password rules: core logic + unit tests