> 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/reference/sod-rules-and-rule-sets.md).

# SoD rule and policy reference

Every value, field and table behind SoD policies and rule sets — the five enums, the rule JSON schema, the ten shipped catalogues, what activation creates, and the twenty violation-report fields.

## What this is, and when you need it

The exhaustive lists behind the SoD screens: the enumerated values each field accepts, how an entitlement reference in a rule resolves against your access model, the full `RULES_JSON` schema with a complete shipped rule, the ten shipped catalogues with their real slugs and counts, the tables that store all of it, and the twenty fields the violation report can carry.

Scan this page; do not read it. What an SoD policy is and why you need one is [SoD policies and rule sets](/administration-guide/governance/sod/sod-policies-and-rule-sets.md). Building a policy is [Create an SoD policy](/administration-guide/governance/sod/sod-policies-and-rule-sets/create-an-sod-policy.md); turning a catalogue into policies is [Activate an SoD rule set](/administration-guide/governance/sod/sod-policies-and-rule-sets/activate-an-sod-rule-set.md).

## The values you will meet

| Where you meet it                                                           | Values                                                                            |
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| **Severity** on a policy (`SOD_POLICY.SEVERITY`), and as a report filter    | `SOFT`, `HARD`                                                                    |
| `riskLevel` in rule JSON, which becomes the `SOD_RISK_*` tag                | `CRITICAL`, `HIGH`, `MEDIUM`                                                      |
| A rule set's status (`SOD_RULE_SET.STATUS`), and the `mode` you activate in | `INACTIVE`, `SHADOW`, `ENFORCED`                                                  |
| `type` on each entitlement reference in rule JSON                           | `ROLE`, `GROUP`, `RESOURCE`, `ORGANIZATION`, `ENTITLEMENT`                        |
| The outcome shown against each reference in the activation preview          | `MATCHED`, `WILL_CREATE`, `AMBIGUOUS`, `NEEDS_MANUAL`                             |
| Where a rule set came from (`SOD_RULE_SET.SOURCE`)                          | `OPENIAM_OTB`, `CUSTOM_UPLOAD`, `CUSTOM_BUILT`                                    |
| `ENTITLEMENT_TYPE` on an exemption (`SOD_EXEMPTION`)                        | `ROLE`, `GROUP`, `RESOURCE`, `ORGANIZATION`                                       |
| `REVIEW_FREQUENCY` on a mitigating control                                  | `ANNUALLY`, `SEMI_ANNUALLY`, `QUARTERLY`, `MONTHLY`                               |
| `REGION` on a rule set, in the catalogue filter                             | `US`, `EU`, `INDIA`, `CUSTOM` — content ships only for `US` and `EU`              |
| `VERTICAL` on a rule set                                                    | `MANUFACTURING`, `HR_PAYROLL`, `FINANCIAL_SERVICES`, `PLANT_MAINTENANCE`, `BASIS` |

`OPENIAM_OTB` content is read-only and OpenIAM refuses to save an edit to it, so the check is simply that the save fails; export, edit and re-import as `CUSTOM_UPLOAD` instead.

Declarations for all of these are in [Enumerated values](/administration-guide/reference/enums.md).

### The three risk classifications

Three `METADATA_TYPE` rows in the `SOD_RISK` grouping, seeded as of 2026.7.1.0 with display names localized into twelve languages. Confirm all three exist on **Administration → Metadata Types** with **Grouping** filtered to `SOD_RISK` — a missing row means no rule set can be activated with that classification.

| `TYPE_ID`           | `NAME`   | Rule `riskLevel` it maps from | Severity at activation | Exceptions allowed |
| ------------------- | -------- | ----------------------------- | ---------------------- | ------------------ |
| `SOD_RISK_CRITICAL` | Critical | `CRITICAL`                    | `HARD`                 | no                 |
| `SOD_RISK_HIGH`     | High     | `HIGH`                        | `SOFT`                 | yes                |
| `SOD_RISK_MEDIUM`   | Medium   | `MEDIUM`                      | `SOFT`                 | yes                |

