> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/lifecycle/birthright-access.md).

# Grant birthright access

Grant baseline access from identity attributes with no request, worked twice end to end, with the four mechanisms that do it and the removal behaviour of each.

## What this is, and when you need it

Birthright access is access granted because of who someone is, with no request. Four mechanisms express "everyone like this gets that", they are not interchangeable, and removal behaves differently in all four. This page works two of them end to end and then compares all four. Read [Change configuration safely](/administration-guide/start/change-safely.md) first: every mechanism here is population-scale.

## At a glance

|                          |                                                                                                                                       |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | A live rule granting one role to everyone who qualifies, tagged `BUSINESS_RULE_ASSIGNMENT`, swept once, with removal armed separately |
| **Where**                | `/webconsole/br` — **Access Control → Business Rules**                                                                                |
| **You need first**       | The role, proven to provision by hand; the attribute's stored **ID**; one disposable user                                             |
| **Takes**                | An hour to build and pin; the sweep is one provisioning save per affected user                                                        |
| **Reversible**           | Partly — the rule is, its grants are not. A no-match sweep cannot be undone                                                           |

## Before you begin

* **The role or group, already proven.** Grant it by hand to one disposable user and confirm the account appears in the target *before any rule exists*.
* **The authoritative attribute's stored ID.** Several condition attributes compare an **ID**, not the display value — the shipped employee type displayed as **PERMANENT FULL TIME** stores `PERM FULL TIME`. See [What a condition can test](/administration-guide/access/business-rules/business-rule-reference.md#what-a-condition-can-test).
* **One disposable user whose Employee ID you know.** Both examples pin the live rule to that one person.
* **The decision that this rule is the entitlement's only source.** Never express one grant through two mechanisms: removal through one leaves the other asserting it, and the next save re-provisions.

{% hint style="warning" %}
**Nothing sweeps the population on a schedule.** `PERFORM_BR_REPROVISION`, cron `0 0 0 * * ?`, ships **disabled** — enabled in 4.2.1.0, switched off in 4.2.1.5. A new rule reaches joiners and anyone who is saved straight away, and **nobody else** until a human runs the sweep. Read its **Is Active** state and last execution time under **Administration → Batch Tasks** before you plan anything.
{% endhint %}

## Worked example 1: one attribute, one role

*Every sales representative gets the CRM, on day one, without a request, and loses it when they stop being one.* One authoritative attribute, one business role: the shape most birthright requirements actually have.

|                 |                                                                                                                                                    |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Objects**     | The role `CRM User`; action groups `CRM User grant` and `CRM User revoke`; the rule `Birthright: CRM for sales reps`                               |
| **Condition**   | One **Expression**: **Job code** *Equals* `SALES REP`                                                                                              |
| **On match**    | `CRM User grant`: one **Add user to role** action, value = the `CRM User` role ID                                                                  |
| **On no match** | `CRM User revoke`: one **Remove user from role** action, same role ID                                                                              |
| **Evidence**    | The role tagged `BUSINESS_RULE_ASSIGNMENT`; `BUSINESS_RULE_EXPLANATION` on the provisioning audit event; `BUSINESS_RULE_RECALCULATE` for the sweep |

`SALES REP` is one of the job codes OpenIAM ships, alongside `MANAGER`, `SECURITY MANAGER` and `SERVICE REP`; most deployments replace them with their own. What the picker stores is the job code's **ID**, which is not always what the list displays — verify by opening a known sales rep and reading the value off their record.

{% stepper %}
{% step %}

### Build the role and prove it works before any rule exists

Create `CRM User`, entitle it to the CRM resource, and grant it **by hand** to one disposable user. Confirm the account appears in the CRM. Remove it again and confirm the account is disabled or deleted, whichever your `ON_DELETE` setting produces.

Do this first, always. If the role does not provision correctly, a birthright rule turns one broken grant into a population of them, and the rule will be blamed.
{% endstep %}

{% step %}

### Create the grant action group

**Access Control → Business Rules → Action groups → New action group**. Name `CRM User grant`, type `PROVISIONING`, **Active** ticked. One action: **Add user to role**, value = the role ID. Save; audit records `BUSINESS_RULE_TARGET_SAVE` and `BUSINESS_RULE_ACTION_SAVE`.

