Set up a custom policy rule for your tenant
Policy Rules let your tenant override attendance timing, pay eligibility and work-arrangement defaults without a code change. Rules are created in a modal with structured per-type forms, can be filtered by job level or department, and leave an audit trail you can diff version by version.
Available on Enterprise
Where to find it
Go to Settings → Policies → Policy Rules. The list groups your rules by category — Attendance Timing, Attendance Windows, Pay Eligibility, Work Arrangement, Other — and shows the match summary and status at a glance.
Create a rule
Select New rule. The modal walks top-to-bottom:
- Policy Type. The picker groups known types by category. Pick one and the editor below reshapes itself for that type's value — a number input for Grace Period, a time picker for Half-Day Late Cutoff, a rounding-method dropdown for Tardiness Rounding, a bespoke object editor for the Minimum Hours Deduction Waiver, and so on. Picking an unknown type falls back to a raw JSON textarea.
- Rule Name. This appears on the list and in the audit trail. Describe who the rule covers, not just the policy type.
- Priority. Default
100. Higher runs first when multiple rules of the same type match. - Description. Optional — a sentence to say why this rule exists so the next admin does not undo it by accident.
- Rule Value. Fill the per-type form. The form writes the correct JSON into the hidden backing field.
- Match Criteria. Add rows that scope the rule to a subset of employees. The engine ANDs the rows — an employee must satisfy every row for the rule to match.
- Effective window. Optional end date for a rule that should expire on a specific day. Leave empty for an open-ended rule.
- Active immediately. Keep ticked unless you want to stage the rule and switch it on later from the list.
Select Save rule. The engine's cache for that policy type invalidates automatically — new attendance or payroll calculations pick up the rule within five minutes without a restart.
Common match criteria shapes
| Rule covers | Match Criteria |
|---|---|
| Every employee | empty |
| All supervisors | Job Level = SUPV |
| One named policy group | Policy Group = Night shift |
| A specific group of people | Employee IDs = guid-1, guid-2, guid-3 |
| One department's rank-and-file | Department = <guid> and Job Level = RF |
Match keys are compared case-insensitively, so SUPV and supv behave the same.
Edit, pause and delete
- Edit. Row pencil icon re-opens the modal with the saved values. Script rules open the dedicated editor instead (so Roslyn validation keeps working).
- Pause. Row Active / Paused button is an inline toggle. Pausing keeps the rule and its history but stops it from matching. Pausing invalidates the cache the same way saving does.
- Delete. Row trash icon removes the rule. The history drawer still works for the audit trail; the row's snapshots survive after the live rule is gone.
History and diff
The clock-arrow icon on each row opens a drawer showing every historical version of the rule, newest first. Diff mode (default) highlights only the fields that changed vs the previous version — ignoring noisy audit fields like UpdatedAt and UpdatedBy. Snapshot mode shows the full version if you want to copy it elsewhere. The drawer is available to every tier, not just Enterprise, so Essential and Pro admins can audit what changed on their rules.
Simulate a rule before you ship it
The flask icon in a row opens the Policy Simulator with the policy type pre-focused. Build a scenario — pick an employee, set a date and attendance, hit Run — and the simulator shows which rules fired and what each returned. Use this before enabling a rule you are nervous about.
Related
Questions people ask
What can a policy rule change?
Attendance timing (grace period, tardiness and undertime rounding, half-day cutoff, minimum-hours waiver), attendance windows (break deduction, night differential, premium zone), pay eligibility (holiday pay, overtime, night differential by rank) and work-from-home eligibility. Each policy type has its own structured editor.
What's the difference between a JSON rule and a Script rule?
JSON rules are a value returned to the engine — a number, a time, a toggle or an object. The admin UI generates them from the per-type form so you never see the JSON. Script rules are C# compiled by Roslyn — use them when a decision depends on multiple inputs the structured form does not cover. Script rules go through the full editor at Settings → Policies → Policy Rules → Edit, with syntax highlighting and bracket matching.
How do I target a subset of employees?
Open the Match Criteria builder in the rule modal. Add rows for Job Level, Employee Type, Policy Group, Department, Position, Payroll Group, or a comma-separated list of Employee IDs. The engine matches when every row's value fits the employee's contract. Leave empty to match everyone.
What does Priority mean?
Higher runs first. When multiple rules of the same policy type match, the engine takes the value from the highest-priority rule and stops. Priority 100 is a safe default. Reserve 1000 and above for emergency overrides.
Where do I see what changed?
Each row has a History button that opens a drawer showing every version of the rule, newest first. The drawer defaults to Diff mode — only the fields that changed vs the previous version — with a toggle for the full Snapshot. Insert entries render as 'Initial version' with the full snapshot.
Can I test a rule before it goes live?
Yes. Each row has a flask button that opens the Policy Simulator with the policy type pre-focused. Run a payroll or timekeeping scenario; the audit output names which rule fired for each policy type and what it returned.
What tier do I need?
Policy Rules are an Enterprise feature for creating and editing. Essential and Pro tenants can still see existing rules (read-only) and open the history drawer.