The tag is stored on `SOD_POLICY.RISK`, a foreign key to `METADATA_TYPE`. Activation derives it from the rule's `riskLevel` by prefixing `SOD_RISK_`, and reads it back the same way, so the two names are always one transformation apart and you can match a policy to its rule by eye. This grouping is **separate** from the `RISK` grouping that [risk scoring](/administration-guide/risk/factors.md#factor-entitlement-sensitivity) uses for entitlement sensitivity — same word, different values, no interaction.

## How an entitlement reference resolves

Each entitlement reference in a rule carries a `type` and a `name`. Matching is **by name, case-insensitively**, and scoped hard to the managed system you choose as the activation target: only candidates whose managed system *is* that target are considered. A same-named role in another managed system — **or with no managed system at all** — is not a match, and a duplicate is created in the target instead.

{% hint style="warning" %}
**A generic `ENTITLEMENT` reference resolves against exactly one object type, not both.** That type is the create-as type you choose in the activation dialog, which defaults to `ROLE`. A generic reference matches only roles, or only groups — never roles and groups together.

So if your entitlements are OpenIAM **groups** and you leave the create-as type at its `ROLE` default, nothing matches and everything is created. Run the activation preview once as `ROLE` and once as `GROUP` and compare the *will be created* counts: the type that matches your estate is the one that stops proposing new objects. The preview is non-destructive.
{% endhint %}

Per-reference outcome, as shown in the preview:

| Outcome        | Preview label | Meaning                                                                                                         |
| -------------- | ------------- | --------------------------------------------------------------------------------------------------------------- |
| `MATCHED`      | Matched       | An existing entitlement of the referenced type matched by name                                                  |
| `WILL_CREATE`  | Will create   | Activation will create the entitlement                                                                          |
| `AMBIGUOUS`    | Ambiguous     | Several candidates matched and the first is used                                                                |
| `NEEDS_MANUAL` | Needs manual  | An `ORGANIZATION` reference; organizations are never auto-created, so the reference is dropped from the segment |