Create only this one for now. A no-match action group is not a per-user setting — it runs for every user in the system who does not match, from the moment the rule is live.
{% endstep %}

{% step %}

### Create the rule, pinned to one user, saved Inactive

**Rules → New rule**. **Operation** *All operations - including both user creation and updating* so transfers are caught as well as joiners. Condition: a **Group 'AND'** with two **Expression** children — **Job code** *Equals* `SALES REP`, and **Employee ID** *Equals* the employee ID of your test user.

That second expression is a temporary pin: while it is there, nobody else in the system can satisfy the condition. Set **Apply selected action group when conditions match** to `CRM User grant`, leave **Apply selected action group when conditions DO NOT match** empty, **Status** Inactive, save.

A rule created as Inactive is stored `INACTIVE` and is evaluated by nothing at all.
{% endstep %}

{% step %}

### Test on the one pinned user

Set the rule's **Status** to Active and save. It is stored as *Pending modifications*, which is what the Status column will read from now on and is normal. Now save the pinned user, and check three things:

1. The role is on the user, tagged `BUSINESS_RULE_ASSIGNMENT` — that tag is how you tell a rule's grant from a request's or an administrator's.
2. The provisioning audit event carries `BUSINESS_RULE_EXPLANATION`, containing `JOB_CODE_ID: 'SALES REP' EQUALS 'SALES REP' == true.` and *"The ADD\_ROLE action has been performed with the following results: ADD with Id=…"*.
3. The account exists in the CRM. Check the connector reply, not just the OpenIAM screen.

Then save the same user again: the action should report *"Action skipped for Id=… as user is already entitled to this entity"*. Then change their job code and save: the explanation should read `== false.`, and the role should **stay**, because nothing is yet configured to remove it.
{% endstep %}

{% step %}

### Remove the pin, preview, and sweep

Delete the **Employee ID** expression and save with Status Active. The rule now applies to real sales reps the next time each of them is saved — and to nobody else until you sweep.

**Out of sync users → Preview impacted users**, then compare the count with the number of sales reps you expect. When it matches, **Provision impacted users**. Every affected user goes through a real provisioning save; expect one CRM account creation per user and plan the load. The rule then settles to **Active**.
{% endstep %}

{% step %}

### Arm the removal, as a separate decision

Only now create `CRM User revoke` with a single **Remove user from role** action for the same role ID, and attach it as the no-match action group.

{% hint style="danger" %}
The removal matches by role ID alone. It does not check the `BUSINESS_RULE_ASSIGNMENT` tag, and it does not check which rule wrote the membership — so it will take `CRM User` away from someone who was granted it through an approved request. Before arming it, enumerate every other path to that role. Immediately after saving, press **Preview impacted users**: the entries are the users the rule would now change, which — the grant population having just been swept — is the set holding the role without qualifying for it. That is the set the rule will strip. If it is not what you expected, untick **Active** on `CRM User revoke` and save; an inactive target is skipped with *"Target CRM User revoke is inactive, ignore"*. There is a real exposure window between saving and reviewing, because any user saved in between is evaluated against the live rule.
{% endhint %}

Verify by changing the test user's job code again: the explanation should now report *"The REMOVE\_ROLE action has been performed with the following results: DELETE with Id=…"*, and the CRM account should change.
{% endstep %}
{% endstepper %}

**To reverse it.** Untick **Active** on `CRM User revoke` first, then set the rule Inactive. In that order the rule stops acting and nobody loses anything. In the other order the rule is stored as *Pending deactivation* with the revoke group still armed, and the next recalculation strips the role from every user the rule ever matched. To unwind the grants deliberately, that is exactly the sequence you want — but choose it, do not arrive at it.

## Worked example 2: two attributes, and access that must survive

*Finance-US permanent staff get the reporting group. Some people outside that population were approved for it individually, and must not lose it when their department or employee type changes.*

This is the example people get wrong, and it goes wrong in two independent ways: the conditions are combined loosely, and the exception holders are destroyed by the rule's own no-match target.

