# Eligibility Rules

## Overview

Eligibility Rules maintains `EligibilityRule` — the **applicability layer** (eligibility rules) declaring which population may be assigned which rule: which Worker, Position, JobProfile, or employment type may be assigned which WorkRule. It is the Workday Eligibility Rule analogue (issue #7): the policy "who is eligible for what" is data, resolved `asOf` a date, and bound entirely by stable keys rather than display names (ADR-015). The grant was narrowed to `WORK_RULE` only in #39 (the former `TIME_ENTRY_CODE` grant and its `timeEntryCodeKey` were removed); enforcement against WorkRuleAssignment is tracked in #41.

## Business Purpose

- Externalize "who may be assigned which rule" as data instead of hard-coded branches in calculation (e.g. managers exempt from overtime)
- Bind every side of the rule to stable identity/keys — workforce ids and normalized employment/work-type enums on the target side, WorkRule identity on the grant side (ADR-015, issue #14)
- Let eligibility change over time (a role becomes exempt) with full history via effective dating (ADR-013)
- Give the calculation engine a single `asOf` resolution for the assignable rule of any worker on any date

## Process Flow

```mermaid
flowchart TD
    A[Declare EligibilityRule: target -> WorkRule] --> B[Effective-dated generation stored]
    B --> C{Resolve for a worker on a date}
    C --> D[Collect eligibility generations in force for worker, position, job-profile, employment-type]
    D --> E[Assignable WorkRule determined]
    E --> F[WorkRule assignment restricted to eligible rules; enforcement tracked in #41]
    A --> G{Policy change e.g. role becomes exempt}
    G -- Yes --> H[Close current generation, insert new effective-dated generation]
```

## Scenario Patterns

- **Restrict a work rule**: declare a WorkRule assignable only to a specific population; assignment outside it is rejected
- **Managerial exemption**: an employment-type / work-type target (supervisory/managerial staff) is granted a rule set that excludes statutory overtime
- **Additive resolution**: a worker's assignable-rule set is the union of grants in force for the worker and their position/job-profile/employment-type
- **Effective-dated change**: a role becoming exempt closes the prior generation and inserts a new one on the change date
- **Future-dated eligibility**: a grant with a future `effectiveStart` does not take effect until its start date

## Test Cases

- assigning a WorkRule to a target with no in-force eligibility grant is rejected
- resolving eligibility `asOf` a date returns only generations in force on that date
- the assignable-rule set is the union across the worker's position / job-profile / employment-type grants
- a target and grant are stored by id / key / enum, never by display name
- an eligibility change closes the prior generation and inserts a new one with no range overlap
- a future-dated grant is not returned as in force before its `effectiveStart`

## Reference Links

- Data-model design research (Workday Eligibility Rule, rule externalization): https://github.com/tailor-sandbox/Omakase-ERP-attendance/issues/7
- Customization reality (eligibility as configuration, not per-customer code): https://github.com/tailor-sandbox/Omakase-ERP-attendance/issues/13
- Cautionary lesson: bind eligibility to semantic keys/enums, not display-name strings: https://github.com/tailor-sandbox/Omakase-ERP-attendance/issues/14
