> 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/solution-architecture/identity/authoritative-sources.md).

# Choosing your authoritative sources

Decide which systems are allowed to assert that a person exists, has changed or has left — one HR system or several, what happens when two sources disagree, and who owns the populations HR does not.

## What this is, and when you need it

An **authoritative source** is a system whose word OpenIAM takes as fact: it may create a person, change a person, and — the part that matters most — say that a person has left. This page is about deciding which systems get that authority, for which populations, and for which fields. It is the first design decision in a programme and the one most often assumed rather than made.

You need it when the organization has more than one HR system, when a sizeable population is not in HR at all, or when a directory has been quietly acting as the source of truth for years because nothing else was. All three are normal in a large estate, and none of them is a reason to defer the decision.

## The decision

| Option                                                   | What it costs                                                                                                           | What it buys                                                                                                      |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **One HR system for the whole workforce**                | Everyone not in HR — contractors, service accounts, partners — needs another answer, and you will need one anyway       | The simplest possible model: one joiner event, one leaver event, one place to argue with                          |
| **Several HR feeds, one per organization or region**     | A written precedence rule, and a correlation key that is genuinely the same value in all of them                        | Survives acquisitions and regional payroll without pretending they are one system                                 |
| **HR for employees, a contractor register for the rest** | A second system somebody has to own and keep current, and a defined handover when a contractor becomes an employee      | Coverage of the population that causes most of the orphan accounts and most of the missed leavers                 |
| **A directory as the authoritative source**              | The directory records the *consequence* of a decision, not the decision; it usually cannot say why or when someone left | Fast to stand up when no HR feed is available. Treat it as an interim position, not a design                      |
| **A person register you build**                          | Real work, and a system of record you now operate                                                                       | The only workable answer when three or four HR systems each cover part of the workforce and none covers all of it |

Most large estates end up with the second or third row, and a number of them arrive at the fifth.

## What OpenIAM can read, and how

A source reaches OpenIAM as a **synchronization** — a configured feed with its own schedule, its own matching rule and its own transformation. Five source types exist: a delimited file, a relational database query, anything a connector can read from a managed system, a custom Groovy adapter, and a log adapter used for diagnostics. In practice an HR feed is a file or a database query; a directory feed is a connector.

Two things follow that shape the design. **Every feed is independent.** There is no ordering between synchronizations, no shared transaction and no notion of one feed waiting for another. Two feeds scheduled five minutes apart against overlapping populations will interleave, and if both assert the same field, the later run wins until the next run of the other one. **Every feed asserts on every run.** A synchronization does not compute a delta against the last run's assertions; it applies whatever its transformation sets, every time.

OpenIAM also exposes a SCIM 2.0 service-provider interface for users and groups, so a source can push instead of being pulled. That path goes through provisioning rather than through a synchronization, which means it has no matching rule, no transformation script and no run report — a different set of trade-offs, and rarely the right one for a workforce feed.

## Precedence is a decision you write down, not a setting you enable

This is the single most important thing on this page and the thing most designs get wrong.

**This release does not provide a field-precedence engine.** There is no ranking of sources, no "this source may not overwrite that one", and no per-field authority table to configure. Precedence is therefore something the design establishes rather than something the product enforces, and it is established by giving every attribute a single owning source: authority is carried entirely by what each feed's transformation chooses to assert. A source that does not own a field must not set it — and "must not set it" means the field is absent from the transformation's output, which is different from setting it empty. Setting it empty is a decision to clear it.

So the artefact that makes two sources cooperate is a **field authority matrix**, approved before either feed runs, naming for every OpenIAM field which single source owns it and where the answer is "no assertion at all". The Administration Guide's *Import from two authoritative sources without overwriting* sets out how that matrix is then enforced in the feed's scripts. Design the matrix here; enforce it there.

Three rules keep a matrix honest:

**One owner per field, not per record.** It is normal and correct for HR to own name, manager, employment status and end date while a directory owns the account identifier and its own status. It is never workable for both to own the primary email address.

**"No assertion" and "clear the value" are different outcomes.** A source that omits a field leaves the current value alone. A source that asserts an empty value erases it. A great many "the HR feed wiped everyone's mobile number" incidents are this distinction, discovered late.

**The leaver assertion is the one to be strict about.** If two systems can both say a person has left, one of them will say it wrongly — a contractor record closed at the end of a purchase order, an HR record that lags a transfer by a week. Name exactly one source per population that may trigger the leaver lifecycle, and make every other source's departure signal informational.

## When HR is not authoritative for contractors

