# UpdateEligibilityRule

## Permission Scope

`eligibility`

## Overview

Records a change to an eligibility grant's target or grant reference — for example a role becoming exempt, or a population moving to a different work rule — as a new effective-dated generation, closing the prior one.

## Business Rules

- The change closes the current generation (`effectiveEnd` = day before the change date) and inserts a new generation effective on the change date; it never overwrites the existing record
- Generations sharing the same `versionOf` must not overlap in their effective ranges
- The target and grant on the new generation remain bound by stable id (targetType + targetId, workRuleId), never by display name
- The revised `targetId` must resolve to an existing workforce entity of its `targetType`; a well-formed but dangling id is rejected so a rule can never grant a nonexistent target
- A future-dated new generation does not take effect before its `effectiveStart`

## Process Flow

```mermaid
flowchart TD
    A[Receive rule id and revised target/grant/effectiveStart] --> B{Rule exists?}
    B -- No --> C[Reject: ELIGIBILITY_RULE_NOT_FOUND]
    B -- Yes --> D{New target/grant valid?}
    D -- No --> E[Reject: INVALID_TARGET / TARGET_NOT_FOUND / INVALID_GRANT]
    D -- Yes --> F{New effectiveStart overlaps existing generation?}
    F -- Yes --> G[Reject: EFFECTIVE_DATE_OVERLAP]
    F -- No --> H[Close current generation at effectiveStart - 1 day]
    H --> I[Insert new generation effective on effectiveStart]
```

## External Dependencies

- [time-tracking::EligibilityRule](../model/EligibilityRule.md) model — the entity this command mutates

## Error Scenarios

- **ELIGIBILITY_RULE_NOT_FOUND**: no EligibilityRule exists for the given id
- **INVALID_TARGET**: no `targetId` was supplied for the target
- **TARGET_NOT_FOUND**: the target does not resolve to an existing workforce entity
- **INVALID_GRANT**: the grant does not resolve to a valid WorkRule (a workRuleId is required)
- **EFFECTIVE_DATE_OVERLAP**: the new generation's effective range overlaps an existing generation

## Test Cases

- an eligibility change closes the prior generation and inserts a new one with no range overlap
- resolving eligibility `asOf` a date returns only the generation in force on that date
- updating a non-existent eligibility rule id is rejected
- revising the target or grant on update is rejected when unresolvable, following the same validation as creation
- revising the target to an id that does not resolve to a workforce entity is rejected
- an update whose new effective range overlaps an existing generation is rejected