The construction that works keeps **one** rule authoritative for the group, and puts the exception inside the condition so that exception holders keep matching:

|                           |                                                                                                                                                                                                                                             |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Objects**               | The group `Finance Reporting Readers`; the role `Finance Reporting Exception`, requestable through the catalog with its own approval; one action group to add the group, one to remove it; the rule                                         |
| **Condition**             | A **Group 'OR'** with two children: a **Group 'AND'** of **Organizations** *Any match* Finance-US and **Employee type ID** *Equals* `PERM FULL TIME`; and an **Expression** of **Roles** *Any match* the `Finance Reporting Exception` role |
| **On match**              | **Add user to group**, value = the group ID                                                                                                                                                                                                 |
| **On no match**           | **Remove user from group**, same group ID                                                                                                                                                                                                   |
| **Granting an exception** | Request the `Finance Reporting Exception` role. The holder now matches the rule, so the group follows automatically                                                                                                                         |
| **Withdrawing one**       | Remove that role. The next save fails the condition and the group is removed                                                                                                                                                                |

Five things decide whether this works.

**Nest the AND inside the OR, and read the tree back before saving.** Three expressions in one flat `OR` grants the group to everyone in Finance-US whatever their employee type, and to every permanent employee in the company. Rule validation only checks that an `AND` or `OR` has at least two children — *"An Or/And condition must have at least two child conditions"* — it has no opinion about your intent. The explanation names the branch that decided the outcome: *"Because of ('ROLES' ANY\_MATCH '…') returns 'true' for OR operation, expression is TRUE"*.

**Both values are IDs, and one of them does not look like its label.** Among the shipped employee types the entry displayed as **PERMANENT FULL TIME** stores `PERM FULL TIME`, and the one displayed as **CONTRACTOR** stores `CONTRACTOR TYPE`. Pick from the drop-down; never transcribe.

**Use&#x20;*****Any match*****, not&#x20;*****Equals*****, for organizations and roles.** They are collections. *Equals* on a collection cannot be evaluated at all, and an unevaluable condition resolves to `false`, which runs the no-match target — so the wrong operator here does not fail safe, it revokes.

**Express the exception as a role, not as a user attribute.** A flag would work in principle, but the current Business Rules screen writes a **User attributes** condition as an unquoted pair while the engine requires the literal quoted form `"name":"value"`, and a rejected condition makes the **whole rule** unevaluable rather than just that branch: the rule resolves to `false` for everybody and the no-match target strips the group from the entire population. A role uses a picker, appears on the user's entitlements screen, is requestable and can be certified. See [Two condition forms the current screen writes incorrectly](/administration-guide/access/business-rules/business-rule-reference.md#two-condition-forms-the-current-screen-writes-incorrectly).

**An expired exception still counts.** The collection comparison looks only at the IDs the user holds and ignores start and end dates; the add and remove actions do honour dates. An exception role that expired last month therefore still satisfies the condition and keeps the group. If exceptions must be time-bound, remove the role rather than end-dating it, and certify the exception role on its own schedule.

**Testing it takes six users, not one.** Pin the rule to a single employee ID as in example 1 and work through them in turn, reading the explanation each time: matches the AND branch only; matches the exception branch only; matches both; matches neither; holds the exception and then loses it; and — the one everybody forgets — a user moved into a *child* department of Finance-US. That last user does not match on the save that moves them, because the inherited parent affiliation is written after the rules have run. They match from their next save.

**To reverse it.** Same order as example 1: no-match action group inactive first, then the rule. Withdrawing a single exception never needs the rule touched at all — remove the exception role and save the user.

## The four mechanisms, and choosing between them