This is the common case, not the exception, and it deserves a design rather than a workaround. Contractors are frequently invisible to payroll, appear in a procurement or vendor-management system with a purchase-order end date rather than an employment end date, or exist only because a manager asked for an account.

| Situation                                       | The design that works                                                                                                                                                                                 |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A contractor register exists and is current     | Treat it as a second authoritative source for that population, with its own feed, its own end-date field and its own leaver authority                                                                 |
| A contractor register exists and is not current | Feed it anyway, but drive expiry from a mandatory end date held in OpenIAM and re-confirmed by the sponsoring manager, not from the register's status                                                 |
| No register exists                              | Create the contractor in OpenIAM through a sponsored request with a mandatory end date and a named internal sponsor. OpenIAM becomes the source of record for that population, and you have to say so |

Whichever applies, **a non-employee identity with no end date is the defect to design against**. It is the mechanism by which contractor accounts outlive contracts, and it is why the contractor population produces most of an estate's orphan accounts. Make the end date mandatory at creation, make extending it an explicit act with an approver, and expire on the date rather than on a status change somewhere else.

The transition — the contractor who becomes an employee — is a lifecycle event and belongs to [Designing for every population](/solution-architecture/identity/populations.md). What belongs here is the authority consequence: on the day of conversion, authority for that person moves from one source to another, and both feeds will see them for a period. If the contractor feed is still asserting a termination date it read before the conversion, it will terminate a new employee. Decide, in the matrix, how a source is told to stop asserting on a person it no longer owns.

## Two sources describing the same person

When two feeds legitimately cover the same people — an HR system and a directory, two HR systems after an acquisition — three things have to be true before either runs:

1. **Both carry the same correlation value**, or a governed crosswalk exists that turns one into the other. See [Identity correlation: choosing a matching key](/solution-architecture/identity/correlation-key.md).
2. **The field authority matrix is approved**, and each feed's transformation has been narrowed to it.
3. **Exactly one of them owns the leaver event** for each population.

If any of the three is unresolved, run one feed and hold the other. Two feeds asserting freely against the same people is the fastest way to produce a data-quality problem that looks like a product defect.

## What we recommend

**Start from the population, not from the system.** List every population that needs an identity — employees, contractors, seasonal, partners, customers, service accounts, machine identities — and name the authoritative source for each. Populations with no named source are the design's real scope, and they are what the programme will actually spend its time on.

**Prefer one HR feed per organization over one merged feed.** Merging two HR extracts upstream to produce a single file hides which system asserted what, and makes precedence impossible to enforce or to audit. Two feeds with an approved authority matrix is more configuration and considerably less risk.

**Do not let a directory be the long-term authoritative source for people.** A directory tells you an account exists; it rarely tells you a person was hired, transferred or terminated, and it cannot tell you about a person who has no account. Where a directory is currently the de facto source, treat that as an interim position with a date on it.

**Give every non-employee identity a mandatory end date, owned by a named sponsor.** This single rule removes more risk than any other decision on this page.

The circumstance that changes this advice is an organization with a genuinely complete, current HR system covering every worker type including contractors. Where that exists, take it: one source, one leaver event, one argument.

## What OpenIAM does not do here

* **This release has no source-precedence or field-authority configuration.** No ranking, no per-field owner, no conflict resolution. Two feeds that both assert a field will take turns overwriting it, and both runs are reported as successful.
* **There is no ordering or dependency between synchronizations.** You cannot declare that the contractor feed runs only after the HR feed has completed; you schedule them and they run.
* **A synchronization does not diff against its own previous assertions.** It re-applies whatever the transformation produces on every run, so removing a field from a source does not clear it in OpenIAM, and re-adding a stale value re-asserts it.
* **There is no built-in identity crosswalk object.** Where two sources use different identifiers, the translation lives in a custom matching rule or in a user attribute you populate — not in a product feature.
* **OpenIAM does not validate that a feed is complete.** A truncated extract that arrives with a tenth of the expected rows is processed as a valid run. Completeness checking belongs to the feed's owner and to the schedule around it.

## Related

* [Identity correlation: choosing a matching key](/solution-architecture/identity/correlation-key.md) — what the feeds you have just chosen will be matched on.
* [Designing for every population](/solution-architecture/identity/populations.md) — the populations that need a source, and the transitions between them.
* *Import from two authoritative sources without overwriting* in the Administration Guide — how a field authority matrix is enforced in a feed's scripts.
* *Set up a synchronization* and *How a synchronization matches and processes a record* in the Administration Guide — the mechanics this page's decisions are implemented with.

*Applies to OpenIAM 2026.8.1. Last reviewed 13 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/solution-architecture/identity/authoritative-sources.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.