What each outcome asks of you before you confirm is on [Activate an SoD rule set](/administration-guide/governance/sod/sod-policies-and-rule-sets/activate-an-sod-rule-set.md#read-the-preview-like-a-mapping-sheet).

Per-rule verdict, also in the preview:

| Verdict       | Preview label      | Meaning                                                                                                                                                   |
| ------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREATE`      | Will create policy | No policy exists for this rule key                                                                                                                        |
| `SKIP_EXISTS` | Already activated  | An active policy already exists for the rule key                                                                                                          |
| `REACTIVATE`  | —                  | The rule's existing inactive policy will be re-enabled, for example after a set deactivation. Counted separately from created policies in the result line |

### What activation creates

When a reference resolves `WILL_CREATE`:

| Created as           | `NAME`                                   | `DESCRIPTION`                                         | Type                                                                                                                            | Managed system                         |
| -------------------- | ---------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| `ROLE` (the default) | the reference `name`, for example `FK01` | the `displayName`, for example `Create vendor (FK01)` | `METADATA_TYPE` from `org.openiam.sod.ruleset.role.type`, default **`ACCESS_ROLE`**                                             | the activation target                  |
| `GROUP`              | as above                                 | as above                                              | `METADATA_TYPE` from `org.openiam.sod.ruleset.group.type`, default **`GENERAL_GROUP`**                                          | the activation target                  |
| `RESOURCE`           | as above                                 | `COORELATED_NAME` = `displayName` or `name`           | `RESOURCE_TYPE` from `org.openiam.sod.ruleset.resource.type`, default **`SOD_ENTITLEMENT`**, which has shipped since 2026.7.1.0 | —                                      |
| `ORGANIZATION`       | —                                        | —                                                     | —                                                                                                                               | never created; resolves `NEEDS_MANUAL` |

All three type properties carry built-in defaults and have no `SYS_PROP` row, so they are not on **Administration → System Configuration** and can only be overridden in the deployment's property layer. You cannot read their live values from the Webconsole; what you *can* see is the metadata type on an entitlement activation created, which tells you the effective value after the fact.

Created roles and groups are saved `ACTIVE` and indexed immediately, so a later connector reconciliation can match them **by name** — which is the intended path to turning a created `FK01` role into a real one.

## The rule JSON schema

`SOD_RULE_SET.RULES_JSON` is what you need to author a rule set offline, and the shape is not visible anywhere in the UI. It nests four levels — the set, its rules, each rule's segments, and each segment's entitlement references — and **any field OpenIAM does not recognise is silently discarded on import**, with no warning and no rejected-field list. Export what you imported and compare it against your source file; anything missing was dropped.

| Field                                           | Type                   | Notes                                                                                                                                |
| ----------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `schemaVersion`                                 | int                    | Current version is **1**. Every shipped rule set declares `1`                                                                        |
| `rules[]`                                       | array                  | The rules                                                                                                                            |
| `rules[].ruleKey`                               | string                 | Stable human id, unique within the set. Shipped format `MFG-FI-001`. Unique with the set in `SOD_POLICY (SOD_RULE_SET_ID, RULE_KEY)` |
| `rules[].name`                                  | string                 | The generated policy is named `[ruleKey] name`                                                                                       |
| `rules[].description`                           | string                 | Why the combination is a conflict                                                                                                    |
| `rules[].riskLevel`                             | string                 | `CRITICAL` / `HIGH` / `MEDIUM`. Drives severity and the `SOD_RISK_*` tag                                                             |
| `rules[].module`                                | string                 | Domain tag (SAP module for SAP content), snapshot-copied to `SOD_POLICY.MODULE`                                                      |
| `rules[].controlObjective`                      | string                 | Audit-language control statement, copied to `CONTROL_OBJECTIVE`                                                                      |
| `rules[].businessRisk`                          | string                 | Copied to `BUSINESS_RISK`                                                                                                            |
| `rules[].remediation`                           | string                 | Copied to `REMEDIATION`                                                                                                              |
| `rules[].policyThreshold`                       | int                    | Segments that must be violated, becoming `SOD_POLICY.POLICY_THRESHOLD`                                                               |
| `rules[].severity`                              | `SOFT`, `HARD` or null | Explicit override honoured at activation only, never on `Enforce`. Null in all shipped rules                                         |
| `rules[].incomplete`                            | boolean                | Summary-only rule with no entitlements; skipped at activation. False in all shipped rules                                            |
| `rules[].segments[].name`                       | string                 | Copied to the created `SOD_POLICY_SEGMENT.NAME`                                                                                      |
| `rules[].segments[].threshold`                  | int                    | Defaults to `1`, becoming `SEGMENT_THRESHOLD`                                                                                        |
| `rules[].segments[].entitlements[].type`        | string                 | One of `ROLE`, `GROUP`, `RESOURCE`, `ORGANIZATION`, `ENTITLEMENT`                                                                    |
| `rules[].segments[].entitlements[].name`        | string                 | Match key, compared case-insensitively against existing entitlement names                                                            |
| `rules[].segments[].entitlements[].displayName` | string                 | Used as the name if the entitlement must be created                                                                                  |

A rule is skipped at activation when `incomplete` is true, `ruleKey` is blank, `segments` is empty, or every segment has no entitlements. Skipped rules produce no policy and no error, so compare the activation preview's rule count against the count in your file.

{% hint style="info" %}
The shipped catalogue also carries an `authObjects` array on each rule — the SAP authorization objects behind the conflict. OpenIAM has no field for it and discards it on import, along with any other unrecognised field. It is reference content in the seeded JSON, not something the product stores or shows, and it will not survive an export-edit-import round trip. If you need those authorization objects retained, carry them in `description` or `controlObjective`.
{% endhint %}

### A complete rule

`MFG-FI-001`, quoted verbatim from `openiam:mfg-us` v1.1.0 and pretty-printed:

{% code overflow="wrap" lineNumbers="true" expandable="true" %}

```json
{
  "schemaVersion": 1,
  "rules": [
    {
      "ruleKey": "MFG-FI-001",
      "name": "Create vendor master + Execute payment run",
      "description": "A user with access to both create or modify vendor master records and execute the automatic payment run can introduce a fictitious or modified vendor and approve payment to that vendor without any independent authorisation.",
      "riskLevel": "CRITICAL",
      "module": "FI",
      "controlObjective": "SOX ITGC AC-3: Segregation of duties over payment processing — no individual should be able to both create the payee and authorise the payment. PCAOB auditors test this control as part of the procure-to-pay cycle assessment under AS 2201.",
      "businessRisk": "Manufacturing and distribution companies process significant volumes of supplier payments. A user with this conflict could create a fictitious vendor and divert payments. This is the most common procurement fraud vector in SAP environments and is the first conflict tested by PCAOB auditors under AS 2201.",
      "remediation": "Split roles: remove F110 access from users who have FK01/FK02. Where operational constraints require both, implement compensating control: mandatory dual approval on all payment runs with documented second-person review retained as audit evidence.",
      "authObjects": ["F_LFA1_BUK", "F_LFA1_GRP", "F_BKPF_BUK"],
      "policyThreshold": 2,
      "severity": null,
      "segments": [
        {
          "name": "Create vendor master",
          "threshold": 1,
          "entitlements": [
            { "type": "ENTITLEMENT", "name": "FK01", "displayName": "Create vendor (FK01)" },
            { "type": "ENTITLEMENT", "name": "FK02", "displayName": "Change vendor (FK02)" }
          ]
        },
        {
          "name": "Execute payment run",
          "threshold": 1,
          "entitlements": [
            { "type": "ENTITLEMENT", "name": "F110", "displayName": "Automatic payment run (F110)" }
          ]
        }
      ]
    }
  ]
}
```

{% endcode %}

Read it as the control it is: two segments, each satisfied by holding **any one** of its entitlements (`threshold: 1`), and a `policyThreshold` of 2 meaning both sides must be held. `riskLevel: CRITICAL` and `severity: null` together mean this becomes a `HARD` policy tagged `SOD_RISK_CRITICAL` with exceptions off on `Enforce` — and a `SOFT` one in Shadow.

### The CSV import columns

The CSV format is built for exactly the two-segment conflict the shipped content uses. Its columns are `ruleKey,name,module,riskLevel,segmentAName,segmentACodes,segmentBName,segmentBCodes,controlObjective,businessRisk,remediation`. Codes are pipe-separated, `policyThreshold` is set to the number of segments and each segment threshold to 1. A code may carry a `ROLE:`, `GROUP:`, `RESOURCE:` or `ORGANIZATION:` prefix — `ROLE:SAP_AP_CLERK` — and an unprefixed code becomes a generic `ENTITLEMENT` reference. More than two segments needs the JSON or XML format.

The import also accepts SAP GRC's own column names as aliases: `ruleId`, `ruleName`, `risk`, `functionAName`, `functionATCodes`, `functionBName` and `functionBTCodes` all map onto the native columns, so a GRC function-conflict export can be uploaded with minimal reshaping. Custom rule keys follow the same convention as the shipped ones — `CUS-FI-001`: letters, digits, `-` or `_`.

## The ten shipped rule sets

Ten `SOD_RULE_SET` rows, all `SOURCE = 'OPENIAM_OTB'`, all `STATUS = 'INACTIVE'`, all `RULES_JSON` at `schemaVersion` **1**, addressed by `EXTERNAL_KEY` so seed upgrades can find and update them. All ten shipped in 2026.7.1.0; a content update in the same release replaced the two Manufacturing sets' rules and raised their `VERSION` to `1.1.0`. The **Rule Set Catalog** screen shows each set's version, which is where you confirm what your deployment actually has.

| `EXTERNAL_KEY`            | `ID`                    | Name                               | Version   | Rules | Modules (rules each)                 | Critical / High / Medium |
| ------------------------- | ----------------------- | ---------------------------------- | --------- | ----- | ------------------------------------ | ------------------------ |
| `openiam:mfg-us`          | `SOD_RULE_SET_MFG_US`   | Manufacturing Edition — US         | **1.1.0** | 45    | FI 10, MM 10, SD 8, PP 7, CO 6, QM 4 | 15 / 20 / 10             |
| `openiam:mfg-eu`          | `SOD_RULE_SET_MFG_EU`   | Manufacturing Edition — EU         | **1.1.0** | 45    | FI 10, MM 10, SD 8, PP 7, CO 6, QM 4 | 15 / 20 / 10             |
| `openiam:hr-payroll-us`   | `SOD_RULE_SET_HR_US`    | HR & Payroll — US                  | 1.0.0     | 30    | HR 30                                | 10 / 13 / 7              |
| `openiam:hr-payroll-eu`   | `SOD_RULE_SET_HR_EU`    | HR & Payroll — EU                  | 1.0.0     | 30    | HR 30                                | 10 / 13 / 7              |
| `openiam:fin-services-us` | `SOD_RULE_SET_FS_US`    | Financial Services — US            | 1.0.0     | 45    | FI 27, TR 11, CO 7                   | 15 / 20 / 10             |
| `openiam:fin-services-eu` | `SOD_RULE_SET_FS_EU`    | Financial Services — EU            | 1.0.0     | 45    | FI 27, TR 11, CO 7                   | 15 / 20 / 10             |
| `openiam:pm-us`           | `SOD_RULE_SET_PM_US`    | Plant Maintenance — US             | 1.0.0     | 30    | PM 30                                | 10 / 13 / 7              |
| `openiam:pm-eu`           | `SOD_RULE_SET_PM_EU`    | Plant Maintenance — EU             | 1.0.0     | 30    | PM 30                                | 10 / 13 / 7              |
| `openiam:basis-us`        | `SOD_RULE_SET_BASIS_US` | SAP Basis & Privileged Access — US | 1.0.0     | 30    | BASIS 30                             | 10 / 13 / 7              |
| `openiam:basis-eu`        | `SOD_RULE_SET_BASIS_EU` | SAP Basis & Privileged Access — EU | 1.0.0     | 30    | BASIS 30                             | 10 / 13 / 7              |

**360 rules in total, 120 of them Critical.** The regulatory frameworks each set declares in `REGULATORY_FRAMEWORKS`:

| Set                       | `REGULATORY_FRAMEWORKS`                                        |
| ------------------------- | -------------------------------------------------------------- |
| `openiam:mfg-us`          | `SOX_302,SOX_404,PCAOB_AS2201,COSO,ITGC`                       |
| `openiam:mfg-eu`          | `DORA,NIS2,COBIT_2019`                                         |
| `openiam:hr-payroll-us`   | `SOX_302,SOX_404,PCAOB_AS2201,COSO,ITGC`                       |
| `openiam:hr-payroll-eu`   | `DORA,COBIT_2019,GDPR,EU_EMPLOYMENT_LAW`                       |
| `openiam:fin-services-us` | `SOX_302,SOX_404,PCAOB_AS2201,OCC_FDIC,BASEL_III,COSO,BSA_AML` |
| `openiam:fin-services-eu` | `DORA,MIFID_II,EBA_GUIDELINES,CRR_CRD,COBIT_2019,AMLD6`        |
| `openiam:pm-us`           | `SOX_302,SOX_404,PCAOB_AS2201,COSO,ITGC`                       |
| `openiam:pm-eu`           | `DORA,NIS2,COBIT_2019,EU_MACHINERY_DIRECTIVE`                  |
| `openiam:basis-us`        | `SOX_302,SOX_404,PCAOB_AS2201,COSO,ITGC`                       |
| `openiam:basis-eu`        | `DORA,NIS2,COBIT_2019,GDPR`                                    |

The catalogue card's *Modules* chips, its rule count and its critical count are all computed when the card is read, from the `module` and `riskLevel` values inside `RULES_JSON` — they are not separately stored metadata, which is why they change when you import a modified copy of a set. The catalogue stat cards count **Rule sets**, **Active rule sets**, **Active policies** and **Active critical policies**, the last being active policies tagged `SOD_RISK_CRITICAL`.

### The shape of all 360 rules

| Property of the shipped content | Value, across all 360 rules                                                                                                                      |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Segments per rule               | **2** — always a two-sided conflict                                                                                                              |
| `segments[].threshold`          | **1** — holding any one entitlement satisfies that side                                                                                          |
| `policyThreshold`               | **2** — both sides must be held                                                                                                                  |
| `severity`                      | `null` in every rule, so severity is derived entirely from `riskLevel`                                                                           |
| Entitlement reference `type`    | `"ENTITLEMENT"` for all 1,316 references — never `ROLE`, `GROUP`, `RESOURCE` or `ORGANIZATION`                                                   |
| Total segments and references   | 720 segments, 1,316 references — per set: 172 (Manufacturing), 175 (Financial Services), 116 (Plant Maintenance), 102 (Basis), 93 (HR & Payroll) |
| Distinct transaction-code names | 262 across the catalogue: 110 per Manufacturing edition, 88 Financial Services, 57 Plant Maintenance, 47 Basis, 35 HR & Payroll                  |

The paired editions are **the same conflicts with different control narrative**. For Manufacturing, field by field: identical `ruleKey` list, identical entitlement-name set of 110 names, and all 45 `controlObjective` strings different. So the edition choice is which control language your auditor reads, not which conflicts you detect.

## Catalogue status, and the actions that change it

Three of the signals on a catalogue card are `SOD_RULE_SET.STATUS` values; the rest are derived, and each tells you something the status column cannot.

| Signal               | Meaning                                                                                                                                                                                                                                                               |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Inactive**         | `STATUS = 'INACTIVE'`. No policies have been generated from this set                                                                                                                                                                                                  |
| **Shadow**           | `STATUS = 'SHADOW'`. Policies exist, every one forced `SOFT`, violations visible and never blocking                                                                                                                                                                   |
| **Enforced**         | `STATUS = 'ENFORCED'`. Each policy's severity follows its risk classification                                                                                                                                                                                         |
| **Partial**          | Derived: some of the set's rules have policies and some do not, because an earlier activation restricted `ruleKeys`, some rules were skipped as incomplete, or a newer version added rules. A `SHADOW` set can be **Partial** and look fully adopted on the dashboard |
| **Update available** | Derived: the seeded `VERSION` is newer than `ACTIVATED_VERSION`. Run **Compare** before adopting it                                                                                                                                                                   |
| **Out of sync**      | Derived from the two hashes on `SOD_POLICY`: a rule recipe changed after its policy was generated. Editing a live policy by hand does **not** raise this — the indicator tracks recipe-to-policy drift, not policy edits                                              |

| Action                             | What it does                                                                                                                                                                                                          |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Activate selected**              | Generates policies for the confirmed rules, in `SHADOW` or `ENFORCED`                                                                                                                                                 |
| **Activate more rules**            | Turns rules left out of an earlier activation into policies, leaving the existing ones alone. This is how a **Partial** set is completed, and it is the action to reach for after adopting a version that added rules |
| **Enforce**                        | `SHADOW` → `ENFORCED`, re-deriving every policy's severity from its risk tag                                                                                                                                          |
| **Deactivate**                     | Returns the whole set to `INACTIVE` and leaves its policies inactive. Not cleanup: the policies, and any entitlements activation created, both remain                                                                 |
| **Reactivate**                     | Re-enables the policies a deactivation switched off. Re-activating in Shadow re-forces `SOFT`; re-activating in Enforced leaves each policy's severity as the administrator last had it                               |
| **Compare** / **Re-sync policies** | Diff a newer version, then reapply the current rules to the generated policies                                                                                                                                        |

## The tables

| Table                                                                          | Holds                                                 | Notable columns                                                                                                                                                                                                                           |
| ------------------------------------------------------------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SOD_POLICY`                                                                   | One policy                                            | `SEVERITY`, `POLICY_THRESHOLD` (default 1), `RISK` → `METADATA_TYPE`, `ACTIVE`, `EXCEPTIONS_ALLOWED`, `MANAGER_CAN_HANDLE_SPV`, `MANAGER_GROUP_ID` → `GRP`                                                                                |
|                                                                                | Rule-set traceability                                 | `SOD_RULE_SET_ID`, `RULE_KEY` (unique together), `MODULE` (indexed by `IDX_SOD_POLICY_MODULE`), `CONTROL_OBJECTIVE`, `BUSINESS_RISK`, `REMEDIATION` — all `VARCHAR(500)` except `MODULE` at `VARCHAR(30)` and `RULE_KEY` at `VARCHAR(30)` |
|                                                                                | Drift detection                                       | `SOURCE_RULE_HASH` (fingerprint of the rule that generated it), `GENERATED_POLICY_HASH` (fingerprint of the policy as generated)                                                                                                          |
| `SOD_POLICY_SEGMENT`                                                           | One segment                                           | `SEGMENT_THRESHOLD`, `ACTIVE`, `SOD_POLICY_ID` (`ON DELETE CASCADE`)                                                                                                                                                                      |
| `SOD_SEGMENT_ROLE` / `SOD_SEGMENT_GRP` / `SOD_SEGMENT_RES` / `SOD_SEGMENT_ORG` | Entitlements in a segment                             | `(SOD_SEGMENT_ID, <entitlement>_ID)` composite keys                                                                                                                                                                                       |
| `SOD_POLICY_ROLE` / `SOD_POLICY_GRP` / `SOD_POLICY_RES` / `SOD_POLICY_ORG`     | Pre-segment policy-level entitlement links            | Predate `SOD_POLICY_SEGMENT`                                                                                                                                                                                                              |
| `SOD_EXEMPTION`                                                                | One user exempted from one policy for one entitlement | `ENTITLEMENT_TYPE ENUM('ROLE','GROUP','RESOURCE','ORGANIZATION')`, `ENTITLEMENT_ID`, `CREATED_AT` (`DEFAULT CURRENT_TIMESTAMP`), `CREATED_BY`, `COMMENT_TEXT` (1024 characters). No expiry column                                         |
| `SOD_MITIGATING_CONTROL`                                                       | A compensating control                                | `NAME`, `DESCRIPTION`, `ACTIVE` (default `N`), `MANAGER_TYPE`/`MANAGER_ID`, `OWNER_TYPE`/`OWNER_ID`, `REVIEW_FREQUENCY`, `EFFECTIVE_DATE`, `EXPIRATION_DATE`                                                                              |
| `SOD_POLICY_MC`                                                                | Control-to-policy link                                | `(SOD_POLICY_ID, SOD_MC_ID)`                                                                                                                                                                                                              |
| `SOD_RULE_SET`                                                                 | One catalogue                                         | `SOURCE`, `REGION`, `VERTICAL`, `REGULATORY_FRAMEWORKS`, `VERSION`, `EXTERNAL_KEY` (unique), `STATUS`, `ACTIVATED_AT`, `ACTIVATED_VERSION`, `MANAGED_SYS_ID`, `RULES_JSON`                                                                |
| `SOD_DIGEST_STATE`                                                             | Digest recipients and last snapshot                   | Singleton, `ID = 'SOD_DIGEST'`: `RECIPIENTS_JSON`, `LAST_RUN`, `LAST_PAIRS_JSON`                                                                                                                                                          |

Detected violations are **not** relational. One document per violating user lives in the OpenSearch index `user-violated-sod-policy`, carrying `userId`, `login`, `name`, `timestamp` and a `sodPolicies` list whose entries hold `id`, `name`, `severity`, `managerGroupId`, `riskId`, `riskName`, `policyThreshold` and `mitigatingControlIds`. See [Search indexes and the authorization graph](/administration-guide/reference/search-indexes.md).

## The twenty violation-report fields

**Selected Fields (column order)** on the **Reports** tab offers exactly twenty fields, and at least one is required. The column order of the CSV is the order you select them in; OpenIAM then appends `SEGMENT_1` … `SEGMENT_n`, where *n* is the segment count of the **widest policy in the system**.

| Value                       | Column label                 | What it reports                                 |
| --------------------------- | ---------------------------- | ----------------------------------------------- |
| `USER_ID`                   | User ID                      | Internal user id                                |
| `USER_FIRST_NAME`           | User First Name              |                                                 |
| `USER_LAST_NAME`            | User Last Name               |                                                 |
| `USER_EMAIL`                | User Email Address           | Primary email                                   |
| `USER_EMPLOYEE_ID`          | Employee ID                  |                                                 |
| `USER_IDENTITY`             | User Identity                | Primary principal in the default managed system |
| `USER_MANAGER`              | User Manager                 |                                                 |
| `USER_ORGANIZATION`         | User Organization            |                                                 |
| `SOD_POLICY_ID`             | Policy ID                    |                                                 |
| `SOD_POLICY_NAME`           | Policy Name                  |                                                 |
| `SOD_POLICY_DESCRIPTION`    | Policy Description           |                                                 |
| `SOD_POLICY_SEVERITY`       | Policy Severity              | `SOFT` or `HARD`                                |
| `SOD_POLICY_RISK`           | Policy Risk                  | The `SOD_RISK_*` classification                 |
| `SOD_POLICY_THRESHOLD`      | Policy Threshold             | `POLICY_THRESHOLD`                              |
| `SOD_POLICY_MANAGER_GROUP`  | Policy Manager Group         |                                                 |
| `SOD_SEGMENT_MANAGER_GROUP` | Policy Segment Manager Group |                                                 |
| `SOD_SEGMENT_DESCRIPTION`   | Policy Segment Description   | Per-segment description                         |
| `SOD_MITIGATING_CONTROL`    | Mitigating Control(s)        | The linked compensating controls                |
| `USER_IS_MC_MANAGER`        | Is User an MC Manager?       | Whether the violating user manages that control |
| `USER_IS_MC_OWNER`          | Is User an MC Owner?         | Whether the violating user owns it              |

The last three are the ones an auditor asks for: the compensating control, and whether the person in violation is the one operating it. Select all three together or the answer is not evidence.

Fields are not free. OpenIAM resolves a value only when its field was selected — the user's primary login is looked up only if `USER_IDENTITY` is in the list, and the policy is read in full only for `SOD_POLICY_DESCRIPTION`, `SOD_POLICY_MANAGER_GROUP` or `SOD_POLICY_RISK`. Selecting everything on a large population costs real time, which you will notice as a report that takes minutes rather than seconds to appear in the list.

Each `SEGMENT_n` cell holds the segment name in brackets, then a `DIRECT[...]` line and an `INDIRECT[...]` line naming the entitlements that triggered it, each prefixed by its type — `ROLE`, `GROUP`, `RESOURCE` or `ORGANIZATION`.

## Related

* [SoD policies and rule sets](/administration-guide/governance/sod/sod-policies-and-rule-sets.md) — what these objects are for, and the enforcement ladder
* [Create an SoD policy](/administration-guide/governance/sod/sod-policies-and-rule-sets/create-an-sod-policy.md) — building one by hand
* [Activate an SoD rule set](/administration-guide/governance/sod/sod-policies-and-rule-sets/activate-an-sod-rule-set.md) — turning a catalogue into policies
* [SAP role and SoD analysis](/administration-guide/governance/sod/sap-sod-analysis.md) — what the shipped SAP content does and does not analyse
* [Enumerated values](/administration-guide/reference/enums.md) — every SoD enum with its declaration

*Applies to OpenIAM 2026.8.1. Last reviewed 3 September 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/reference/sod-rules-and-rule-sets.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.