| Mechanism                                        | Where the grant is expressed                                                          | When it is applied                                                         | Removal                                                    |
| ------------------------------------------------ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------- |
| **Business rule** with match/no-match actions    | Action groups attached to a rule                                                      | Every user add and update, plus any recalculation someone runs             | The no-match action group, if you configured one           |
| **Universal role or group**                      | `ROLE.ASSIGN_TO_ALL` / `GRP.ASSIGN_TO_ALL` = `Y`                                      | Every Add and Update                                                       | Untick the flag — but existing memberships are not removed |
| **Provision all users with this managed system** | `MANAGED_SYS.ASSIGN_TO_ALL` = `Y`                                                     | Every Add and Update                                                       | Untick the flag — existing identities remain               |
| **Organization-driven**                          | A role, group or resource entitled *to the organization*, plus the user's affiliation | Whenever the affiliation changes and the authorization graph is recomputed | Change the affiliation                                     |

### Universal assignment: `ASSIGN_TO_ALL`

One flag, three tables, one behaviour. On **every** user add and every user update, before the diff is built, OpenIAM runs three searches:

| It looks for    | Matching                                  | And then                                     |
| --------------- | ----------------------------------------- | -------------------------------------------- |
| Groups          | Status `ACTIVE`, **Assign to all** ticked | Adds each one the user does not already have |
| Roles           | Status `ACTIVE`, **Assign to all** ticked | Adds each one the user does not already have |
| Managed systems | Active, **Assign to all** ticked          | See below                                    |

The managed-system branch is the one with a wrinkle. For a user who **already exists**, OpenIAM looks for that user's login on each universal managed system and associates the system's resource **only if there is no login yet** — so an existing account is not re-provisioned by the flag alone. For a user being created, every universal managed system's resource is associated unconditionally.

This pass runs **after** the business rules have been evaluated, on every add and every update. That ordering is the reason a rule and a universal assignment must never both own the same object: the rule's removal survives the save that made it, and the universal assignment puts the object back on the following one.

Three consequences:

* **Inactive objects are exempt.** An `ASSIGN_TO_ALL` role with `STATUS` other than `ACTIVE` is not assigned. Deactivating the role is therefore a faster brake than unticking the flag on a large population, because it takes effect on the next save either way.
* **Every user update re-asserts it.** Removing a universal role from one person by hand lasts until their next save. There is no per-user exception mechanism. If you need exceptions, this is the wrong mechanism — use a business rule with a condition.
* **Unticking the flag does not remove anything.** The membership rows already written stay. Plan the cleanup as a separate, deliberate bulk operation: flipping the flag across many roles or groups is one bulk operation, and removing the memberships is a different one. See [Change many users at once](/administration-guide/identities/bulk-operations.md).

`MANAGED_SYS.ASSIGN_TO_ALL` is the widest of the three because it associates a *managed system* — an account in a real target — on every user save. The guide's [blast-radius table](/administration-guide/start/change-safely.md#changes-with-a-wide-blast-radius) lists it for that reason.

### Business rules

**Business rules** are the precise, conditional mechanism, and the one to reach for by default. The screens, the condition model and every action's exact blast radius are [Build a business rule](/administration-guide/access/business-rules.md) and [Business rule reference](/administration-guide/access/business-rules/business-rule-reference.md).

A rule has a **type** — `PROVISIONING` or `SELF_REGISTRATION` — a **status**, a condition tree, and up to two action groups. The birthright-relevant actions, by the label the drop-down shows and the value stored:

| Action                                                                                                             | Effect                                                                                                                                                    | Use for                                                                                                                                                                                                     |
| ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADD_ROLE`, `ADD_GROUP`, `ADD_RESOURCE`, `ADD_ORG`                                                                 | Grant one named entitlement                                                                                                                               | The match branch of a birthright rule                                                                                                                                                                       |
| `REMOVE_ROLE`, `REMOVE_GROUP`, `REMOVE_RESOURCE`, `REMOVE_ORG`                                                     | Revoke one named entitlement                                                                                                                              | The no-match branch                                                                                                                                                                                         |
| `ADD_ATTRIBUTE`, `REMOVE_ATTRIBUTE`                                                                                | **Nothing.** Both are selectable and neither is implemented — they report *"Could not perform action with type ADD\_ATTRIBUTE"* every time the group runs | Nothing. Use a `GROOVY` action to stamp an attribute                                                                                                                                                        |
| `ENABLE`, `DISABLE`, `ACTIVATE`, `DEACTIVATE`, `LOCK`                                                              | Change user or account state                                                                                                                              | Status-driven lifecycle, not access                                                                                                                                                                         |
| `ADD_ROLE_ACCESS_REQUEST`, `REMOVE_ROLE_ACCESS_REQUEST`, `ADD_GROUP_ACCESS_REQUEST`, `REMOVE_GROUP_ACCESS_REQUEST` | Raise an **access request** rather than granting directly                                                                                                 | Access that must be approved even though the rule identified it                                                                                                                                             |
| `GROOVY`                                                                                                           | Run a script                                                                                                                                              | Anything the declarative actions cannot express                                                                                                                                                             |
| `END_DATE_ALL_ACCESS`, `RESTORE_ALL_ACCESS`, `PROLONG_ALL_ACCESS`, `DROP_ALL_ENTITLEMENTS`                         | Bulk end-date, clear end dates, extend by *n* days, or mark everything for deletion                                                                       | Leaver and leave-of-absence policies — read the exact scope of each in [Broad access actions](/administration-guide/access/business-rules/business-rule-reference.md#broad-access-actions) before using one |

The four request-raising actions are the mechanism most people miss: a rule can *identify* who needs privileged access and still route it through approval, rather than choosing between silent automation and manual requests.

### Organization-driven access

The fourth mechanism, and the one that needs no flag and no rule. Entitle a role, group or resource to an **organization**; users affiliated with that organization inherit it through the authorization graph. On the user's record the affiliations are the **Organizations** the user belongs to, and a synchronization transformation script sets them from an HR feed.

Use it when the population genuinely is an organizational unit and the HR feed is authoritative for it. It has two real advantages over `ASSIGN_TO_ALL`: the grant is scoped, and it moves with the person when their affiliation changes, with no rule to maintain. Its disadvantage is that the blast radius is invisible from the role — you have to look at the organization's membership to know who is affected.

### Choosing

| Situation                                                                                    | Mechanism                                                                                 |
| -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Every user in the system, no exceptions, low risk                                            | `ASSIGN_TO_ALL` on a role or group                                                        |
| Every user needs an account in one target                                                    | `MANAGED_SYS.ASSIGN_TO_ALL` — and only if that is genuinely true                          |
| A condition on status, user type, organization, department, location or a governed attribute | Business rule, `ADD_ROLE` / `ADD_GROUP`, with a paired removal action                     |
| The rule can identify who needs it but a human must approve                                  | Business rule, `ADD_ROLE_ACCESS_REQUEST`                                                  |
| The population is an organizational unit and HR owns it                                      | Entitle the organization                                                                  |
| Optional, exceptional, high-risk, time-bound, or needing justification                       | Not birthright. [The request catalog](/administration-guide/requests/request-catalog.md). |

Never express one grant through two mechanisms. Removal through one leaves the other still asserting it, and the next save re-provisions.

## What evaluates a birthright rule, and when

Two things evaluate a rule, and only two.

**Every user save.** On every add and every update, OpenIAM evaluates every rule whose status is `ACTIVE` or `ON_MODIFY` — *Pending modifications* — against the user being saved, before the provisioning diff is built. This is the path that gives a joiner their access on day one, and it is immediate: from the moment a rule is saved as Active, the very next save of any user anywhere is evaluated against it.

**A recalculation, when someone runs one.** A recalculation pages the entire user base 50 at a time, evaluates the **pending** rules against each user, and for anyone whose access changes performs a real provisioning save reaching every managed system they are entitled to. It then settles the pending statuses: `ON_MODIFY` becomes `ACTIVE`, `ON_DEACTIVATE` becomes `INACTIVE`, and *Pending deletion* rules are deleted. Audit action `BUSINESS_RULE_RECALCULATE`.

The deliberate path is two buttons on **Access Control → Business Rules → Out of sync users**. **Preview impacted users** evaluates the pending rules across the whole population and records one entry per affected user without changing anything; **Provision impacted users** performs the same evaluation for real. Both act on **every** pending rule on the system, not only yours, both take a cluster-wide lock, and neither is available for a rule that is `INACTIVE` or already settled to `ACTIVE` — the preview is not a dry run of a rule you have not committed to. Check who else has a rule in a pending status before you press either.

Per-user evidence: when rules run during a provisioning operation, the filtered explanation is attached to the audit event as `BUSINESS_RULE_EXPLANATION`, keeping only the rules that matched or performed an action. That is the only record of what the rules decided for one user, and its **absence** on an otherwise successful operation means the rules did not run at all.

And the fail-open path, repeated here because it hits birthright hardest: with no consumer on the business-rule evaluation queue, OpenIAM logs `Business Rule Service is not run. Skip Business Rule processing` at **warn** in the service log and carries on. Provisioning continues and the account is created with none of its birthright access. See [Configure provisioning](/administration-guide/lifecycle/configure-provisioning.md#the-three-fail-open-paths).

## The other half: losing it when they leave

A birthright rule takes access away when someone stops matching, and that covers transfers. It does not cover the leaver, because a leaver usually stops matching only when somebody edits their record.

The mechanism that does cover it ships **enabled** and is easy to overlook: batch task `LEAVER_PROCESS`, *Disable by last date*, cron `0 0 17 * * ?`. It is a thin wrapper around a Groovy script you own, and its window comes from **Parameter 1** on the task row — **an empty Parameter 1 selects nobody**, so the task runs every evening, searches an empty range, finds nothing and reports success. Building it, with a complete script that guards service accounts and users who are already gone, is [Disable leavers automatically on their end date](/administration-guide/lifecycle/disable-leavers-automatically.md).

Disabling a user is not the same as unwinding their entitlements. Decide separately whether the leaver also needs their memberships removed or end-dated, and by what — see [Advanced lifecycle patterns](/administration-guide/lifecycle/advanced-lifecycle-patterns.md).

## What removing a birthright rule does, and does not, undo

Retiring the mechanism is not the same as retiring the access, and the difference is where most of the mess comes from.

| What you do                                    | What happens to the rule                                                                     | What happens to access already granted                                                                                           |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Untick **Active** on the grant action group    | Still evaluated; the match branch does nothing                                               | Untouched. Nobody gains, nobody loses                                                                                            |
| Untick **Active** on the no-match action group | Still evaluated; the no-match branch does nothing, and says *"Target … is inactive, ignore"* | Untouched                                                                                                                        |
| Set a live rule Inactive                       | Stored as *Pending deactivation*. It stops being evaluated on user saves immediately         | **Nothing yet** — and then the no-match target runs across the whole population at the next recalculation, if it is still active |
| Delete a rule with no active no-match group    | Deleted immediately, audit `BUSINESS_RULE_DELETE`                                            | Untouched. Every membership stays exactly as it is                                                                               |
| Delete a rule with an active no-match group    | Stored as *Pending deletion*; the rule survives until a recalculation runs                   | Removed from every user the rule matched, at that recalculation                                                                  |
| Untick `ASSIGN_TO_ALL`                         | The flag stops applying on future saves                                                      | Untouched. Existing memberships stay                                                                                             |
| Deactivate a universal role or group           | Excluded from the universal pass on future saves                                             | Untouched                                                                                                                        |

Two things no path above undoes. **Memberships already written stay** unless something explicitly removes them; a rule that no longer exists cannot take back what it granted. And **nothing reaches the managed system by itself** — the target account changes only when a provisioning operation runs for that user, so a membership removed by a recalculation and a membership removed by a database edit are not the same event.

The one thing that is genuinely irreversible is the no-match sweep. Once a recalculation has run a **Remove user from role** across a population, the memberships are gone, the target accounts have been deprovisioned, and the only record of who held what is the audit trail and the preview results you kept. Keep them.

## Verification

* **The rule.** `BUSINESS_RULE_SAVE`, `BUSINESS_RULE_TARGET_SAVE`, `BUSINESS_RULE_ACTION_SAVE`; deletes are `BUSINESS_RULE_DELETE`, `BUSINESS_RULE_TARGET_DELETE`, `BUSINESS_RULE_ACTION_DELETE`.
* **The population.** The **Out of sync users** tab after **Preview impacted users** — one entry per affected user, with the full explanation behind **View details**.
* **The recalculation.** `BUSINESS_RULE_RECALCULATE`, and afterwards the rule's Status column reading **Active** rather than *Pending modifications*.
* **Per-user.** `BUSINESS_RULE_EXPLANATION` on the provisioning event. The lines to look for are `<ATTRIBUTE>: '<actual>' <OPERATION> '<expected>' == <result>.` for each condition, and *"The ADD\_ROLE action has been performed with the following results: ADD with Id=…"* for each action.
* **Which mechanism granted it.** The membership tag on the user's role or group row: `BUSINESS_RULE_ASSIGNMENT` means a rule wrote it. No tag means a request, a synchronization, an administrator or a universal assignment did.
* **Universal assignment.** `SELECT ROLE_ID, ROLE_NAME, STATUS FROM ROLE WHERE ASSIGN_TO_ALL = 'Y'`, the same for `GRP`, and `SELECT MANAGED_SYS_ID, NAME, IS_ACTIVE FROM MANAGED_SYS WHERE ASSIGN_TO_ALL = 'Y'`. Three short lists that should contain nothing you did not intend.
* **The far end.** The entitlement in OpenIAM, then the connector reply, then the account in the target.

## When it goes wrong

These are the birthright-specific failures. Everything about conditions, operators, statuses and the recalculation lifecycle is in [Build a business rule](/administration-guide/access/business-rules.md#when-it-goes-wrong).

| Symptom                                                | Cause                                                                                                   | Fix                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Too many users matched                                 | The condition is broader than intended, or an OR where you meant AND                                    | Untick **Active** on the no-match action group, **then** set the rule Inactive — that order does not unwind anything. Record the **Out of sync users** entries as evidence before they are cleared by the next preview, then edit. Remove unintended assignments through the same governed path. |
| Account created with no birthright access at all       | Business-rule service fail-open                                                                         | Restore consumers on the evaluation queue; grep for `Business Rule Service is not run`.                                                                                                                                                                                                          |
| An exception holder keeps losing access                | The no-match target removes by entity ID and cannot tell an exception from an error                     | Put the exception inside the condition, as an ORed **Roles** *Any match* branch — worked example 2.                                                                                                                                                                                              |
| User still entitled after they stop matching           | No no-match action configured, or the access also comes from another role, a request or `ASSIGN_TO_ALL` | Enumerate every path to the resource before concluding the rule is broken.                                                                                                                                                                                                                       |
| A hand-removed universal role comes back               | The universal pass runs on every save and re-adds anything the user does not already hold               | `ASSIGN_TO_ALL` has no exception mechanism. Convert to a business rule with a condition.                                                                                                                                                                                                         |
| Unticking `ASSIGN_TO_ALL` left everyone still a member | The flag governs assignment, not existing membership                                                    | Bulk-remove deliberately, after estimating the deprovisioning impact.                                                                                                                                                                                                                            |
| `ASSIGN_TO_ALL` role appears not to apply              | Its `STATUS` is not `ACTIVE` — the search filters on it                                                 | Activate it, or accept that deactivation is the brake.                                                                                                                                                                                                                                           |

## Related

* [Build a business rule](/administration-guide/access/business-rules.md) — the screens, the condition model and three more worked rules
* [Business rule reference](/administration-guide/access/business-rules/business-rule-reference.md) — every condition attribute, operator and action, with its exact scope
* [Disable leavers automatically on their end date](/administration-guide/lifecycle/disable-leavers-automatically.md) — `LEAVER_PROCESS` and a complete leaver script
* [Decommission a managed system](/administration-guide/lifecycle/decommission-a-managed-system.md) — retiring the integration that carried the access
* [Configure a managed system](/administration-guide/lifecycle/configure-managed-system.md) — `ASSIGN_TO_ALL`, `ON_DELETE` and the downstream reference
* [Change many users at once](/administration-guide/identities/bulk-operations.md) — cleaning up memberships a flag left behind
* [Shipped batch tasks](/administration-guide/reference/shipped-batch-tasks.md) — `PERFORM_BR_REPROVISION`, `LEAVER_PROCESS` and the rest

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/lifecycle/birthright-access.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
